wilkelab / ggtext

Improved text rendering support for ggplot2
https://wilkelab.org/ggtext/
GNU General Public License v2.0
655 stars 37 forks source link

Feature request: Inject LaTeX math into Markdown text by wrapping in $$, like R Markdown #4

Open mattwarkentin opened 5 years ago

mattwarkentin commented 5 years ago

Hi,

This package is great and will undoubtedly save lots of people lots of headaches. I am wondering if you would be able to add additional support to be able to inject LaTeX math into the text for plots. I did notice you have shown an example of using HTML tags to do things like superscripts and subscripts, however, I think many users will be more familiar with writing more complex equations using LaTeX.

I really have no idea of the difficulty in adding this feature, but it would be great to use some sort of system like R Markdown uses, where it seems to parse the $$ and renders all text inside as LaTeX math. This would certainly be an amazing feature, in my eyes.

Something like:

iris %>%
  ggplot(aes(Sepal.Length, Sepal.Width)) +
  geom_point() +
  geom_smooth(method = 'lm') +
  labs(title = "The line in this plot represents $\hat{y}=\beta_0+\beta_1x_1$")

Thank you for your work.

clauswilke commented 5 years ago

I agree it's a useful feature, but it's a lot of work. (Essentially, somebody would have to re-implement large parts of the TeX rendering engine in R grid.) So don't get your hopes up for this to be coming soon or ever.

mattwarkentin commented 5 years ago

Thanks for the reply. I suspected this would be a non-trivial feature. In any case, I am very thankful for your hard work and I am excited to use this package!

baptiste commented 4 years ago

Rather than re-implementing a TeX-like engine I think one could potentially leverage a javascript-based one such as KaTeX – with the existing R-js interpreters/bridges it might in fact be quite doable.

https://katex.org/docs/api.html#server-side-rendering-or-rendering-to-a-string

clauswilke commented 4 years ago

@baptiste Thanks for the pointer. How feasible this is depends on what kind of html tags it generates. Would you be in a position to provide example R code that goes from an input latex expression to output html? (E.g., the equivalent of katex.renderToString() but wrapped into R.)

baptiste commented 4 years ago

Not likely – too many things on.

mattwarkentin commented 4 years ago

Hi @clauswilke,

So I felt some obligation to try and attempt this since I started the issue; but I didn't think I had the javascript knowledge to be able to do it. I did some reading and here's my first attempt. I have tried to satisfy your request of getting the output HTML using katex.renderToString() from inside R. This attempt is quite crude, since it is simply running javascript code inside of R, but it is a starting point. If this is even remotely on the right track for what you were hoping to see, I could wrap this into a more palatable R function.

Here goes:

  1. Install katex in working directory

    npm install katex
  2. Followed this vignette to bundle the katex library into a stand-alone Javascript file:

    
    npm install -g browserify

echo "global.katex = require('katex');" > in.js browserify in.js -o bundle.js


3. In `R` (with `V8` package installed):
```r
library(V8)
ct <- v8()
ct$source(file = "/Users/Matt/bundle.js")

ct$eval(
'var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", {
    throwOnError: false
});')

ct$get('html')

And here is the resulting HTML string:

<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>c</mi><mo>=</mo><mi>p</mi><mi>m</mi><mi>s</mi><mi>q</mi><mi>r</mi><mi>t</mi><mrow><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup></mrow></mrow><annotation encoding=\"application/x-tex\">c = pmsqrt{a^2 + b^2}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathdefault\">c</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.008548em;vertical-align:-0.19444em;\"></span><span class=\"mord mathdefault\">p</span><span class=\"mord mathdefault\">m</span><span class=\"mord mathdefault\">s</span><span class=\"mord mathdefault\" style=\"margin-right:0.03588em;\">q</span><span class=\"mord mathdefault\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathdefault\">t</span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathdefault\">a</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222222222222222em;\"></span><span class=\"mord\"><span class=\"mord mathdefault\">b</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141079999999999em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span></span>
clauswilke commented 4 years ago

Thanks! This will definitely require more CSS support than I currently have implemented in gridtext, so we'll have to defer for now.

mattwarkentin commented 4 years ago

Alright, sounds good. Please let me know if there is anything else I can do to help down the line.

baptiste commented 4 years ago

@coolbutuseless might rendering this be easy in minisvg? Much like tikzGraphics can bypass the grDevices bottleneck, here one could perhaps leverage native mathml–xml support (noting that web technologies are increasingly becoming the most relevant graphics output)

coolbutuseless commented 4 years ago

@baptiste I think it could be possible. Could you file an issue on coolbutuseless/devoutsvg and link to here?

zmeers commented 4 years ago

Hi all,

I was searching for this feature in ggtext, but I understand it might take a while to set up or it's not a priority for the package devs. In the meantime, I've been working with latex2exp instead. While it's not as intuitive as the request posed above, primarily because you need to wrap the text arg in latex2exp::TeX("$\alpha$") - e.g. ggplot() + geom_text(aes(label = latex2exp::TeX("$\\alpha$") )), it does what we want. See the vignette here: https://cran.r-project.org/web/packages/latex2exp/vignettes/using-latex2exp.html.

Hope this helps if people are looking for another way to input latex into ggtext!

wdkrnls commented 4 years ago

Paul Murrell's dvir package also seems relevant to mention here: https://www.stat.auckland.ac.nz/~paul/Reports/dvir/intro/dvir.html https://www.stat.auckland.ac.nz/~paul/Reports/dvir/luatex/dvir-luatex.html

mattwarkentin commented 3 years ago

Perhaps the new katex package will be useful if/when ggtext/gridtext supports more HTML tags.