markdown::mark()
Source document -> Markdown output -> Target document
Examples:
.Rmd
-> .md
-> .html
/ .tex
/ .docx
.qmd
-> .md
-> .html
/ .tex
/ …We only talk about the second step today, i.e., converting .md
.
R Markdown (https://rmarkdown.rstudio.com) has already had a mature and rich ecosystem.
Today I’m introducing a different version of R Markdown, which is not based on Pandoc but the R package markdown instead: https://github.com/rstudio/markdown
Historically this is called “R Markdown v1” (= markdown + knitr).
markdown is based on the commonmark package.
rmarkdown and Pandoc are too rich for me; personally I don’t need so many features
commonmark is too poor to be practically useful (e.g., no support for LaTeX math)
markdown is a compromise: extending commonmark to cover most core Markdown features in Pandoc and still being lightweight
It is not the man who has too little that is poor, but the one who hankers after more.
— Letters from a Stoic (Lucius Annaeus Seneca)
Unless you consider yourself a minimalist or a hacker, you may not benefit much from this talk (please feel free to leave at any time during the talk).
For most people, I think rmarkdown and Quarto are better choices.
Smaller footprint of software packages (faster and easier to install):
pkg_size = function(pkg) {
pkgs = tools::package_dependencies(pkg, recursive = TRUE)
pkgs = setdiff(c(pkg, unlist(pkgs)), xfun::base_pkgs())
dirs = find.package(pkgs)
files = list.files(dirs, full.names = TRUE, recursive = TRUE)
sum(file.size(files))
}
xfun::format_bytes(pkg_size('markdown')) # 2 Mb (knitr = 8 Mb)
xfun::format_bytes(pkg_size('rmarkdown')) # 83 Mb
xfun::format_bytes(file.size(rmarkdown::pandoc_exec())) # 152 Mb
Faster to convert Markdown to HTML/LaTeX
markdown uses the commonmark package, which calls C code
rmarkdown calls Pandoc, an external command–line tool
Smaller (HTML) output file size
No use of CSS or JS frameworks like Bootstrap (on which rmarkdown depends by default)
All CSS and JS code was written from scratch and relatively simple
Quicker to learn thoroughly
markdown’s syntax and features:
vignette('intro', package = 'markdown')
Pandoc’s manual: https://pandoc.org/MANUAL.html
Fewer features (e.g., no support for citations or figure captions at the moment)
Fewer output formats
Primarily supports HTML and LaTeX output
No support for Word, PowerPoint, or EPUB, etc.
commonmark | markdown | rmarkdown | |
---|---|---|---|
Installation | commonmark: 1.1 Mb | markdown: 2 Mb | rmarkdown: 83 Mb, Pandoc: 152 Mb (or RStudio: 1.7 Gb) |
Rendering | fastest | fast | slower |
Output file size | N/A | small (start from ~3 Kb) | big (start from ~800 Kb) |
Learning | easy | easy | it depends |
Features | minimal | moderate | rich |
The markdown package was born in 2012 (a decade ago…): https://github.com/rstudio/markdown
It has been almost retired since 2016 (when rmarkdown became mature)
Originally based on C library sundown; switched to commonmark in late 2022
Rewritten in early 2023 (hence revived)
markdown::mark()
I’m using markdown v1.7 today:
install.packages('markdown')
# packageVersion('markdown') >= '1.7'
The core function is markdown::mark()
:
cat(markdown::mark('Hello **world**!', format = 'latex'))
#> Hello \textbf{world}!
cat(markdown::mark('Hello **world**!', format = 'html'))
#> <p>Hello <strong>world</strong>!</p>
markdown::mark()
generates a fragment of HTML/LaTeX code by default.
In practice, it’s more common to generate a full document.
You can use markdown::mark_html()
or markdown::mark_latex()
.
markdown::mark_html('file.md') # geneates file.html
markdown::mark_latex('file.md') # geneates file.tex
# enable table of contents
markdown::mark_html('file.md', options = list(toc = TRUE))
Or specify output formats in the YAML metadata.
---
title: "An Example Document"
output:
markdown::html_format:
options: ...
meta: ...
markdown::latex_format: ...
---
This way can be easier because you can click the Knit
button in RStudio to
render a document, and more importantly, the configurations like options
and meta
can be specified inside the document.
The argument options
of markdown::*_format
controls Markdown features, e.g.,
whether to enable TOC (table of contents) or section numbering:
---
output:
markdown::html_format:
options:
toc: true
number_sections: true
---
The full list of available options:
vignette('intro', package = 'markdown')
To render a full document, we need a template. For example, this is a simple HTML template:
<html>
<head>
<title>$title$</title>
<style type="text/css">$css$</style>
</head>
<body>$body$</body>
</html>
markdown::mark()
generates the document body, and the rest of template
$variables$
get their values from metadata (see the next slide).
The argument meta
of markdown::*_format
contains metadata variables to be
passed to the template.
output:
markdown::html_format:
meta:
title: "A different title"
css: "custom.css"
markdown::latex_format:
meta:
documentclass: "book"
header_includes: "\\usepackage{microtype}"
You can set options
Change meta
variables
Use a custom template
output:
markdown::html_format:
template: "your-template.html"
---
output:
markdown::html_format:
meta:
css: [default, slides]
js: [slides]
---
You can learn more in
vignette('slides', package = 'markdown')
.
---
output:
markdown::html_format:
meta:
css: ["default", "@xiee/utils/css/article.min.css"]
js: ["@xiee/utils/js/sidenotes.min.js,appendix.min.js"]
---
Learn more in
vignette('article', package = 'markdown')
.
I have been thinking about a question in recent years:
Why has it become so rare that a software package can declare being “feature complete”? In other words, why is it so hard to reach “feature complete” now?
Where have the old days of “do one thing and do it well” gone?
Developing software is often like playing an infinite game now, which can become exhausting.
I’m happy to declare that the markdown package is mostly feature complete: it has included all features that I want from Markdown.
Questions?
Try Stack Overflow or RStudio Community
Then Github issues, e.g., https://github.com/rstudio/markdown/issues
If you want my public help, use https://github.com/yihui/yihui.org/discussions
If your question involves privacy and you must reach me privately: https://yihui.org/en/about/#contact-me