How to get \bm{} to work in an R markdown (to HTML) file?

后端 未结 4 2020
误落风尘
误落风尘 2021-02-08 00:42

My R Markdown (.Rmd) file looks like this:

---
title: Foo
author: Marius Hofert
header-includes:
    - \\usepackage{bm}
output:
    pdf_document
vignette: >
          


        
相关标签:
4条回答
  • 2021-02-08 01:19

    A third solution works well if you are using Mathjax to render equations in your html docs. Mathjax is on by default in pandoc in RStudio. This has the advantage of no flickering and works in $$ $$ and the equation environment. The big downside to this is that pandoc strips \ref{} out of the html so you have to add a knit hook to change to \ref{}. Surely there is a way to tell pandoc not to do this, but I couldn't find it. I tried many different pandoc args with no success.

    This example assumes you want equation numbers and you want to crossref those in your text. It also assumes you are knitting from RStudio. Probably works otherwise, but that is what I tested in.

    mathjax.js --- define the macros here and tell Mathjax to add eqn #s

    <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
    </script>
    <script type="text/x-mathjax-config"> 
      MathJax.Hub.Config({ 
        TeX: { 
          equationNumbers: {autoNumber: "all"},
          Macros: {
            AA: "{\\bf A}",
            BB: "{\\bf B}"
          }
        } 
      });
    </script>
    

    defs.tex --- this is for pdf_document

    \def\AA{\bf A}
    \def\BB{\bf B}
    

    test.Rmd --- now we can make Rmd docs that work with html and pdf. I could not figure out how to tell pandoc not to strip LaTeX commands out of the html. So passed in a knit hook to double \ the \ref{} calls.

    ---
    title: "Test"
    knit: ( function(inputFile, encoding) { if(rmarkdown::all_output_formats(inputFile)[1]=="html_document"){ f <- inputFile; x <- readLines(f); y <- gsub("[\\]ref[{]","\\\\\\\\ref{", x); cat(y,file="tmp.Rmd", sep="\n"); rmarkdown::render("tmp.Rmd", encoding = encoding ) }else{ rmarkdown::render(inputFile, encoding = encoding ) } })
    output: 
      html_document:
        includes:
          before_body: [../tex/mathjax.html]
      pdf_document: 
        includes: 
          before_body: ../tex/defs2.tex
    ---
    
    ```{r mss-setup, include=FALSE, purl=FALSE}
    knitr::opts_knit$set(unnamed.chunk.label = "tvarss-")
    ```
    
    In the pdf, this will not have a number but in the html it will.
    
    $$
    \AA^\top\BB
    $$
    You can use nonumber if you need the equation numbering to be the same in html and pdf.
    
    $$
    \AA^\top\BB\nonumber
    $$
    
    If we want to crossref an equation, use equation environment.  
    \begin{equation}
    \AA^\top\BB
    \label{eqn1}\end{equation}
    This is Equation \ref{eqn1}.
    

    Here is the knit function:

    ( function(inputFile, encoding) { if(rmarkdown::all_output_formats(inputFile)[1]=="html_document"){ f <- inputFile; x <- readLines(f); y <- gsub("[\]ref[{]","\\\\ref{", x); cat(y,file="tmp.Rmd", sep="\n"); rmarkdown::render("tmp.Rmd", encoding = encoding ) }else{ rmarkdown::render(inputFile, encoding = encoding ) } })

    0 讨论(0)
  • 2021-02-08 01:20

    I think your \[ \] and \begin{align} ... \end{align} are redundant. When I ran it as written above I got

    ! Package amsmath Error: Erroneous nesting of equation structures; (amsmath) trying to recover with `aligned'.

    See the amsmath package documentation for explanation. Type H for immediate help. ...

    l.84 \end{align}

    Worked fine for me when I deleted \begin{align} ... \end{align} ...

    (It seems that a similar issue arose in your previous question too ...)

    (Perhaps you were getting errors that you didn't notice and were accidentally looking at a previously compiled version?)


    As far as why you don't get the right HTML output: I'm pretty certain that MathJax (the engine used to render LaTeX embedded in Rmarkdown-produced HTML) doesn't know about \boldmath; adding the package to your LaTeX input won't help, you'll have to use \mathbf and \boldsymbol instead. You can play around here to see what works and what doesn't: entering

    $\bm X \boldmath X \boldsymbol X \mathbf X$
    

    at that web page gives

    Bottom line, if you want fancy math rendered properly, you're probably better off sticking to PDF output.

    0 讨论(0)
  • 2021-02-08 01:36

    Another solution is to use the child chunk argument. The downside, which is kind of major, is that it will only work for math surrounded by $ $ or $$ $$. It won't work in the equation environment. The upside is that you do not get your definitions "flashing" at the top of your html pages for a moment, which happens to me with the solution above.

    demo.Rmd

    ---
    title: Foo
    output:
      pdf_document: default
      html_document: default
    ---
    
    ```{r child = 'defs.tex'}
    ```
    
    My math definitions are in defs.tex.  Now I can use the defs in equations
    but they need to be in math mode for html output.  This works for both
    pdf and html:
    $\AA^\top\BB$ and 
    $$\AA^\top\BB$$
    
    But using your new commands in the equation environment
    only works for pdf output because pandoc will not expand the
    definitions if the newcommands are not in $ $ or $$ $$.    
    
    \begin{equation}
    \AA^\top\BB
    \end{equation}
    

    defs.tex

    \newcommand{\BB}{\mathbf{B}}
    \newcommand{\CC}{\mathbf{C}}
    \renewcommand{\AA}{\mathbf{A}}
    
    0 讨论(0)
  • 2021-02-08 01:38

    I don't think Mathjax (which is what Pandoc uses in HTML output) can \usepackage{}. I work around this by having 2 files: one called preamble-mathjax.tex, one called preamble-latex.texMy YAML metadata is set up like this (for rmarkdown):

    output:
        html_document:
           includes:
             before_body: preamble-mathjax.tex
        pdf_document:
           includes:
             in_header: preamble-latex.tex
    

    And preamble-mathjax.tex has (note surrounding \( \) so that mathjax parses as a maths block)

    \(
    \newcommand{\bm}[1]{\boldsymbol{\mathbf{#1}}}
    \)
    

    while preamble-latex.tex has:

    \usepackage{bm}
    

    So that whenever I use \bm{..} in my document, it works whether I compile to HTML or PDF. (stacking the boldsymbol with the mathbf so that both greek letters and normal letters are made bold, and bold letters remain upright as they would if you used \bm).


    Peripheral to your question: Eventually you may wish to have a third file, preamble-both.tex, with macros that are not package-specific (supposing the relevant preamble-* has already been included) e.g.

    \newcommand{\bX}{\bm{X}} % bold X
    \newcommand{\R}{\mathbb{R}} % real numbers
    

    And then you include this with both output formats. This saves you from writing all your macros twice, once for html_document and again for pdf_document. However, MathJax requires the macros to be surrounded by \( and \), whereas LaTeX will error out if this is the case.

    The only way I've found to work around this is to have a file bracket-start.txt containing just \( and a file bracket-end.txt containing just \), so that my YAML is:

    output:
        html_document:
           includes:
             before_body: [preamble-mathjax.tex, bracket-start.txt, preamble-both.tex, bracket-end.txt]
        pdf_document:
           includes:
             in_header: preamble-latex.tex
             before_body: preamble-both.tex
    

    which is pretty unwieldy, but it works (there is the Pandoc latex_macros extension, but it has never worked for me)

    0 讨论(0)
提交回复
热议问题