- Preface
- The past journey
- A question
- Overview
- Highlights
- Small footprint
- Live preview everything
- Precise parser
- Versioned CSS/JS assets
- Chunk options management
- Non-linear order of execution
- Time code chunks
- Table output for data frames by default
- Relieved pain of paths
- Output in memory or to disk
- A new cache system
- A book is a single HTML file
- R scripts as first-class citizens
- Clean HTML output
- Features out of scope
- 1 Knitting, or Fusing
- 1.1 Code chunks
- 1.2 Inline code
- 1.3 R scripts
- 1.4 Comparison to knitr
- 2 Markdown Syntax
- 2.1 Basic syntax
- 2.2 Add-on features
- 2.2.1 Raw LaTeX/HTML blocks
- 2.2.2 LaTeX math
- 2.2.3 Superscripts and subscripts
- 2.2.4 Footnotes
- 2.2.5 Attributes
- 2.2.6 Appendices
- 2.2.7 Fenced Divs
- 2.2.8 Cross-references
- 2.2.9 Smart HTML entities
- 2.3 Comparison to Pandoc
- 3 Markdown Rendering
- 3.1 Markdown options
- 3.1.1 auto_identifiers
- 3.1.2 embed_resources
- 3.1.3 js_highlight
- 3.1.4 js_math
- 3.1.5 latex_math
- 3.1.6 number_sections
- 3.1.7 smartypants
- 3.1.8 superscript
- 3.1.9 subscript
- 3.1.10 toc
- 3.1.11 top_level
- 3.2 Templates
- 3.3 YAML metadata
- 3.1 Markdown options
- 4 CSS/JS assets
- 4.1 HTML slides
- 4.2 HTML articles
- 4.2.1 The overall style
- 4.2.2 Side elements
- 4.2.3 Body elements
- 4.3 Tabbed sections
- 4.4 Code folding
- 4.5 Callout blocks
- 4.6 Right-align a quote footer
- 4.7 Add anchor links to headings
- 4.8 Style keyboard shortcuts
- 5 Authoring
- 5.1 The Knit button
- 5.2 Live preview
- 5.3 Visual editor
- 6 Books and Websites
- 6.1 Books
- 6.2 Websites
- Appendix
- A For rmarkdown Users
- B Package vignettes
- C Technical Notes
- C.1 Embedding resources
- C.2 CSS for margin content
Edit this chapter on GitHub
The litedown package is still new and experimental. The documentation isvery incomplete. Besides, litedown was designed for minimalists with alimited scope. Average users should perhaps consider using rmarkdown orQuarto instead.
You may say I’m a dreamer
But I’m not the only one
I hope someday you’ll join us
And the world will live as one—John Lennon, Imagine
Imagine there’s no PDF. It’s easy if you try. No Word below us. Above us, onlyHTML.
I do not mean PDF and Word are bad. I only lament the time that human beingsspend on various document formats, given how much a static web page can do.
The past journey
Having worked on the development of R Markdown for nearly 12 years, I have toconfess that I have become a little perplexed about my work, although I clearlyremember the exciting moments. For example:
The moment when I added syntax highlighting to R code in
.Rnw
documents.Beautiful!The moment when I managed to generate a base R plot and a ggplot in the samecode chunk and place them side by side in LaTeX. Magic! Not to mention thatggplot does not require an explicit
print()
call in a code chunk—youprobably do not even know what that means now.The moment when I saw the impossible-to-read diagram that shows all possibleconversions among numerous document formats on the Pandoc homepage.Incredible!
The moment when I discovered DZSlides in Pandoc. Wow! So PowerPoint andLaTeX beamer were not the only choices for slides.
The moment when some rstudio::conf attendees started applauding after I toldthem that the PowerPoint support had been added to the development versionof rmarkdown when one person asked about it.
The moment when I came across remark.js. And tufte.css. And GitBook. AndHugo. And distill.pub. And htmlwidgets, reticulate, and so on.
…
I think the work was largely meaningful. The only problem is I do not see anend. The list of exciting things to do goes on and on.
A question
“At forty, I had no more doubts.” Confucius said. Apparently, I’m not Confucius.On the contrary, as I’m turning forty, I’m having more doubts. I have beenreflecting on the things that have kept me busy.
If I were to summarize the 700+ episodes of Naruto in one sentence, I would usethe question that Gaara (the Fifth Kazekage) asked Onoki (the Third Tsuchikage):
When did you all forsake yourselves?
In my opinion, this question was the most critical turning point in the 700+episodes, reminding the 79-year-old Onoki and the rest of people of theiroriginal dreams. The shinobi world existed to put an end to wars, but it turnedout to bring even more and larger-scale wars.
When did we forsake simplicity? We create software to simplify things, butsoftware often ends up in feature wars.
Markdown was originally invented for simplicity. That is, to make it easier towrite HTML. I used to take out my wallet and tell people that if they are unableto learn the basics of Markdown in 5 minutes, I’d award them 20 dollars. I alsoused to say “In HTML I Trust”, which sounds like a joke, but I really love HTMLand web technologies. Again, I do not mean other document formats are bad atall. It is just that I feel HTML has the greatest potential, and I hope to takefull advantage of its power.1
In other words, I do not expect that “the (software) world will live as one”. Ijust want to make the HTML world a little bit better.
Overview
The litedown package is an attempt to reimagine R Markdown with one primarygoal—do HTML, and do it well, with the minimalism principle. Before LaTeX fanswalk away in disappointment, let me quickly clarify that LaTeX output is alsosupported, but please do not expect anything fancy before you learn to customizeLaTeX templates. Most other output formats are not supported. No Word, RTF,PowerPoint, or EPUB.
R Markdown is rendered via litedown::fuse()
, which is similar tormarkdown::render()
and knitr::knit()
. Markdown is rendered vialitedown::mark()
, which uses commonmark instead of Pandoc.
The commonmark package follows the GFM (GitHub Flavored Markdown) spec,which can be seen as a subset of Pandoc’s Markdown. Therefore the litedownpackage can be viewed as a small subset of the current R Markdown ecosystem (thelatter is based on Pandoc). It aims at simplicity, lightweight, and speed, atthe cost of giving up some advanced features. This package is intended forminimalists. Most users may prefer using tools based on Pandoc instead, such asrmarkdown or Quarto, which offer richer features.
Is litedown really simple? From the developer’s perspective, yes, it is,largely due to the limited scope of the package. From the user’s perspective,some features are definitely not that simple. However, the point is that thecore is simple and small, and you can enable or disable most features. What’smore, you can implement features by yourself if you know CSS/JS.
Highlights
Small footprint
Almost everything in litedown was written from scratch. The package is verylightweight. Currently, it has two dependencies, commonmark andxfun.2 It does not depend on knitr or Pandoc.
It is a deliberate design choice to keep this package lightweight, to make itrelatively easy to use and simple to maintain. The functions mark()
andfuse()
can be viewed as significantly trimmed-down versions of Pandoc andknitr, respectively.
It is absolutely not the goal for litedown to become a substitute of toolsbased on knitr and Pandoc, such as rmarkdown and Quarto. If you are notsure if you should choose litedown or rmarkdown/Quarto, you may want tochoose the latter (especially Quarto). Some litedown features may be portedinto knitr in the future.
Live preview everything
To get started, run litedown::roam()
and it will launch a file browser to letyou preview everything that can be rendered to HTML, such as .md
, .Rmd
, and.R
files. The rendering takes place in memory, which means it will not render.html
files on your disk, unless you request so. The page will beautomatically updated as you edit and save a file. This update-on-save featurecan be turned off, and then you can manually refresh the page to re-render thefile whenever you want.
You can open any file in your editor or the default system application byclicking a button in the browser. You can also render a file or a project in anew R session by clicking a button in the browser.
Precise parser
The R Markdown parser stores the precise line and column numbers of codeelements. The location information is used in various places. For example, whenan error occurs, you will get a message that tells you the precise location inthe source. In editors that support ANSI links (such as the RStudio IDE), youcan even click on the message to go to a specific line/column in the sourcedocument, so you can quickly and easily know where the error occurred exactly.When previewing .Rmd
documents with roam()
, you will see line numbers on theleft side of code blocks. Clicking on these numbers will bring you to the linesin the source.
Due to the fact that the parser is based on commonmark (instead of solely onregular expressions like knitr’s parser), it can precisely recognize codechunks and inline code, which means code within other verbatim code blocks orcomments will be untouched. For example:
````mdBelow is not a code chunk but verbatim contentinside a fenced code block (with four backticks).```{r}1 + 1```Inline code expressions like `{r} 1+1` are notparsed, either.````
<!--Feel free to comment out anything, such as a code chunk:```{r}1 + 1```-->
Versioned CSS/JS assets
By default, litedown produces bare minimal HTML output, but many featurescan be enabled by adding CSS/JS assets (see 4). You can freely choosewhatever versions that work for you to avoid potential future breakage when theassets are upgraded. The assets are not bundled in the litedown package, buthosted on CDN, so updating litedown will not update your assets.
The CSS and JS code for commonly used features do not depend on any frameworkssuch as Bootstrap or jQuery. They are simply vanilla code written from scratch.No generator was used (such as SCSS). The code is often relatively short, so youcould just fork the code, modify it, publish your own version, and use it if youare not satisfied with the original version.
Chunk options management
Chunk options are managed by an environment, i.e., litedown::reactor()
. Usingan environment (as compared to a list like knitr’s opts_chunk
) means youcan access the up-to-date chunk options anywhere, because environments in R aremutable. I cannot explain how awkward knitr’s opts_current
has been. It isbasically a lie—chunk options that you get from opts_current
are notnecessarily “current”.
Non-linear order of execution
A document does not have to be compiled in the linear order. With the chunkoption order
, you can specify code chunks and inline code expressions to beexecuted in an arbitrary order. For example, if you have an abstract in thebeginning of a document, and the abstract needs to use a number calculated atthe end of the document, you can let the abstract be compiled in the end,although it appears earlier in the document.
I guess some users may want to kill me upon knowing this feature, and some maysend me flowers (although I’m not sure if they want to thank me or prepare theflowers for my funeral). For those who want to kill me, please note that thisfeature does not mean litedown is as awful as Jupyter notebooks. It meansyou can specify a fixed order to execute code in the document. The order doesnot have to be from beginning to end, but it is deterministic. In other words,it does not mean you run code chunks in an arbitrary or random order that candetriment reproducibility.
Time code chunks
If you want to figure out which code chunks are time-consuming, simply set thechunk option litedown::reactor(time = TRUE)
in the beginning, and putlitedown::timing_data()
in the last code chunk. It will tell you detailedinformation. In the roam()
preview, the data will also contain links tospecific lines of code chunks, so you click to jump to a specific code chunk.
Table output for data frames by default
Rectangular objects such as data frames (including tibbles) and matrices areprinted as tables by default, and the number of rows is limited to 10 by defaultto avoid generating huge tables by accident.
Relieved pain of paths
File paths (such as image paths) have been a mess in knitr. My deepestapologies for that. I have worked much harder in litedown in this regard.
Output in memory or to disk
Functions such as mark()
, fuse()
, and fuse_book()
can operate in memorywithout writing to disk. By default, if you pass a file input, you get a fileoutput; if you pass text input, you get text output.
A new cache system
You can feel more confident with using the chunk option cache = TRUE
inlitedown than in knitr. The new cache system is more robust andintelligent.
A book is a single HTML file
Unlike bookdown and Quarto, litedown::fuse_book()
renders multiple inputfiles to a single output file. Yes, your whole precious book is in a single(HTML or PDF) file. Grab and go.
The assumption of single-file output for books has made several things a loteasier. For example, if you want to search within the book, just pressCtrl + F
or Command + F
in your browser as you usually do on any other webpage. You do not need a client-side search library. It is also quicker to jumpbetween chapters because they are on the same page. If you want to print theHTML version of the book to PDF, just press Ctrl + P
or Command + P
.
I know you have a concern: wouldn’t the single HTML file be too heavy for thebrowser? The answer is: you should be fine if you do not have too many images.If you do, do not base64 encode them (which is the default), and you can alsolazy-load images to make the book load faster.
R scripts as first-class citizens
An R script has the same status as an R Markdown document. You can writeMarkdown in #'
comments, and chunk options in #|
comments (both areoptional). These are the only two rules to remember. Compared toknitr::spin()
, the rules are much simpler. Besides, R scripts are alsocarefully parsed into “code chunks”, so their line numbers work as well as RMarkdown’s line numbers.
Any application that you can create with R Markdown can be created with Rscripts, such as books and websites.
Clean HTML output
The HTML output generated from litedown is very clean. For example, codeblocks in HTML output contain plain code, instead of full of <span>
tags withrandom attributes. Clean HTML output means the output file size is smaller, andmore importantly, it is easier to inspect the differences between two versionsof output (e.g., in Git). Every time when you update the source document, youcan know more clearly what has changed in the output, which can help you avoidunexpected changes before publishing the output.
Features out of scope
Output formats besides HTML and LaTeX are unlikely to be supported.3 If otheroutput formats are desired, you may use Pandoc to do the conversion.
For tables, only pipe tables are supported. Other table formats are notrecognized.
At the moment, litedown mainly supports R as the computing language. Otherlanguages might be added in the future, but please keep your expectation low,because the support is unlikely to be as good as R.
HTML widgets are not supported yet, but may be reimagined in the future withsome minimal support.
Edit this chapter on GitHub
R Markdown documents need to be knitted to Markdown before being rendered to atarget output format. The function litedown::fuse()
plays a role similar toknitr::knit()
. It “fuses” program code with narratives, i.e., it executes allcode in the source document and interweaves results with narratives in theoutput document. Similar to knitr, litedown supports code chunks andinline code.
1.1 Code chunks
A code chunk consists of the language name, chunk options (in the chunk headeror pipe comments), and the code:
```{lang}#| chunk optionscode```
Currently, a subset of knitr chunk options aresupported, which can be accessed in litedown::reactor()
. To get an optionvalue, use reactor("NAME")
, where NAME
is the option name (e.g.,fig.width
). To set an option globally, use reactor(NAME = VALUE)
.Alternatively, you can manipulate the value returned by reactor()
directly,which is essentially an environment:
opts = litedown::reactor()opts$fig.width # get an optionopts$echo = FALSE # set an option
Code chunks inside other code blocks are not parsed or evaluated, which providesa way to write verbatim code chunks, e.g.,
````markdownSome verbatim content.```{r}1 + 1```````
Similarly, code in comments will not be recognized, either, e.g.,
<!--Do not run this chunk:```{r}1 + 1```or the inline code `{r} pi`.-->
If N + 1
pairs of curly braces are used in the opening fence, the chunk fences(with N
pairs of curly braces) and chunk options will be shown in the output,which can be useful for telling readers the full source of a chunk, e.g.,
```{{r}}#| echo = TRUE, eval = FALSE1 + 1```
1.2 Inline code
The syntax for inline code expressions is `{lang} code`
, where lang
isthe language name, e.g., r
. Spaces are allowed after the opening backtick andbefore the closing backtick. If the code
happens to contain N
backticks, youwill need to use at least N + 1
backticks outside, e.g.,``{r} paste("`", rnorm(1), "`")``
. An inline code expression insideanother piece of inline code is not parsed or evaluated, which provides a way towrite verbatim inline code expressions, e.g., `` `{lang} code` ``
.
Comma-separated chunk options can also be provided to inline code expressionsafter the language name, e.g., `{r, eval=FALSE} code`
.
For knitr users, please note that the syntax `r code`
is not supportedby default. You have to wrap the language name r
in curly braces. As atemporary workaround, you may set options(litedown.enable.knitr_inline = TRUE)
in your .Rprofile
to make litedown recognize `r code`
, but werecommend that you convert the document via litedown:::convert_knitr()
insteadif you decide to stay with litedown in the long run.
1.3 R scripts
Besides R Markdown, you can also pass an R script to fuse()
. You can writeMarkdown content in #'
comments, and group lines of code into chunks by #|
comments, e.g.,
#' ---#' title: An R script#' output:#' litedown::latex_format: null#' ---#' #' A _paragraph_.#| eval=FALSE1:101 + 1#| fig.width=10, dev='pdf'plot(cars)
Both #'
and #|
comments are optional.
1.4 Comparison to knitr
Major differences between knitr and litedown include:
knitr | litedown |
---|---|
Supports multiple graphical devices for a chunk. | Only supports one device for a chunk (but there are multiple choices for this device). |
Depending on certain chunk options, figure output could be both Markdown (![]() ) and raw HTML (<img> ) / LaTeX (\includegraphics{} ). | Always use Markdown syntax for figures. |
The document parser is based on regular expressions and not robust. Code chunks and inline expressions are not aware of their contexts (e.g., code blocks or comments). | The parser is based on commonmark, which is more robust and makes it straightforward to write verbatim code (in a parent code block) or comment out code (in <!-- --> comments). |
Supports a large number of chunk options and language engines. | Supports a limited number of chunk options and engines. |
Inline code does not support options or languages other than R. | Inline code supports options and other languages. |
All code is executed in the linear order. | Code chunks and inline code can be executed in a custom non-linear order defined by the chunk option order (higher values indicate higher priority). |
Supports chunk hooks and output hooks. | No hooks at the moment. |
The package is more than 12 years old and quite mature. | The package is new and still experimental. |
If you feel any indispensable features are missing in litedown, please feelfree to suggest them in Github issues.However, please remember that the goal of litedown is not to fullyre-implement rmarkdown, knitr or Pandoc. Some features may never bere-implemented, especially when the implementation is not simple enough.
Edit this chapter on GitHub
2.1 Basic syntax
For the full list of supported document elements, please read the GFM spec.Below is a quick summary:
Headings start with a number of
#
’s, e.g.,## level-two heading
.Inline elements:
**strong**
,_emphasis_
,~~strikethrough~~
,[text](link)
, and![alt](image/path)
.4Inline code is written in a pair of backticks, e.g.,
`code`
. Codeblocks can be indented, or fenced by```
.List items start with
-
,+
, or*
, e.g.,- item
. A task list item isa regular list item with[ ]
or[x]
in the beginning, e.g.,- [ ] item
.Block quotes start with
>
.Tables are created with
|
as the column separator (i.e., Pandoc’s pipetable, which can be generated byknitr::kable(x, "pipe")
orxfun::md_table()
).
2.2 Add-on features
In addition to GFM features, the litedown package also supports thefollowing features.
2.2.1 Raw LaTeX/HTML blocks
Raw LaTeX and HTML blocks can be written as fenced code blocks with languagenames =latex
(or =tex
) and =html
, e.g.,
```{=tex}This only appears in \LaTeX{} output.```
Raw LaTeX blocks will only appear in LaTeX output, and will be ignored in otheroutput formats. Similarly, raw HTML blocks will only appear in HTML output. Oneexception is raw LaTeX blocks that are LaTeX math environments, which also workfor HTML output (see the next section).
2.2.2 LaTeX math
You can write both $inline$
and $$display$$
LaTeX math, e.g.,\(\sin^{2}(\theta)+\cos^{2}(\theta) = 1\)
$$\bar{X} = \frac{1}{n} \sum_{i=1}^n X_i$$
$$|x| = \begin{cases} x &\text{if } x \geq 0 \\ -x &\text{if } x < 0 \end{cases}$$
LaTeX math environments are also supported, e.g., below are an align
environment and an equation
environment:
\begin{align}a^{2}+b^{2} & = c^{2}\\\sin^{2}(\theta)+\cos^{2}(\theta) & = 1\end{align}\begin{equation}\begin{split}(a+b)^2 &=(a+b)(a+b)\\ &=a^2+2ab+b^2\end{split}\end{equation}
These math environments can be written in raw LaTeX blocks, and they work forboth LaTeX and HTML output, e.g.,
```{=latex}\begin{align}a^{2}+b^{2} & = c^{2}\\\sin^{2}(\theta)+\cos^{2}(\theta) & = 1\end{align}```
For HTML output, it is up to the JavaScript library (MathJax or KaTeX) whether amath environment can be rendered.
2.2.3 Superscripts and subscripts
Write superscripts in ^text^
and subscripts in ~text~
(same syntax asPandoc’s Markdown), e.g., 210 and H2O. Currently only alphanumericcharacters, *
, (
, and )
are allowed in the scripts. For example, a^b c^
will not be recognized as a superscript (because the space is not allowed). Notethat GFM supports striking out text via ~text~
, but this feature has beendisabled and replaced by the feature of subscripts in litedown. To strikeout text, you must use a pair of double tildes.
2.2.4 Footnotes
Insert footnotes via [^n]
, where n
is a footnote number (a uniqueidentifier). The footnote content should be defined in a separate block startingwith [^n]:
. For example:
Insert a footnote here.[^1][^1]: This is the footnote.
The support is limited for LaTeX output at the moment,5 and thereare two caveats if the document is intended to be converted to LaTeX:
The footnote content must be a single paragraph.
Only numbers6 are supported as identifiers, and other types ofidentifiers are not recognized.
The two limitations do not apply to HTML output, e.g., you can write arbitraryelements in footnotes and not necessarily one paragraph.
2.2.5 Attributes
Attributes on images, fenced code blocks, and section headings can be written in{}
. For example, ![text](path){.foo #bar width="50%"}
will generate an<img>
tag with attributes in HTML output:
<img src="path" alt="text" id="bar" class="foo" width="50%" />
and ## Heading {#baz}
will generate:
<h2 id="baz">Heading</h2>
For fenced code blocks, a special rule is that the first class name will betreated as the language name for a block, and the class
attribute of theresult <code>
tag will have a language-
prefix. For example, the followingcode block
```{.foo .bar #my-code style="color: red;"}```
will generate the HTML output below:
<pre> <code class="language-foo bar" id="my-code" style="color: red;"> </code></pre>
Most attributes in {}
are ignored for LaTeX output except for:
The
width
attribute for images, e.g.,![text](path){width="50%"}
will beconverted to\includegraphics[width=.5\linewidth]{path}
.The
.unnumbered
attribute, which will make a heading unnumbered, e.g.,# Hello {.unnumbered}
will be converted to\section*{Hello}
.The
.appendix
attribute on a heading, which will start the appendix, e.g.,# Appendix {.appendix}
will be converted to\appendix
.
2.2.6 Appendices
When a top-level heading has the attribute .appendix
, the rest of the documentwill be treated as the appendix. If section numbering is enabled(3.1.6), the appendix section headings will be numbereddifferently.
2.2.7 Fenced Div
s
A fenced Div
can be written in :::
fences. Note that the opening fence musthave at least one attribute, such as the class name. For example:
::: fooThis is a fenced Div.:::::: {.foo}The syntax `::: foo` is equivalent to `::: {.foo}`.:::::: {.foo #bar style="color: red;"}This div has more attributes.It will be red in HTML output.:::
A fenced Div
will be converted to <div>
with attributes in HTML output,e.g.,
<div class="foo" id="bar" style="color: red;"></div>
For LaTeX output, it can be converted to a LaTeX environment if both the classname and an attribute data-latex
are present. For example,
::: {.tiny data-latex=""}This is _tiny_ text.:::
will be converted to:
\begin{tiny}This is \emph{tiny} text.\end{tiny}
The data-latex
attribute can be used to specify arguments to the environment(which can be an empty string if the environment doesn’t need an argument). Forexample,
::: {.minipage data-latex="{.5\linewidth}"}
will be converted to:
\begin{minipage}{.5\linewidth}
If a fenced Div
doesn’t have the data-latex
attribute, the fence will beignored, and its content will be written out normally without a surroundingenvironment. If a fenced Div
has multiple class names (e.g., {.a .b .c}
),only the first class name will be used as the LaTeX environment name. However,all class names will be used if the output format is HTML (e.g.,<div class="a b c">
).
2.2.8 Cross-references
To cross-reference an element, it must be numberd first. For section headings,the numbers are automatically generated if the number_sections
option is true.For other elements, they must contain empty anchors of the form [](#@ID)
,where ID
is the ID of the element to be referenced. For figures, these anchorsare automatically generated if the chunk options fig.cap
(figure caption) andfig.env
are not empty, e.g.,
```{r}#| nice-plot, fig.cap="A nice caption", fig.env=".figure"plot(cars)```
To refer to an element in the text, use the syntax @ID
, e.g.,
Please see @fig-nice-plot for an overview of the `cars` data.
2.2.9 Smart HTML entities
“Smart” HTML entities can be represented by ASCII characters, e.g., you canwrite fractions in the form n/m
. Below are some example entities:
1/2 | 1/3 | 2/3 | 7/8 | 1/7 | 1/9 | 1/10 | (c) | (r) | (tm) |
---|---|---|---|---|---|---|---|---|---|
½ | ⅓ | ⅔ | ⅞ | ⅐ | ⅑ | ⅒ | © | ® | ™ |
2.3 Comparison to Pandoc
As mentioned earlier, a lot of features in Pandoc’s Markdown are not supportedin the litedown package. Any feature that you find missing in previoussections is likely to be unavailable. In addition, a lot of R Markdown andQuarto (both are based on Pandoc) features are not supported, either. Some HTMLfeatures have been implemented via JavaScript and CSS.
Pandoc can convert Markdown to many output formats, such as Word, PowerPoint,LaTeX beamer, and EPUB. The litedown package is unlikely to support outputformats beyond HTML and LaTeX.
Edit this chapter on GitHub
The main function to convert Markdown to other formats is litedown::mark()
.
You can either call litedown::mark()
to render a Markdown documentprogrammatically, or click the Knit
button in RStudio to render a (Markdown orR Markdown) document interactively. The latter requires you to specify theoutput format in the output
field in YAML metadata (3.3), e.g.,
---output: litedown::html_format: options: js_math: package: "katex" version: "0.16.4" number_sections: true embed_resources: ["local", "https"] meta: css: "custom.css"---
3.1 Markdown options
The options
argument of mark()
can be used to enable/disable/set options tocontrol 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 enablean option, and -
means to disable an option. The options can also be set inYAML metadata in 3.3 (recommended). Available options are listedbelow.
3.1.1 auto_identifiers
Add automatic IDs to headings, e.g.,
# Hello world!
will be converted to
<h1 id="sec-hello-world">Hello world!</h1>
You can override the automatic ID by providing an ID manually via the IDattribute, e.g.,
# Hello world! {#hello}
An automatic ID is generated by substituting non-alphanumeric characters in theheading text with hyphens. If the result is empty, the ID will be section
. Ifany ID is duplicated, a numeric suffix will be added to the ID, e.g.,example_1
and example_2
. A prefix sec-
will be added to the automatic IDs.
3.1.2 embed_resources
Embed resources (images, CSS, and JS) in the HTML output using theirbase64-encoded data (images) or raw content (CSS/JS). Possible values are:
null
orfalse
: Do not embed any resources."local"
ortrue
: Embed local image/CSS/JS files."https"
: Embed web resources (links that start withhttps://
)."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 youhave 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.
3.1.3 js_highlight
Specify the JavaScript library to syntax highlight code blocks. Possible valuesare highlight
(highlight.js) and prism
(Prism.js). The default is prism
. This option can alsotake a list of the form list(package, version, style, languages)
, whichspecifies the package name (highlight
or prism
), version, CSS style/themename, and names of languages to be highlighted.
You can find information about Prism.js from its CDN athttps://cdn.jsdelivr.net/npm/prismjs/. Available styles are under the
themes/
directory (e.g.,prism-dark
), and languages are under thecomponents/
directory (e.g.,prism-c
). You can omit the prefixprism-
,e.g.,js_highlight: package: prism style: dark languages: [r, latex, yaml]
The CDN of highlight.js is athttps://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/. Themes areunder the
styles/
directory (e.g.,github
), and you can find demos ofthemes at https://highlightjs.org/static/demo/. Supported language areunder thelanguages/
directory (e.g.,latex
).
By default, languages are automatically detected and the required JS files areautomatically loaded. Normally you need to specify the languages
array only ifthe automatic detection fails.
Technically this option is a shorthand for setting the metadata variables css
and js
in 3.3. If you want full control, you may disable thisoption (set it to false
or null
) and use metadata variables directly, whichrequires more familiarity with the JS libraries and the jsdelivr CDN.
3.1.4 js_math
Specify the JavaScript library for rendering math expressions in HTML output.Possible values are "mathjax"
and "katex"
(the default). Like thejs_highlight
option, this option is also essentially a shorthand for settingthe metadata variables css
and js
.
For MathJax, the
js
variable isset totex-mml-chtml.js
.For KaTeX, the
js
variable is settokatex.min.js
and thecss
variable is set tokatex.min.css
. KaTeX’sauto-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 formlist(package, version, css, js)
. This will allow you to specify the packagename, version, and css/js files. For example, if you want to use MathJax’stex-chtml.js
instead, you may set:
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 mayset:
js_math: package: mathjax version: 2 js: MathJax.js?config=TeX-AMS-MML_CHTML
Please visit the MathJax CDN to knowwhich versions and JS files are available.
For KaTeX, the version is not specified by default, which means the latestversion from the CDN. Below is an exampleof specifying the version 0.16.4 and using the mhchem
extension:
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 theembed_resources
option, KaTeX can be embedded and used offline, but MathJaxcannot be fully embedded due to its complexity. MathJax v3 can be partiallyembedded and used offline, but currently only its fonts can be embedded, andextensions cannot. If you must view HTML output offline, we recommend usingKaTeX, but please also note that KaTeX and MathJax do not fully cover eachother’s features.
3.1.5 latex_math
Whether to identify LaTeX math expressions in pairs of single ($ $
) or doubledollar signs ($$ $$
), and transform them so that they could be correctlyrendered by MathJax (HTML output) or LaTeX.
3.1.6 number_sections
Whether to number section headings. To skip numbering a specific heading, add anattribute {.unnumbered}
to it.
3.1.7 smartypants
Whether to translate certain ASCII strings into smart typographic characters(see ?litedown::smartypants
).
3.1.8 superscript
Whether to translate strings between two carets into superscripts, e.g.,text^foo^
to text<sup>foo</sup>
.
3.1.9 subscript
Whether to translate strings between two tildes into subscripts, e.g.,text~foo~
to text<sub>foo</sub>
.
3.1.10 toc
Whether to generate a table of contents (TOC) from section headings. If aheading has an id
attribute, the corresponding TOC item will be a link to thisheading. You can also set a sub-option:
depth
: The number of section levels to include in the TOC (3
bydefault). Settingtoc
totrue
is equivalent to:toc: depth: 3
3.1.11 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 ofcommonmark::markdown_*()
functions, and the table
option is for the table
extension in commonmark’s extensions.
litedown::markdown_options()
#> [1] "-hardbreaks" "-number_sections" "-smartypants" #> [4] "-tagfilter" "-toc" "+auto_identifiers"#> [7] "+autolink" "+cross_refs" "+embed_resources" #> [10] "+js_highlight" "+js_math" "+latex_math" #> [13] "+smart" "+strikethrough" "+subscript" #> [16] "+superscript" "+table" "+tasklist"
# commonmark's argumentsopts = formals(commonmark::markdown_html)opts = opts[setdiff(names(opts), c('text', 'extensions'))]unlist(opts)
#> hardbreaks smart normalize sourcepos footnotes #> FALSE FALSE FALSE FALSE FALSE
# commonmark's extensionscommonmark::list_extensions()
#> [1] "table" "strikethrough" "autolink" "tagfilter" #> [5] "tasklist"
3.2 Templates
By default, mark()
generates a document fragment (i.e., the body) if the inputdoes 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> <head> <title>$title$</title> </head> <body> $body$ </body></html>
It contains two variables, $title$
and $body$
. All variables will besubstituted by metadata values, except for $body$
, which is from the body ofthe input document (after conversion to a target output format).
The litedown has provided default templates forHTMLandLaTeXoutput. To pass metadata to templates, use the meta
argument, e.g.,
litedown::mark(..., meta = list(title = "My Title"))
If you want to use a custom template file, you can either set the path in theglobal option litedown.FORMAT.template
(where FORMAT
is the output formatname (html
or latex
), e.g., in .Rprofile
:
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 theoutput format litedown::html_format
or litedown::latex_format
in anindividual document, e.g.,
---output: litedown::html_format: template: "path/to/my/template.html"---
The template path can also take a logical value: TRUE
means to use the defaulttemplate, and FALSE
means to generate only a fragment document without usingany template.
Alternatively, the meta
argument can read YAML metadata in the Markdowndocument. The following variables can be set in the top-level fields in YAML:
author
: The document author(s).date
: The date.title
: The document title.
For example:
---title: "My Title"author: "[Frida Gomam](https://example.com)"date: "2023-01-09"---
Note that you can use Markdown syntax in them.
Other variables need to be specified underoutput -> litedown::*_format -> meta
, where *
can be html
or latex
,e.g.,
---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 LaTeXtemplates:
header-includes
,include-before
,include-after
: Either a vector of(HTML/LaTeX) code or a code file to be included in the header, before thebody, or after the body of the output.
Variables specific to the HTML template:
css
: A vector of CSS files to be included in the output. The default valueislitedown:::pkg_file('resources', 'default.css')
.If you want to use built-in CSS files in this package, you can only specifythe base name, e.g.,
default
meansdefault.css
in this package.You can also use web resources, e.g.,
https://example.org/style.css
. Onespecial case is jsdelivr resources: if acss
value starts with@
, it will be recognized as a jsdelivr.com resource. ifyou are not familiar with jsdelivr, you may read its documentation tounderstand the following example URLs. The shorthand syntax is as follows(CDN
stands forhttps://cdn.jsdelivr.net
):@foo
(without a filename extension) will be converted toCDN/npm/@xiee/utils/css/foo.min.css
, e.g.,@default
meansCDN/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 beconverted toCDN/npm/@xiee/utils@version/css/foo.min.css
, e.g.,@[emailprotected]
meansCDN/npm/@xiee/[emailprotected]/css/article.min.css
.@path/to/file
(i.e., a value that contains slashes) will be convertedtoCDN/path/to/file
, e.g.,@npm/@xiee/utils/js/center-img.js
will beconverted toCDN/npm/@xiee/utils/js/center-img.min.js
.@path/to/file-1,file-2
(comma-separated values and later values do notcontain slashes) will be converted toCDN/combine/path/to/file-1,path/to/file-2
(this can be useful tocombinemultiple resources and load all at once).@path-1/to/file-1,path-2/to/file-2
(comma-separated values and latervalues contain slashes) will be converted toCDN/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 fromthe web instead of embedding inside HTML, at the cost of requiring Internetconnection when viewing the HTML file. If you need the external webresources to work after you go offline, you can enable
"https"
in theMarkdown optionembed_resources
in advance to embed the resources.js
: A vector of JavaScript files to be included in the output. The syntaxis the same as thecss
variable, e.g.,snap
meanssnap.js
in thispackage, and@snap
means a “jsdelivr” resource.body-class
: A class name for the main body (the default value isbody
).
Variables specific to the LaTeX template:
classoption
: A string containing options for the document class.documentclass
: The document class (by default,article
).
Note that you can use either underscores or hyphens in the variable names.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 inthe template.
The above are variables supported in the default templates. If you use a customtemplate, you can use arbitrary variable names consisting of alphanumericcharacters and hyphens, except for $body$
(which is a reserved name), and yourmetadata values will be passed to these variables in your template.
Besides metadata variables, the aforementioned Markdown options can also be setin YAML under output -> litedown::*_format -> options
, e.g.,
output: litedown::html_format: options: toc: true js_highlight: package: highlight theme: github languages: [diff, latex]
See the help page ?litedown::html_format
for possible fields in addiction tometa
and options
that can be specified under the format name, e.g.,
output: litedown::latex_format: latex_engine: xelatex keep_md: true template: custom-template.tex
Edit this chapter on GitHub
The litedown package aims at lightweight with a minimal number of featuresat its core, but you can add more features by yourself. In this chapter, weintroduce some CSS/JS assets from the GitHub repositoryhttps://github.com/yihui/misc.js. You can load arbitrary external JS and CSSfiles via the js
and css
meta variables. There are numerous JS libraries andCSS frameworks on the web that you can use, and you do not have to use the onesmentioned in this chapter. You can also write CSS/JS by yourself to enhance yourHTML applications.
Remember that the CSS and JS are introduced under the output formatlitedown::html_format
in YAML metadata, e.g.,
---output: litedown::html_format: meta: css: ["one.css", "two.css"] js: ["three.js", "four.js"]---
For the sake of brevity, we will omit the full YAML fields in examplesthroughout this chapter but only use the css
and js
fields. A file namefoo.js
denotes the file under the js/
directory of the aforementionedyihui/misc.js
repository. Similarly, foo.css
is under the css/
directory.
All these CSS/JS resources can be used offline, and there are two ways to do it.One way is to clone the GitHub repo to your working directory, and use the filesyou need, e.g.,
js: ["repo/path/js/callout.js"]
Another way is to enable embedding resources:
output: litedown::html_format: meta: js: ["@callout"] options: embed_resources: ["https"]
After you have embedded CSS/JS resources once when you have Internet access,these resources will be cached locally and will not require an Internetconnection again. This solution works for any online resources, not limited tothe yihui/misc.js
repository.
4.1 HTML slides
With snap.css
and snap.js
, you can create lightweight HTML slides:
css: ["@default", "@snap"]js: ["@snap"]
You can learn more in vignette('slides', package = 'litedown')
.
4.2 HTML articles
We can style an HTML page in an article format via the following CSS and JS:
css: ["@default", "@article"]js: ["@sidenotes", "@appendix"]
The article.css
is mainly for styling the article frontmatter, body, and sidecontent.
The
sidenotes.js
is required only if you want to place certain elements onthe left or right side, such as the table of contents (TOC), footnotes, andsidenotes.The
appendix.js
is required only if you have an appendix in the article.
The web version of this book is also based on the article format, so you knowwhat an article format looks like when you read the HTML version of the book.
4.2.1 The overall style
The maximum width of the article body is 800px. For larger screens, this meansthere will be extra space in the left/right margin, where we can place auxiliaryinformation, such as the TOC and footnotes. On smaller screens, the side contentwill be collapsed into the body.
The article frontmatter, body, and optionally the appendix are placed inseparate boxes.
The default typeface is sans-serif, and you can customize it by supplying anexternal CSS file (via the css
meta variable) or just embedding CSS in thedocument body, e.g.,
```{css, echo=FALSE}body { font-family: Palatino, "Book Antiqua", Georgia, serif; font-size: 1em;}```
4.2.2 Side elements
The TOC and footnotes are automatically placed in the margin if space permits.You can also write arbitrary content in the margin via a fenced Div
.
4.2.2.1 The TOC
The TOC is sticky on the left side as you scroll down the article. If you do notlike this behavior, you may cancel it via CSS:
#TOC { top: unset;}
4.2.2.2 Footnotes
Footnotes are moved to the right side. When you move your cursor over a footnotenumber in the body, the footnote will be moved next to your cursor. This can beconvenient when you have multiple footnotes on a line, since you do not need tolook for a specific footnote in the margin.
4.2.2.3 Arbitrary sidenotes
You can write anything in the margin by using a fenced Div
with the classes.side
and .side-left
or .side-right
.
Notice
Here is a note on the left side. Anything permitted by law is permitted here.Math? No problem!
$$e^{i\theta}=\sin{\theta}+i\cos{\theta}$$
When you have this sidenote “hammer”, I’m sure you will hit a lot of nails intothe margin, even if you do not have to.
And here is a note on the right side. Seriously, we should letcommonmark’s authors know that fenced Div
s reallydeserve first-class support! They can make Markdown infinitely customizable.
::: {.side .side-left}**Anything** on the left.:::
::: {.side .side-right}_Anything_ on the right.:::
4.2.3 Body elements
Inside the article body, you can write a few special elements.
4.2.3.1 Full-width elements
When an element is wider than the article body, you can show it in its fullwidth by enclosing the element in a fenced Div
with the class .fullwidth
,e.g.,
::: {.fullwidth}![text](path/to/image):::
If you use R Markdown, you can generate a wide plot or table from an R codechunk, e.g.,
::: {.fullwidth}```{r}#| sunspots, echo=FALSE, fig.dim=c(14, 4),#| fig.cap='Monthly mean relative sunspot numbers from 1749 to 1983.'par(mar = c(4, 4, .1, .1), bg = 'lightgoldenrodyellow', fg = 'red', las = 1)plot(sunspots, col = 'red', panel.first = grid())```:::
If you want to show code (echo = TRUE
) but do not want the code to be in thefull-width container, you can apply the .fullwidth
class to the plot only,e.g.,
```{r}#| sunspots, fig.dim=c(14, 4), fig.env='.fullwidth .figure .box',#| fig.cap='Monthly mean relative sunspot numbers from 1749 to 1983.'par(mar = c(4, 4, .1, .1), bg = 'lightgoldenrodyellow', fg = 'red', las = 1)plot(sunspots, col = 'red', panel.first = grid())```
4.2.3.2 Left/right quotes
Whenever you find that you are on the side of the majority, it is time topause and reflect.
Sometimes you may want to add a quote but do not want it to take the full widthin the body. You may use a fenced Div
with the class .quote-left
or.quote-right
.
Despite the class names, the content does not have to be a quote. If you do wanta quote, just use the blockquote syntax >
, e.g.,
::: {.quote-right}> This is a boring quote.>> ---Someone:::
4.2.3.3 Margin embedding
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
You can embed elements on the left or right margin using a fenced Div
with theclass .embed-left
or .embed-right
. These elements will float to the left orright and exceed the margin by about 200px, which can save some space in thearticle body. You can use the extra space to explain the embedded element withtext.
We have embedded a table of the first 4 rows of the mtcars
data on the rightmargin, which you can see if the browser window is wide enough.
4.3 Tabbed sections
You can load the script tabsets.js
and CSS tabsets.css
to create tabsetsfrom sections (see documentationhere).
css: ["@tabsets"]js: ["@tabsets"]
4.4 Code folding
Code folding is supported by fold-details.js
(see documentationhere).
js: ["@fold-details"]
4.5 Callout blocks
A callout block is a fenced Div with the class name callout-*
. Calloutsrequire callout.css
and callout.js
:
css: ["@callout"]js: ["@callout"]
For example:
::: callout-tipThis is a tip.> You can write arbitrary content, such as a blockquote.::: callout-cautionEven another callout!:::Is that cool?:::
Output:
This is a tip.
You can write arbitrary content, such as a blockquote.
Even another callout!
Is that cool?
The stylesheet callout.css
supports styling three types of callouts: tip
,caution
, and important
. For example:
Be careful when testing for strict equality of floating point numbers.
seq(0, 1, .2) == c(0, .2, .4, .6, .8, 1)
#> [1] TRUE TRUE TRUE FALSE TRUE TRUE
For the sake of reproducibility, please remember to render an R Markdowndocument in a new R session before publishing or submitting the outputdocument.
You do not have to use callout.css
but can define your own CSS rules, e.g.,
.callout-important { background-color: red; color: yellow;}
Under the hood, callout.js
turns the fenced Div into a <fieldset>
for theform:
<fieldset class="callout-*"> <legend>Title</legend> Content.</fieldset>
The content comes from the original fenced Div. The title comes from the classname (converted to uppercase) by default. You can provide a custom title via thedata-legend
attribute of the Div, e.g.,
::: {.callout-tip data-legend="Information"}:::
The icons before the callout titles can be defined via CSS, e.g., you can addtwo exclamation marks before the title of important
callouts:
.callout-important legend::before { content: "!! ";}
The default icons defined in callout.css
are essentially UTF-8characters. In theory,there are hundreds of thousands of characters that you can choose from. Eachcharacter is 1 to 4 bytes. For example, you can define a music
callout withthe music note symbol ♫ in the CSS:
.callout-music { background-color: springgreen;}.callout-music legend::before { content: "♫ ";}
Then you can insert a music
callout in your document:
::: callout-musicPlease listen to this lovely song.:::
You can use the script right-quote.js
to right-align a blockquote footer if itstarts with an em-dash (---
).
js: ["@right-quote"]
4.7 Add anchor links to headings
The CSS is necessary only if you want to hide the anchors by default and revealthem on hover.
css: ["@heading-anchor"]js: ["@heading-anchor"]
4.8 Style keyboard shortcuts
The script key-button.js
identifies keys and the CSS styles them, which can beuseful for showing keyboardshortcuts.
css: ["@key-buttons"]js: ["@key-buttons"]
Of course, you can combine any number of JS scripts and CSS files if you wantmultiple features.
Edit this chapter on GitHub
5.1 The Knit
button
If you use the RStudio IDE, the Knit
button can render R Markdown to alitedown output format specified in YAML (e.g., litedown::html_format
orlitedown::latex_format
). Please also remember to add a top-level settingknit: litedown:::knit
in YAML, otherwise RStudio will use knitr::knit()
instead of litedown::fuse()
to compile R Markdown.
---output: litedown::html_format: null litedown::latex_format: nullknit: litedown:::knit---
5.2 Live preview
Unless it has become your muscle memory to click on the Knit
button inRStudio, you may try to switch to litedown::roam()
to preview your HTMLoutput. It also allows you to render a document or project in a new R session byclicking on the ↯ button at the top, which is similar to what the Knit
buttondoes.
By default, the preview will automatically refresh the content after you editand save a file. If you prefer building the document only when you want to, youcan turn off the live preview via litedown::roam(live = FALSE)
. In this case,the document will be rebuilt only when you refresh the page by yourself.
In the preview mode, you can click on the ✎ button to open a plain-text file inyour editor. Code blocks in the preview mode will have line numbersautomatically added to their left. If you click on a line number, it will bringyou to the that line in the source document.
5.3 Visual editor
Since the Markdown syntax of litedown can be viewed as a subset of Pandoc’sMarkdown, you can use RStudio’s visual Markdown editor to author documents.Please bear in mind that most common, but not all, Markdown features aresupported.
Edit this chapter on GitHub
Books and websites are usually based on multiple input files under a directory.For a directory to be recognized as a book or website project, it needs tocontain a configuration file named _litedown.yml
.
If you want to customize the output formats html_format
or latex_format
forbooks or websites, you should do it in _litedown.yml
, e.g.,
output: litedown::html_format: options: toc: depth: 4 litedown::latex_format: meta: documentclass: "book"
6.1 Books
The _litedown.yml
file should contain a top-level field named book
, whichcurrently supports these options:
book: new_session: false subdir: false pattern: "[.]R?md$" chapter_before: "Information before a chapter." chapter_after: "This chapter was generated from `$input$`."
You can choose whether to render each input file in a new R session, whether tosearch subdirectories for input files, the types of input files (e.g., you canuse .md
or .R
files if you want), and additional information to be includedbefore/after each chapter, in which you can use some variables such as$input$
, which is the path of each input file.
6.2 Websites
The _litedown.yml
file should contain a top-level field named site
, and youare likely to customize the meta
variables css
, include_before
, andinclude_after
for the html_format
, e.g.,
site: rebuild: "outdated" pattern: "[.]R?md$"output: litedown::html_format: meta: css: ["@default"] include_before: "[Home](/) [About](/about.html)" include_after: "© 2024 | [Edit]($input$)"
Basically, include_before
can take a file or text input that will be used asthe header of each web page, and include_after
will be the footer.
Edit this chapter on GitHub
The litedown package has also provided two internal output formats forcompatibility with rmarkdown: litedown:::html_document
andlitedown:::pdf_document
.7 The purpose is to make it a littleeasier to switch from rmarkdown to litedown by mapping somermarkdown output format options to litedown.
For example, for an R Markdown document with the following output format:
output: html_document: toc: true number_sections: true anchor_sections: true self_contained: false
You can switch to litedown simply by changing the output format name fromhtml_document
to litedown:::html_document
. Internally, the above outputformat is transformed to:
output: litedown::html_format: options: toc: true number_sections: true embed_resources: false meta: css: ["default", "@heading-anchor"] js: ["@heading-anchor"]
Note that not all rmarkdown options are supported, and not even allsupported options have exactly the same effects in litedown. The supportedoptions include:toc
, toc_depth
, number_sections
, anchor_sections
, code_folding
, self_contained
, math_method
, css
, and includes
.
Edit this chapter on GitHub
To build package vignettes with litedown, first add this to the packageDESCRIPTION
file:
VignetteBuilder: litedown
Then use the vignette engine litedown::vignette
in the YAML metadata of a.Rmd
or .md
vignette file:
vignette: > %\VignetteEngine{litedown::vignette} %\VignetteIndexEntry{Your vignette title} %\VignetteEncoding{UTF-8}
The output format of a vignette can be specified in the output
field of theYAML metadata, e.g., litedown::html_format
(for HTML vignettes) orlitedown::latex_format
(for PDF vignettes). If no output format is specified,the default is HTML.
The vignette file can be either .Rmd
or .md
. The former is processed bylitedown::fuse()
, and the latter is converted by litedown::mark()
. Pleaseavoid using the same base filename for two .Rmd
and .md
files, otherwisetheir output files will overwrite each other.
Edit this chapter on GitHub
C.1 Embedding resources
When https
resources needs to be embedded (via the embed_resources
option),only these elements are considered:
<img src="..." /><link rel="stylesheet" href="..."><script src="..."></script>
Background images set in the attribute style="background-image: url(...)"
arealso considered. If an external CSS file contains url()
resources, theseresources will also be downloaded and embedded.
C.2 CSS for margin content
It’s quite simple to move an element into the margin using CSS. For example, the.side-right
class in this article is roughly defined as:
.side-right { width: 200px; float: right; margin-right: -200px}
That basically means the width of the element is 200px and it floats to theright. Now its right side will touch the right margin of its parent element (thearticle body). What we need to do next is move it further to the right by 200px(i.e., its width), which is done by the -200px
right margin. Remember, apositive right margin in CSS moves an element to the left, and a negative rightmargin moves it to the right.
At one night, as I was thinking about Pandoc Lua filters, an obvious factsuddenly came to my mind: suppose all I care about is HTML output, then thegood old JavaScript can actually play a perfect role of Lua filters, becauseyou can manipulate the DOM arbitrarily with JavaScript. ↩
The commonmark dependency might be removed in the (far) future. ↩
In fact,
xml,
man
,text
, andcommonmark
output formats aresupported (thanks to the commonmark package), but perhaps they are notvery useful to average users. ↩Please note that for links and images, their URLs should notcontain spaces. Ifthey do, the URLs must be enclosed in
<>
, e.g.,![alt](<some dir/a subdir/foo.png>).
↩If you know C, I’ll truly appreciate it if you could help withthe LaTeX implementation in GFM:https://github.com/github/cmark-gfm/issues/314 ↩
The specific number doesn’t matter, as long as it’s a uniquefootnote number in the document. For example, the first footnote can be
[^100]
and the second can be[^64]
. Eventually they will appear as[1]
and[2]
. If you use the RStudio visual editor to edit Markdown documents,the footnote numbers will be automatically generated and updated when newfootnotes are inserted before existing footnotes. ↩The triple-colon
:::
means these functions are not exported,which is to avoid name conflicts between the two packages. ↩