react-native-render-html icon indicating copy to clipboard operation
react-native-render-html copied to clipboard

customHTMLElementModels not working with 'math' tags

Open arnabbit opened this issue 2 years ago • 11 comments

Decision Table

  • [X] My issue does not look like “The HTML attribute 'xxx' is ignored” (unless we claim support for it)
  • [X] My issue does not look like “The HTML element <yyy> is not rendered”

Good Faith Declaration

  • [X] I have read the HELP document here: https://git.io/JBi6R
  • [X] I have read the CONTRIBUTING document here: https://git.io/JJ0Pg
  • [X] I have confirmed that this bug has not been reported yet

Description

I wish to render my html content which contains 'math' tags along with a bunch of other tags. My html content for example looks like <p> <p>This is outta the park</p> <math xmlns="http://www.w3.org/1998/Math/MathML"><msqrt><mn>2</mn><mfrac bevelled="true"><mn>4</mn><mn>7</mn></mfrac></msqrt><mo>+</mo><mfrac><mn>5</mn><mn>8</mn></mfrac></math> <- this is just a math string <span>Please look above the problem is with the above math tags!</span> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam. </p> </p>

and i have defined my customHTMLElementModels as follows

const customHTMLElementModels = { math: defaultHTMLElementModels.math.extend({ contentModel: HTMLContentModel.block }) };

and my component's render function looks like the following:
<HTML width = { width} source={{html :customSource}} tagsStyles={SoltagsStyles} customHTMLElementModels={customHTMLElementModels} />

for which the output comes as such image

As you can see, the math equation doesn't render.

I also tried using Custom Rendering using components. using MathJax from react-native-mathjax but same output

React Native Information

System:
    OS: Windows 10 10.0.22621
    CPU: (8) x64 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
    Memory: 9.06 GB / 23.77 GB
  Binaries:
    Node: 18.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: Not Found
    npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
    Watchman: Not Found
  SDKs:
    Android SDK: Not Found
    Windows SDK: Not Found
  IDEs:
    Android Studio: Version     2020.3.0.0 AI-203.7717.56.2031.7678000
    Visual Studio: Not Found
  Languages:
    Java: 20.0.1
  npmPackages:
    @react-native-community/cli: Not Found
    react: >=16.8.0 => 17.0.2
    react-native: 0.68.2 => 0.68.2
    react-native-windows: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

RNRH Version

6.3.4

Tested Platforms

  • [X] Android
  • [ ] iOS
  • [ ] Web
  • [ ] MacOS
  • [ ] Windows

Reproduction Platforms

  • [X] Android
  • [ ] iOS
  • [ ] Web
  • [ ] MacOS
  • [ ] Windows

Minimal, Reproducible Example

https://snack.expo.dev/@arnab_bit/mathtagparsing

Additional Notes

No response

arnabbit avatar Jun 20 '23 10:06 arnabbit

@BenzterBit It is actually working but since you're extending the default model, the opaque flag is set: https://github.com/native-html/core/blob/4c37d2915feb8c071d060b08d54f5ef5fd9c9afc/packages/transient-render-engine/src/model/defaultHTMLElementModels.ts#L614C1-L619

Instead, extend the div model if you want something similar to div. On the other hand, the opaque flag means it won't render inner nodes (so tnode.children will be empty), but you still have access to the dom node. To do this, use the tnode.domNode prop and you'll be able to use a recursive renderer to render all descendants.

jsamr avatar Jun 20 '23 12:06 jsamr

@jsamr From what i am able to understand of what you are saying is that since the opaque flag is set, i won't be able to render the children and say using the other approach of custom rendering using renderers, I have to recursively render all the tags inside of mathml using MathJax individually? Also its too much to ask, but if you could provide a snack, which renders the html content above, that would make my doubts much clearer

arnabbit avatar Jun 21 '23 06:06 arnabbit

@BenzterBit Yes, clearly there are two approaches:

  1. Define non-opaque custom models and renderers for each MathML tag.
  2. Define an opaque custom model for the math tag, and provide a custom renderer. This custom renderer can either use tnode.domNode; which is an object from htmlparser2 library (refer to this lib documentation to walk the tree); or transform the domNode to an HTML string with domNodeToHTMLString and use a third-party library to render it.

I'm sorry as I don't have much time to provide a snack.

jsamr avatar Jun 21 '23 12:06 jsamr

@jsamr I tried the second approach. I did what you said, and now atleast i can see the mathjax or some of it, that i am wiritng. But still it can't render the tags like say . For eg. for equation n/100 *x it will print n100 *x.

It could've been due to me not specifying isOpaque: false, so i did it for each tag supported by mathml and rendered it through MathJax but even that didn't help, it gave the same 'n100 * x'

Can you tell me how to proceed from here? So that i can render the entire equation

arnabbit avatar Jun 24 '23 14:06 arnabbit

@BenzterBit If you could provide snacks with the two approaches I'd be happy to help.

jsamr avatar Jun 24 '23 16:06 jsamr

@jsamr sure, please check the following 2 snacks

  1. where i have defined a custom model to render all the supported math tags via mathjax https://snack.expo.dev/@arnab_bit/allmathmltagsrenderers

  2. where i have only defined a custom model for the 'math' tag specifically and tried to render it via mathjax https://snack.expo.dev/@arnab_bit/singlemathtagcustommodelrenderer

arnabbit avatar Jun 29 '23 11:06 arnabbit

@jsamr also the rendered elements above are in a new line, can you tell me how to make them inline with the rest of the content

arnabbit avatar Jun 29 '23 13:06 arnabbit

@BenzterBit Inlining may or may not work because it basically relies on embedding View into Text, which support has been inconsistent and ill-specified in RN, but this may have changed recently with Fabric which I haven't worked with yet.

To force inlining, you can use HTMLContentModel.textual or HTMLContentModel.mixed in your models. I suggest to first try to see if you can achieve the desired outcome with vanilla React Native + MathJax, and if you manage it, try to tweak these models.

jsamr avatar Jul 03 '23 14:07 jsamr

@jsamr couldn't do it through Mathjax, i converted the mathml incoming which is used a custom renderer using rnrh and converted it to latex using a library mathml-to-latex npm library. I used HTMLContentModel.textual and it did inline though, the styling is a bit off, which i am still figuring, if you do have any ideas on that. I will let you know after a few more tries

arnabbit avatar Jul 12 '23 09:07 arnabbit

@BenzterBit hi! could you share your changes with the rest of us? I think what you are trying to solve is in my usecase, it would be helpul to see a bit of code. We may have a common ground in what we are trying to do :)

ihojmanb avatar Jul 18 '23 23:07 ihojmanb

Thank @BenzterBit for the snack example, I also found a solution seems good for you @ihojmanb, I hope it is useful:

https://medium.com/@nutanbhogendrasharma/how-to-implement-latex-in-react-native-mobile-app-6433a7726954

tranminhnhat1005 avatar Mar 29 '24 07:03 tranminhnhat1005