jsdf/react-native-htmlview

<sup> and <sub> tag not working

minhajul-islam opened this issue · 3 comments

Ca2+ আয়ন সনাক্তকরণ
Na2SO4 এর বৈশিষ্ট

Yeah, to clarify this to make it a better issue:

<sup> and <sub> tags aren't doing anything except for printing out raw text. So they basically work like a <span>. However, the tags can be somewhat limited styled. So to achieve the <sub> effect, just apply a styling with a smaller fontSize, like so:

<HTMLView stylesheet={
  sub: {
    fontSize: defaultFontSize * 0.6,
  }
} />

But you cannot do the same for <sup>, as you cannot align the <Text> component inside another <Text> component. So none of these styles will work to achieve a <sup> effect:

sup: {
  fontSize: defaultFontSize * 0.6,
  textAlignVertical: "top", // nope
  top: -20, // nope
  lineHeight: 30, // nope
},

So basically, it seems like the only option is to wrap the rendered <Text> component inside a <View> component for subscript/superscript cases, so we can adjust their relative position. Instead of everyone building their own custom renderer, maybe this can be included in the source code?

This seems to work for me:

const MyComponent: React.FC = () => {

  const renderNode = (
    node: HTMLViewNode & { children: any },
    index: number,
    siblings: HTMLViewNode,
    parent: HTMLViewNode,
    defaultRenderer: (node: HTMLViewNode, parent: HTMLViewNode) => ReactNode): ReactNode | undefined => {

    if (node.name === "sup") {
      return <View key={index}>
        {defaultRenderer(node.children, node)}
      </View>;
    }

    return undefined;
  };

  return (<HTMLView value={""}
                    renderNode={renderNode}
                    stylesheet={{
                      p: {
                        fontSize: 20
                      },
                      sup: {
                        fontSize: 13
                      },
                      sub: {
                        fontSize: 13
                      }
                    }} />);
};

As suggested in my previous, I just wrap the <sup> children inside a <View> element to do the positioning using a custom renderer. I did not need to add any positioning styling, like top: -10 or something, as the children were automatically aligned to the top.

If this works for others as well, I can create a pull request to implement this into the source code. Please let me know.

Hope this helps others.

This seems to work for me:

const MyComponent: React.FC = () => {

  const renderNode = (
    node: HTMLViewNode & { children: any },
    index: number,
    siblings: HTMLViewNode,
    parent: HTMLViewNode,
    defaultRenderer: (node: HTMLViewNode, parent: HTMLViewNode) => ReactNode): ReactNode | undefined => {

    if (node.name === "sup") {
      return <View key={index}>
        {defaultRenderer(node.children, node)}
      </View>;
    }

    return undefined;
  };

  return (<HTMLView value={""}
                    renderNode={renderNode}
                    stylesheet={{
                      p: {
                        fontSize: 20
                      },
                      sup: {
                        fontSize: 13
                      },
                      sub: {
                        fontSize: 13
                      }
                    }} />);
};

As suggested in my previous, I just wrap the <sup> children inside a <View> element to do the positioning using a custom renderer. I did not need to add any positioning styling, like top: -10 or something, as the children were automatically aligned to the top.

If this works for others as well, I can create a pull request to implement this into the source code. Please let me know.

Hope this helps others.

Is this working on android as well as iOS ? I tried something similar and android is not working as expected