# Markdown Rendering {#chp:mark}

The main function to convert Markdown to other formats is `litedown::mark()`.

You can either call `litedown::mark()` to render a Markdown document
programmatically, or click the `Knit` button in RStudio to render a (Markdown or
R Markdown) document interactively. The latter requires you to specify the
output format in the `output` field in YAML metadata (@sec:yaml-metadata), e.g.,

``` yaml
---
output:
  litedown::html_format:
    options:
      js_math:
        package: "katex"
        version: "0.16.4"
      number_sections: true
      embed_resources: ["local", "https"]
    meta:
      css: "custom.css"
---
```

## Markdown options

The `options` argument of `mark()` can be used to enable/disable/set options to
control Markdown rendering. This argument can take either a list, e.g.,
`list(toc = TRUE, smart = FALSE)`, or a character vector, e.g.,
`c("+toc", "-smart")`, or equivalently, `+toc-smart`, where `+` means to enable
an option, and `-` means to disable an option. The options can also be set in
YAML metadata in @sec:yaml-metadata (recommended). Available options are listed
below.

### `auto_identifiers`

Add automatic IDs to headings, e.g.,

``` markdown
# Hello world!

## Introduction
```

will be converted to

``` html
<h1 id="chp:hello-world">Hello world!</h1>

<h2 id="sec:introduction">Introduction</h2>
```

The prefix `chp:` (chapter) will be added to the automatic IDs of level-one
headings, and `sec:` (section) will be added for other levels of headings.

You can override the automatic ID by providing an ID manually via the ID
attribute, e.g.,

``` markdown
# Hello world! {#hello}
```

An automatic ID is generated by substituting non-alphanumeric characters in the
heading text with hyphens. If the result is empty, the ID will be `section`. If
any ID is duplicated, a numeric suffix will be added to the ID, e.g.,
`example_1` and `example_2`.

### `embed_cleanup`

Whether to clean up plot files after they have been embedded in HTML output (see
@sec:embed-resources).

### `embed_resources`

Embed resources (images, CSS, and JS) in the HTML output using their
base64-encoded data (images) or raw content (CSS/JS). Possible values are:

-   `null` or `false`: Do not embed any resources.

-   `"local"` or `true`: Embed local image/CSS/JS files.

-   `"https"`: Embed web resources (links that start with `https://`).

-   `"all"`: An alias to the union of `"local"` and `"https"`.

The default is `"local"`, i.e., local resources are embedded, whereas `https`
resources are not. This means the output document may not work offline. If you
have to view the output offline, you need to use the option value `"https"` (or
`"all"`) and render the document at least once before you go offline.

### `js_highlight`

