--- title: "Rendering Markdown with Math" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Rendering Markdown with Math} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", dpi = 300, dev = "png" ) library(gridmicrotex) library(grid) ``` gridmicrotex renders [CommonMark](https://commonmark.org) markdown with LaTeX math between `$...$`. There are two functions: - `markdown_grob()` (and `grid.markdown()`) for a single label, such as a title. - `markdown_box_grob()` for a document with headings, lists, quotes, code and tables. Fonts, options and LaTeX support are the same as for `latex_grob()` (see `vignette("getting-started")`). ## Inline markdown ```{r inline, fig.height = 0.8, fig.width = 6, out.width = "90%"} grid.newpage() grid.markdown( r"(The **fitted** $\hat{\beta} = (X^\top X)^{-1} X^\top y$ has ~~no~~ `se` = *0.42*.)", x = 0.02, hjust = 0, gp = gpar(fontsize = 13) ) ``` ### Inline HTML For colour, underline, sub- and superscripts, highlight and size, use inline HTML: | tag | effect | |---|---| | ``, `` | bold | | ``, ``, ``, ``, `` | italic | | ``, ``, ``, `` | monospace | | ``, `` | underline | | ``, ``, `` | strikethrough | | ``, `` | sub / superscript | | `` | yellow highlight | | ``, `` | smaller / larger | | `` | quotation marks | | ``, `` | annotation above the text (furigana) | | ` ` | non-breaking space | | `
` | line break | | `` | `color`, `font-size`, `font-family`, `text-decoration`, and the rest of `?md_style` | ```{r html-css, fig.height = 1.3, fig.width = 6, out.width = "90%", dev = "ragg_png", dev.args = list()} grid.newpage() grid.markdown( r"(Model fit, serif and mono.

The **residual** for H0 is within $2\sigma$.)", x = 0.02, y = 0.9, hjust = 0, vjust = 1, gp = gpar(fontsize = 13) ) ``` Tags nest, and markdown and math work inside them. Other tags are dropped and their text kept. ## Documents `markdown_box_grob()` stacks the blocks of a document inside an optional box. Text wraps to `width`. Code below is quoted with `~~~r` and `~~~`, instead of `"```"` to avoid conflicts with R Markdown of this vignette. But you should use `"```"` in your own code. ```{r block, fig.height = 3.6, fig.width = 4.6, out.width = "80%"} md <- r"( # Model summary The slope is $\beta_1$ with *p* < 0.001, and this paragraph is long enough that it wraps inside the column. ## Diagnostics - residuals look **fine** - $R^2 = 0.87$ - no influential points ~~~r fit <- lm(y ~ x, data = d) # refit if (anyNA(d)) { stop("missing values") } ~~~ > Assumptions were checked and hold. )" grid.newpage() grid.draw(markdown_box_grob( md, width = unit(4.6, "in"), padding = unit(10, "pt"), box_gp = gpar(fill = "grey97", col = "grey40"), gp = gpar(fontsize = 13), style = markdown_style(css = "pre { background: #ece2f0 }") # Code background )) ``` `box_gp = NULL` draws no box, and `r` rounds its corners. `padding` and `margin` take one unit, or four for top, right, bottom and left. ### Code A fenced code block that names its language is highlighted. `available_highlighters()` lists the languages; `register_highlighter()` adds one from a [KDE syntax file](https://kate-editor.org/syntax/). Colours use the same class names as Pandoc and knitr, so a Pandoc theme can be pasted in: ```r markdown_style(css = ".co { color: #59636E } .kw { color: #CF222E }") ``` ### Lists and tables Task lists and tables work, with column alignment from the `|:---:|` markers: ```{r lists-tables, fig.height = 2, fig.width = 4.4, out.width = "80%"} md <- r"( ### Checklist - [x] fit the model - [ ] write it up Coefficients: | term | $\beta$ | *p* | |:-----|------------:|:---:| | intercept | 30.1 | *** | | slope | -5.3 | *** | )" grid.newpage() grid.draw(markdown_box_grob( md, width = unit(4.4, "in"), padding = unit(8, "pt"), gp = gpar(fontsize = 13) )) ``` ### Images An image on its own line is a block, scaled to fit; one inside a sentence is inline. Images must be local PNG, JPEG or SVG files. ```{r image, fig.height = 1.8, fig.width = 4, out.width = "70%"} img <- system.file("img", "Rlogo.png", package = "png") md <- sprintf(" A figure with a caption below it. ![the R logo](%s) The caption explains the figure. ", img) grid.newpage() grid.draw(markdown_box_grob( md, width = unit(4, "in"), padding = unit(8, "pt"), gp = gpar(fontsize = 13) )) ``` ## Styling `style` takes CSS, as text or a `.css` file: ```{r style-css, fig.height = 1.2, fig.width = 5, out.width = "85%"} doc <- r"( # Results The slope is $\beta_1$ with *p* < 0.001. > Worth a second look. )" grid.newpage() grid.draw(markdown_box_grob( doc, width = unit(4.5, "in"), padding = unit(10, "pt"), style = " h1 { color: steelblue; font-size: 1.8rem } blockquote { color: grey40; border-left: 3px solid steelblue } ", gp = gpar(fontsize = 13) )) ``` Or the same in R: ```{r style-r, eval = FALSE} markdown_style( h1 = md_style(color = "steelblue", font_size = 1.8), blockquote = md_style(color = "grey40", border_left = "3px solid steelblue") ) ``` A bare number is a multiple of the body font size (`rem`). Tags are named as in HTML (`p`, `h1`, `li`, `blockquote`, `pre`, `code`, `table`, ...). `?md_style` lists the supported properties; others are ignored. `markdown_style("github")` starts from a GitHub-like preset, and `latex_options(markdown_style = )` sets a default for the session. ### Styling one part Wrap a part in a `
` with a `class` or `style`, leaving a blank line after the opening tag and before the closing one: ```{r style-div, fig.height = 1, fig.width = 5, out.width = "85%"} doc <- ' Ordinary text.
**Note.** This chunk is indented and set apart.
Ordinary text again. ' grid.newpage() grid.draw(markdown_box_grob( doc, width = unit(4.5, "in"), padding = unit(10, "pt"), style = ".note { color: grey35; padding-left: 1.5rem }", gp = gpar(fontsize = 13) )) ``` `` does the same inside a line. ### Styling tables | CSS | effect | |---|---| | `table { border-color }` | colour of every rule | | `tr { background }` | fills a row | | `td`, `th ` `{ background }` | fills a cell | | `tr { border-bottom }` | a rule under each row | | `td { border-left }` | rules between columns | | `td { padding-left }` | the gap between columns | | `table { table-layout: fixed }` | columns of equal width | A table that is too wide for the box wraps its widest columns. ```{r style-table, fig.height = 2, fig.width = 5, out.width = "85%"} tbl <- r"( | Term | Meaning | |:-----|:--------| | $\beta_1$ | the slope, which needs a good deal of room to explain | | $\sigma$ | the residual standard deviation | )" grid.newpage() grid.draw(markdown_box_grob( tbl, width = unit(4, "in"), padding = unit(8, "pt"), style = " table { table-layout: fixed; border-color: #D1D9E0 } th { background: #F6F8FA } tr { border-bottom: 1px solid #D1D9E0 } ", gp = gpar(fontsize = 13) )) ``` ## LaTeX inside markdown For what markdown cannot do, such as merged or coloured table cells, write LaTeX in a `$$...$$` block: ```{r latex-escape, fig.height = 2.4, fig.width = 4.6, out.width = "80%"} tbl <- r"($$\begin{array}{|l|c|c|}\hline \rowcolor{#F6F8FA}\multicolumn{3}{|c|}{\textbf{Model comparison}}\\\hline \textbf{Model}&\textbf{AIC}&\textbf{R}^2\\\hline \text{linear}&214.3&0.71\\ \cellcolor{#DDF0DD}\text{quadratic}&\cellcolor{#DDF0DD}201.8&\cellcolor{#DDF0DD}0.87\\\hline \end{array}$$)" grid.newpage() grid.draw(markdown_box_grob( paste0("Compare the two fits.\n\n", tbl, "\n\nThe quadratic wins."), width = unit(4.6, "in"), padding = unit(10, "pt"), style = "math { color: #1F3864; font-size: 1.1rem }", gp = gpar(fontsize = 13) )) ``` Inside `\textbf{}` you are in text, so write `\textbf{R}^2`, not `\textbf{R^2}`. CSS table rules do not apply to a LaTeX table; style it in LaTeX. ## Limitations - Links show their text only. - Footnotes are placed at the bottom in `markdown_box_grob()`; in `markdown_grob()` only the marker is shown. - HTML blocks other than `
` and `` are dropped, `` included. Use markdown tables. - Markdown tables cannot merge cells; use LaTeX (above). - Small caps are not supported. - The syntax class names (`co`, `st`, `kw`, `dt`, ...) also apply to your own `
`; choose other names for your classes. - Code is a little narrow on `png(type = "cairo")` and `svglite`; use `ragg::agg_png()` if it matters.