Inline LaTeX equations in shiny app with MathJax
Asked Answered
S

4

11

A solution to display LaTeX equations in line is offered here with a working live demo

The above mentioned solution to display equations in line is (cutting a few lines of code):

ui.R:

library(shiny)

shinyUI(fluidPage(
  title = 'MathJax Examples with in-line equations',
  withMathJax(),
  # section below allows in-line LaTeX via $ in mathjax. Replace less-than-sign with < 
  # and grater-than-sign with >
  tags$div(HTML("less-than-sign script type='text/x-mathjax-config' greater-than-sign
                MathJax.Hub.Config({
                tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
                });
                less-than-sign /script greater-than-sign
                ")),
  helpText('An irrational number $\\sqrt{2}$
           and a fraction $1-\\frac{1}{2}$'),
  helpText('and a fact about $\\pi$:$\\frac2\\pi = \\frac{\\sqrt2}2 \\cdot
           \\frac{\\sqrt{2+\\sqrt2}}2 \\cdot
           \\frac{\\sqrt{2+\\sqrt{2+\\sqrt2}}}2 \\cdots$'),
  uiOutput('ex1')
  ))

server.R:

shinyServer(function(input, output, session) {
  output$ex1 <- renderUI({
    withMathJax(helpText('Dynamic output 1:  $\\alpha^2$'))
  })
})

I am running R version 3.5.2 on macOS, and shiny 1.2. The app output is some verbatim text instead of the expected blend of text and inline equations:

less-than-sign script type='text/x-mathjax-config' greater-than-sign MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$'], ['′,′
']]} }); less-than-sign /script greater-than-sign
and a fact about $\pi$:$\frac2\pi = \frac{\sqrt2}2 \cdot \frac{\sqrt{2+\sqrt2}}2 \cdot \frac{\sqrt{2+\sqrt{2+\sqrt2}}}2 \cdots$
Dynamic output 1: $\alpha^2$

Can it be because of my R environment?

Swop answered 26/2, 2019 at 0:20 Comment(2)
Does your code still contain "less-than-sign" and "greater-than-sign"? Those should be replace with "<" and ">" as stated in the comment. Showing it like that was probably just a way to get around some escaping behaviour when posting it to the blog or something.Becki
@Becki Good point. I have replaced those but it's still not working.Swop
O
6

An alternative way, using KaTeX instead of MathJax:

library(shiny)

ui <- fluidPage(
  tags$head(
    tags$link(rel="stylesheet", 
              href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css", 
              integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ",
              crossorigin="anonymous"),
    HTML('<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js" integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij" crossorigin="anonymous"></script>'),
    HTML('<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"></script>'),
    HTML('
    <script>
      document.addEventListener("DOMContentLoaded", function(){
        renderMathInElement(document.body, {
          delimiters: [{left: "$", right: "$", display: false}]
        });
      })
    </script>')
  ),
  titlePanel("Hello Shiny!"),
  helpText('An irrational number $\\sqrt{2}$
           and a fraction $1-\\frac{1}{2}$'),
  helpText('and a fact about $\\pi$:$\\frac2\\pi = \\frac{\\sqrt2}2 \\cdot
           \\frac{\\sqrt{2+\\sqrt2}}2 \\cdot
           \\frac{\\sqrt{2+\\sqrt{2+\\sqrt2}}}2 \\cdots$'),
  uiOutput('ex1')
)

server <- function(input, output) {

  output$ex1 <- renderUI({
    tagList(
      helpText('Dynamic output 1: $\\alpha^2$'),
      tags$script('renderMathInElement(document.getElementById("ex1"), {delimiters: [{left: "$", right: "$", display: false}]});')
    )
  })  

}

enter image description here

Ovenbird answered 26/2, 2019 at 9:26 Comment(3)
KaTeX does the job!Swop
This works, but note that you will have to add another $ to any equations you don't want in-line: withMathJax("$$$ \\mathequation$$$")Enalda
Is there any concern that the src will change, rendering this solution useless in the future?Enalda
L
4

Making the MathJax script work

The < script> tag needs to be <script> and < /script > needs to be </script >:

tags$div(HTML("<script type='text/x-mathjax-config' >
            MathJax.Hub.Config({
            tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
            });
            </script >
            "))

Fixing the math delimiter

However, the preceding code (following the code in the question) uses parentheses as math delimiters, which is a really bad idea. To use the more common \(...\), you need to escape characters with more backslashes:

tags$div(HTML("<script type='text/x-mathjax-config' >
            MathJax.Hub.Config({
            tex2jax: {inlineMath: [['$','$'], ['\\\\(','\\\\)']]}
            });
            </script >
            "))

When writing an inline equation, the backslash again needs to be escaped: p("The equation \\(x=2\\) is inline.")

Leesen answered 18/9, 2019 at 18:36 Comment(4)
This has unintended consequences for text inside parentheses (including non-math characters).Enalda
Can you elaborate? What consequences? Do you mean that removing the space causes a problem, that using ( to indicate math causes a problem, or something else?Leesen
All text within parentheses (outside equations) become nested within a box (if special characters are included, such as # or &) or written as math text (if no characters are included). It does this throughout the entire shiny app, which is not ideal.Enalda
The code in the original question uses parentheses as a delimiter for math, and this answer preserved that (probably undesirable) behavior. I have updated the answer to instead use \( as a delimiter.Leesen
E
0

Long answer:

The KaTeX solution (https://mcmap.net/q/1001918/-inline-latex-equations-in-shiny-app-with-mathjax) is great, but it doesn't allow summation symbols to look as they should.

p(withMathJax("$$$ \\sum_{i=2}^{10} $$$")

Results in: enter image description here

Instead of: enter image description here

@randy's solution (https://mcmap.net/q/1001918/-inline-latex-equations-in-shiny-app-with-mathjax; from the MathJax docs: https://docs.mathjax.org/en/v2.7-latest/options/preprocessors/tex2jax.html), does allow the summation math above to look correct, however, it has the unintended side effect of altering all text that is inside parentheses.

For example, this code:

p("this is a (test) paragraph to show (what #happens)"),

renders as:

enter image description here

For some reason having symbols within the parentheses leads to text being inside a box, and otherwise appearing as math text. This isn't ideal if you are hoping to use parentheticals elsewhere in your Shiny App (perhaps as references, etc.).

To fix this, you only have to remove (from randy's answer) , ['\\(','\\)'], which is the second delimiter listed (which isn't necessary).


Short answer:

    tags$div(HTML("<script type='text/x-mathjax-config' >
    MathJax.Hub.Config({
    tex2jax: {inlineMath: [['$','$']]}
    });
    </script >
    ")),

Session Info

> sessionInfo()
R version 4.3.0 (2023-04-21 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)

Matrix products: default


locale:
[1] LC_COLLATE=English_United States.utf8  LC_CTYPE=English_United States.utf8    LC_MONETARY=English_United States.utf8 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.utf8    

time zone: America/Los_Angeles
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] extraDistr_1.9.1 scales_1.2.1     plyr_1.8.8       ggplot2_3.4.3    shiny_1.7.4.1   

loaded via a namespace (and not attached):
 [1] Matrix_1.5-4        jsonlite_1.8.7      gtable_0.3.3        crayon_1.5.2        dplyr_1.1.3         compiler_4.3.0      promises_1.2.0.1   
 [8] tidyselect_1.2.0    Rcpp_1.0.11         sourcetools_0.1.7-1 later_1.3.1         jquerylib_0.1.4     splines_4.3.0       fastmap_1.1.1      
[15] lattice_0.21-8      mime_0.12           R6_2.5.1            labeling_0.4.2      generics_0.1.3      tibble_3.2.1        munsell_0.5.0      
[22] bslib_0.5.0         pillar_1.9.0        rlang_1.1.1         utf8_1.2.3          cachem_1.0.8        httpuv_1.6.11       sass_0.4.7         
[29] memoise_2.0.1       cli_3.6.1           mgcv_1.8-42         withr_2.5.0         magrittr_2.0.3      digest_0.6.33       grid_4.3.0         
[36] fontawesome_0.5.1   rstudioapi_0.15.0   xtable_1.8-4        nlme_3.1-162        lifecycle_1.0.3     vctrs_0.6.3         glue_1.6.2         
[43] farver_2.1.1        rsconnect_1.1.0     fansi_1.0.4         colorspace_2.1-0    tools_4.3.0         pkgconfig_2.0.3     ellipsis_0.3.2     
[50] htmltools_0.5.5 
Enalda answered 17/10, 2023 at 21:48 Comment(0)
A
0

The example for inline LaTeX equations linked by OP is a bit long in the tooth (posted in 2015). Here is another solution that uses renderUI:

output$descr <- renderUI(withMathJax(
    "The Poisson PMF is:
    $$\\mathrm{Pr}_{\\lambda}(x) = \\frac{\\lambda^x e^{-\\lambda}}{x!}$$
    where \\(\\lambda\\) is its sole parameter."))

The $$ delimiters render the LaTeX formula in "display mode". The \( ... \) pair indicates "inline mode". The example above renders \lambda inline (as λ ).

The backlashes need to be doubled ("leaning toothpick syndrome") due to the way R processes them.

Alejoa answered 24/1, 2024 at 15:8 Comment(1)
The "display mode" math works for me, but the inline code does not. It produces "where (\lambda) is its sole parameter." Removing the extra "\" produces an error in the app.Enalda

© 2022 - 2025 — McMap. All rights reserved.