Specify the JavaScript library to syntax highlight code blocks. Possible values
are `highlight` ([highlight.js](https://highlightjs.org)) and `prism`
([Prism.js](https://prismjs.com)). The default is `prism`. This option can also
take a list of the form `list(package, version, style, languages)`, which
specifies the package name (`highlight` or `prism`), version, CSS style/theme
name, and names of languages to be highlighted.

-   You can find information about Prism.js from its CDN at
    <https://cdn.jsdelivr.net/npm/prismjs/>. Available styles are under the
    `themes/` directory (e.g., `prism-dark`), and languages are under the
    `components/` directory (e.g., `prism-c`). You can omit the prefix `prism-`,
    e.g.,

    ``` yaml
    js_highlight:
      package: prism
      style: dark
      languages: [r, latex, yaml]
    ```

-   The CDN of highlight.js is at
    <https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/>. Themes are
    under the `styles/` directory (e.g., `github`), and you can find demos of
    themes at <https://highlightjs.org/static/demo/>. Supported language are
    under the `languages/` directory (e.g., `latex`).

By default, languages are automatically detected and the required JS files are
automatically loaded. Normally you need to specify the `languages` array only if
the automatic detection fails.

Technically this option is a shorthand for setting the metadata variables `css`
and `js` in @sec:yaml-metadata. If you want full control, you may disable this
option (set it to `false` or `null`) and use metadata variables directly, which
requires more familiarity with the JS libraries and the jsdelivr CDN.

### `js_math`

Specify the JavaScript library for rendering math expressions in HTML output.
Possible values are `"mathjax"` and `"katex"` (the default). Like the
`js_highlight` option, this option is also essentially a shorthand for setting
the metadata variables `css` and `js`.

-   For [MathJax](https://www.mathjax.org/#gettingstarted), the `js` variable is
    set to `tex-mml-chtml.js`.

-   For [KaTeX](https://katex.org/docs/browser.html), the `js` variable is set
    to `katex.min.js` and the `css` variable is set to `katex.min.css`. KaTeX's
    `auto-render` extension (`auto-render.min.js`) is also enabled by default,
    so math expressions can be immediately rendered when the page is loaded.

If you want finer control, you can provide a list of the form
`list(package, version, css, js)`. This will allow you to specify the package
name, version, and css/js files. For example, if you want to use MathJax's
`tex-chtml.js` instead, you may set:

``` yaml
js_math:
  package: mathjax
  version: 3
  js: es5/tex-chtml.js
```

By default, MathJax version 3 is used. If you want to use the older v2, you may
set:

``` yaml
js_math:
  package: mathjax
  version: 2
  js: MathJax.js?config=TeX-AMS-MML_CHTML
```

Please visit [the MathJax CDN](https://cdn.jsdelivr.net/npm/mathjax/) to know
which versions and JS files are available.

For KaTeX, the version is not specified by default, which means the latest
version from [the CDN](https://cdn.jsdelivr.net/npm/katex/). Below is an example
of specifying the version 0.16.4 and using the `mhchem` extension:

``` yaml
js_math:
  package: katex
  version: 0.16.4
  js: [dist/katex.min.js, dist/contrib/mhchem.min.js]
```

Note that if you want the HTML output to be self-contained via the
`embed_resources` option, KaTeX can be embedded and used offline, but MathJax
cannot be fully embedded due to its complexity. MathJax v3 can be partially
embedded and used offline, but currently only its fonts can be embedded, and
extensions cannot. If you must view HTML output offline, we recommend using
KaTeX, but please also note that KaTeX and MathJax do not fully cover each
other's features.

### `keep_yaml`

Whether to keep the YAML metadata in the output. When `TRUE`, the original YAML
in the Markdown input (if exists) will be written to the output. Note that when
this option is enabled, templates (@sec:templates) will be disabled and `mark()`
will only generate a document fragment. This option was introduced mainly for
Hugo websites to use **litedown** instead of Hugo's Markdown engines to render
pages.

### `latex_math`

Whether to identify LaTeX math expressions in pairs of single (`$ $`) or double
dollar signs (`$$ $$`), and transform them so that they could be correctly
rendered by MathJax (HTML output) or LaTeX.

### `number_sections`

Whether to number section headings. To skip numbering a specific heading, add a
class attribute `.unnumbered` (or use the shorthand `-`) to it. For example:

``` md
## Preface {.unnumbered}

## About the author {-}
```

### `smartypants`

Whether to translate certain ASCII strings into smart typographic characters
(see `?litedown::smartypants`).

### `superscript`

Whether to translate strings between two carets into superscripts, e.g.,
`text^foo^` to `text<sup>foo</sup>`.

### `subscript`

Whether to translate strings between two tildes into subscripts, e.g.,
`text~foo~` to `text<sub>foo</sub>`.

### `toc`

Whether to generate a table of contents (TOC) from section headings. If a
heading has an `id` attribute, the corresponding TOC item will be a link to this
heading. You can also set a sub-option:

-   `depth`: The number of section levels to include in the TOC (`3` by
    default). Setting `toc` to `true` is equivalent to:

    ``` yaml
    toc:
      depth: 3
    ```

To exclude a certain heading from the TOC, assign a class name `unlisted` to it.
For example:

``` md
## Acknowledgments {.unlisted}
```

### `top_level`

The desired type of the top-level headings in LaTeX output. Possible values are
`'chapter'` and `'part'`. For example, if `top_level = 'chapter'`, `# heading`
will be rendered to `\chapter{heading}` instead of the default
`\section{heading}`.

Options not described above can be found on the help pages of **commonmark**,
e.g., the `hardbreaks` option is for the `hardbreaks` argument of
`commonmark::markdown_*()` functions, and the `table` option is for the `table`
extension in **commonmark**'s extensions.

```{r}
#| collapse=TRUE

litedown::markdown_options()
# commonmark's arguments
opts = formals(commonmark::markdown_html)
opts = opts[setdiff(names(opts), c('text', 'extensions'))]
unlist(opts)
# commonmark's extensions
commonmark::list_extensions()
```

## Templates

By default, `mark()` generates a document fragment (i.e., the body) if the input
does not contain YAML metadata at the beginning. To generate a full document,
you need to specify YAML metadata. A full document is generated with a template.
Below is a simple HTML template example:

``` html
<html>
  <head>
    <title>$title$</title>
  </head>

  <body>
  $body$
  </body>
</html>
```

It contains two variables, `$title$` and `$body$`. All variables will be
substituted by metadata values, except for `$body$`, which is from the body of
the input document (after conversion to a target output format).

The **litedown** has provided default templates for
[HTML](https://github.com/yihui/litedown/blob/main/inst/resources/litedown.html)
and
[LaTeX](https://github.com/yihui/litedown/blob/main/inst/resources/litedown.latex)
output. To pass metadata to templates, use the `meta` argument, e.g.,

``` r
litedown::mark(..., meta = list(title = "My Title"))
```

If you want to use a custom template file, you can set the path in the global
option `litedown.FORMAT.template` (where `FORMAT` is the output format name
(`html` or `latex`), e.g., in `.Rprofile`:

``` r
options(litedown.html.template = 'path/to/my/template.html')
```

The global option will be applied to all documents to be converted by `mark()`.
Alternatively, you can pass a template path to the `template` argument of the
output format `litedown::html_format` or `litedown::latex_format` in an
individual document, e.g.,

``` yaml
---
output:
  litedown::html_format:
    template: "path/to/my/template.html"
---
```

The template path can also take a logical value: `TRUE` means to use the default
template, and `FALSE` means to generate only a fragment document without using
any template.

## YAML metadata {#sec:yaml-metadata}

Alternatively, the `meta` argument can read YAML metadata in the Markdown
document.

### Top-level variables

The following variables can be set in the top-level fields in YAML:

-   `abstract`: The abstract.

-   `author`: The document author(s).

-   `date`: The date.

-   `subtitle`: The document subtitle.

-   `title`: The document title.

For example:

``` yaml
---
title: "My Title"
author: "[Frida Gomam](https://example.com)"
date: "2023-01-09"
---
```

The values are treated as Markdown text, and will be converted to the target
output format before being passed to the template. For the above example, the
variable `$author$` will be `<a href="https://example.com">Frida Gomam</a>` in
the HTML template.

For top-level variables, `mark()` will also create the "underscore" versions for
templates, which contain HTML and LaTeX markups. For example, for the `$title$`
variable, `$title_$` will also be available to the template. The following table
shows the values of the underscore variables, assuming the original value of a
variable is `TEXT`:

| Variables | HTML | LaTeX |
|---------------------------|---------------------------|---------------------------|
| `$title_$` | `<div class="title"> <h1>TEXT</h1> </div>` | `\title{TEXT}` |
| `$subtitle_$` | `<div class="subtitle"> <h2>TEXT</h2> </div>` | `\subtitle{TEXT}` |
| `$author_$` | `<div class="author"> <h2>TEXT</h2> </div>` | `\author{TEXT}` |
| `$date_$` | `<div class="date"> <h3>TEXT</h3> </div>` | `\date{TEXT}` |
| `$abstract_$` | `<div class="abstract"> <p>TEXT</p> </div>` | `\begin{abstract} TEXT \end{abstract}` |

If an original variable is empty or missing, its underscore version will also be
empty. For the `$author_$` variable, if the `$author$` variable contains
multiple author names as an array, each name will be in a separate `<h2>` in
HTML output, and all names will be concatenated by `\and` in LaTeX output, e.g.,
for

``` yaml
author: ["Jane X", "John Y"]
```

in YAML, the HTML output will be:

``` html
<div class="author">
  <h2>Jane X</h2>
  <h2>John Y</h2>
</div>
```

and the LaTeX output will be:

``` tex
\author{Jane X \and John Y}
```

If you design your own template, you are free to use either the original or the
underscore versions of these variables. For example, you could put the title in
an `<h1>` without the `<div>` wrapper via `<h1 class="title">$title$</h1>`
instead of using `$title_$`.

When these top-level variables are also provided as `meta` variables for an
output format, the latter will override the former, e.g.,

``` yaml
title: "Global Title"
output:
  litedown::html_format:
    meta:
      title: "Title for HTML output"
  litedown::latex_format:
    meta:
      title: "Title for LaTeX output"
```

### Format-specific variables

Other variables need to be specified under
`output -> litedown::*_format -> meta`, where `*` can be `html` or `latex`,
e.g.,

``` yaml
---
title: "My Title"
output:
  litedown::html_format:
    meta:
      css: "style.css"
      js: "script.js"
  litedown::latex_format:
    meta:
      documentclass: "book"
      header_includes: "\\usepackage{microtype}"
---
```

The following metadata variables are supported for both HTML and LaTeX
templates:

-   `header-includes`, `include-before`, `include-after`: Either a vector of
    (HTML/LaTeX) code or a code file to be included in the header, before the
    body, or after the body of the output.

--------------------------------------------------------------------------------

The following variables are for HTML templates:

#### **The `css` variable**

A vector of CSS files to be included in the output. The default value is
`litedown:::pkg_file('resources', 'default.css')`.

If you want to use built-in CSS files in this package, you can only specify the
base name, e.g., `default` means `default.css` in this package.

You can also use web resources, e.g., `https://example.org/style.css`. One
special case is [jsdelivr](https://www.jsdelivr.com) resources: if a `css` value
starts with `@`, it will be recognized as a jsdelivr.com resource. if you are
not familiar with jsdelivr, you may read its documentation to understand the
following example URLs. The shorthand syntax is as follows (`CDN` stands for
`https://cdn.jsdelivr.net`):

-   `@foo` (without a filename extension) will be converted to
    `CDN/npm/@xiee/utils/css/foo.min.css`, e.g., `@default` means
    `CDN/npm/@xiee/utils/css/default.min.css`. If you prefer the `.css`
    extension over `.min.css`, you can use `@default.css`.

-   `@foo@version` (a filename followed by a version number) will be converted
    to `CDN/npm/@xiee/utils@version/css/foo.min.css`, e.g., `@article@1.12.0`
    means `CDN/npm/@xiee/utils@1.12.0/css/article.min.css`.

-   `@path/to/file` (i.e., a value that contains slashes) will be converted to
    `CDN/path/to/file`, e.g., `@npm/@xiee/utils/js/center-img.js` will be
    converted to `CDN/npm/@xiee/utils/js/center-img.min.js`.

-   `@path/to/file-1,file-2` (comma-separated values and later values do not
    contain slashes) will be converted to
    `CDN/combine/path/to/file-1,path/to/file-2` (this can be useful to
    [combine](https://www.jsdelivr.com/documentation#id-combine-multiple-files)
    multiple resources and load all at once).

-   `@path-1/to/file-1,path-2/to/file-2` (comma-separated values and later
    values contain slashes) will be converted to
    `CDN/combine/path-1/to/file-1,path-2/to/file-2`.

This provides a way to reduce the output HTML file size by loading CSS from the
web instead of embedding inside HTML, at the cost of requiring Internet
connection when viewing the HTML file. If you need the external web resources to
work after you go offline, you can enable `"https"` in the Markdown option
`embed_resources` in advance to embed the resources.

#### The `js` variable

A vector of JavaScript files to be included in the output. The syntax is the
same as the `css` variable, e.g., `snap` means `snap.js` in this package,
`@snap` means a "jsdelivr" resource, and you can use arbitrary paths or URLs to
other JS files.

#### The `body-class` variable

A class name for the main body (the default value is `body`).

--------------------------------------------------------------------------------

The following variables are for LaTeX templates:

#### The `classoption` variable

A string containing options for the document class.

#### The `documentclass` variable

The document class (by default, `article`).

### Naming convention of variables

A variable name must consist of alphanumeric characters and hyphens only. You
could use underscores in variable names in the metadata, but please note that
underscores will be normalized to hyphens internally, e.g., `header_includes`
will be converted to `header-includes`. This means if you use a custom template,
you must use hyphens instead of underscores as separators in variable names in
the template.

### Using custom variables

The above are variables supported in the default templates. If you use a custom
template, you can use arbitrary variable names following the naming convention
(except for `body`, which is a reserved name and cannot be used in metadata),
and the values of variables in the metadata will be passed to your template.

### Setting options in YAML

Besides metadata variables, the aforementioned Markdown options
(@sec:markdown-options) can also be set in YAML under
`output -> litedown::*_format -> options`, e.g.,

``` yaml
output:
  litedown::html_format:
    options:
      toc: true
      js_highlight:
        package: highlight
        theme: github
        languages: [diff, latex]
```

### Other fields in YAML

See the help page `?litedown::html_format` for possible fields in addiction to
`meta` and `options` that can be specified under the format name, e.g.,

``` yaml
output:
  litedown::latex_format:
    latex_engine: xelatex
    keep_md: true
    template: custom-template.tex
```
