react-native-htmlview icon indicating copy to clipboard operation
react-native-htmlview copied to clipboard

<sup> and <sub> tag not working

Open minhajul-islam opened this issue 3 years ago • 3 comments

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

minhajul-islam avatar Nov 28 '21 10:11 minhajul-islam

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?

sampie777 avatar Dec 09 '21 08:12 sampie777

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.

sampie777 avatar Dec 09 '21 09:12 sampie777

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

vegerot12 avatar Jul 19 '23 15:07 vegerot12