From 8e4c24df550a8c8ae8a2c784ad9e6fe7f6b0963c Mon Sep 17 00:00:00 2001 From: Yihui Xie Date: Wed, 8 Jul 2026 19:06:01 -0400 Subject: [PATCH] Document previously undocumented features Complete documentation for features that existed in the source code but were missing from the book chapters under docs/: - 02-fuse: add a "Helper functions" section covering get_context(), fuse_env(), fuse_exit(), raw_text(), and timing_data(); document the exec engine's `ext` chunk option. - 04-mark: document the cross_refs option, the plain-title and generator HTML meta variables, and the full set of format fields (template, keep_md, keep_tex, latex_engine, citation_package). - 08-site: document the top-level `type` field, the book `time` field, the numeric `rebuild` value, and a new "Default assets and layout" section (auto nav menu, copyright footer, default css/js, css2/js2, absolute-path rewriting). - 07-editor: document the new-file wizard (feature checkboxes, filename datalist, auto .Rmd extension, seeded YAML) and rendering a whole project. - examples: add 027-raw-text to demonstrate raw_text(). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/02-fuse.Rmd | 112 ++++++++++++++++++++++++++++++++++++++ docs/04-mark.Rmd | 51 ++++++++++++++++- docs/07-editor.Rmd | 26 ++++++++- docs/08-site.Rmd | 74 +++++++++++++++++++++++++ examples/027-raw-text.Rmd | 20 +++++++ examples/027-raw-text.md | 36 ++++++++++++ 6 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 examples/027-raw-text.Rmd create mode 100644 examples/027-raw-text.md diff --git a/docs/02-fuse.Rmd b/docs/02-fuse.Rmd index b16ed0f..0e9678f 100644 --- a/docs/02-fuse.Rmd +++ b/docs/02-fuse.Rmd @@ -1316,6 +1316,112 @@ in your `.Rprofile` to make **litedown** recognize `` `r code` ``, but we recommend that you convert the document via `litedown:::convert_knitr()` instead if you decide to stay with **litedown** in the long run. +## Helper functions {#sec:helpers} + +Inside a code chunk, you can call a few helper functions to interact with the +`fuse()` process, such as querying the context, exiting early, adding raw +output, and getting the timing data. + +### Query the context {#sec:get-context} + +The function `litedown::get_context()` returns information about the current +`fuse()` process, which can be useful when you need to know things like the +input file path or the output format inside a code chunk. Call +`get_context('NAME')` to get a specific item, or `get_context()` to get the +whole context environment. + +The most useful items include: + +- `input`: The input file path (or the input name if the input is text). + +- `full_input`: The full (normalized) path to the input file, if the input is + a file. + +- `format`: The output format name, e.g., `html` or `latex`. This can be + useful when you want to generate different output according to the format, + e.g., + + ```` md + ```{r, results = 'asis', echo = FALSE} + if (litedown::get_context('format') == 'latex') + cat('This paragraph only appears in LaTeX output.') + ``` + ```` + +Other items are mostly for internal use, and you can see their names via +`names(get_context())`. + +### The evaluation environment {#sec:fuse-env} + +The function `litedown::fuse_env()` returns the environment in which the code +chunks and inline code expressions are evaluated (i.e., the `envir` argument of +`fuse()`). Outside `fuse()`, it returns the global environment. This can be +useful if you want to programmatically get or assign variables in the +evaluation environment, e.g., `assign('x', 1, envir = litedown::fuse_env())`. + +### Exit early {#sec:fuse-exit} + +The function `litedown::fuse_exit()` stops `fuse()` from processing the +remaining code chunks and text blocks, i.e., it ends the document early. This +can be useful when you want to conditionally discard the rest of a document, +e.g., + +```` md +```{r} +if (nrow(data) == 0) litedown::fuse_exit() +``` +```` + +You can pass a character string to its `append` argument, which will be +appended to the output after the current code chunk, e.g., +`fuse_exit('The data is empty, so the report ends here.')`. + +### Raw output {#sec:raw-text} + +The function `litedown::raw_text()` marks a character vector as raw output, +which has the same effect as the chunk option `results = 'asis'` +(@sec:option-results), i.e., the text is written to the output verbatim (and +interpreted as Markdown). The advantage is that you do not have to set +`results = 'asis'` for the whole chunk, so you can mix normal output with raw +output in the same chunk. For example: + +```` md +```{r} +1 + 1 # normal output +litedown::raw_text('A **raw** paragraph.') # raw output +``` +```` + +If you provide a `format` argument (e.g., `html` or `latex`), the text will be +wrapped in a raw block (@sec:raw-latex-html-blocks) for that format, so it will +only appear in the corresponding output, e.g., `raw_text('Bold', 'html')` +generates a raw HTML block that only appears in HTML output. + +`{r} c(.ex(27), .ex(27, '.md'))` + +### Timing data {#sec:timing-data} + +As mentioned in @sec:option-time, when the chunk option `time = TRUE` is set, +the execution time of code chunks will be recorded, and you can retrieve the +data via `litedown::timing_data()`, which returns a data frame containing the +input file paths, line numbers, chunk labels, and time. It takes three +arguments: + +- `threshold`: Only chunks with time above this threshold (in seconds) are + returned. The default is `0` (i.e., all chunks are returned). + +- `sort`: Whether to sort the data by time in the decreasing order (`TRUE` by + default), so the slowest chunks appear first. + +- `total`: Whether to append a row for the total time (`TRUE` by default). + +By default, the timing data is cleared after each `fuse()` call and is not +available outside `fuse()`. To store the data persistently, set the `time` +option to a file path (instead of `TRUE`). This is necessary when you want to +collect timing data across multiple documents, such as all chapters of a book +(@sec:books)---each document should point the `time` option to the same file. +When you no longer need the timing data, delete this file by yourself. + ## R scripts Besides R Markdown, you can also pass an R script to `fuse()`. You can write @@ -1585,6 +1691,12 @@ BEGIN { print "Hello, world!" } ``` ```` +Some commands require the temporary file to have a specific extension. You can +set the chunk option `ext` to control it. For example, if a command only +accepts `.py` files, you may use `ext = 'py'` so that the chunk body will be +written to a temporary file with the extension `.py`. By default, the temporary +file has no extension, except for the `powershell` engine, which uses `ps1`. + ## Comparison to **knitr** Major differences between **knitr** and **litedown** include: diff --git a/docs/04-mark.Rmd b/docs/04-mark.Rmd index 7278231..d996942 100644 --- a/docs/04-mark.Rmd +++ b/docs/04-mark.Rmd @@ -82,6 +82,12 @@ automatically add the type of reference before the reference number, e.g., `\cref{sec:intro}` may generate `Section 1`, so you do not have to write `Section \ref{sec:intro}`. +### `cross_refs` + +Whether to resolve cross-references (@sec:cross-references). This option is +`true` by default. If you do not use any cross-references in the document, you +can disable it to slightly speed up the rendering. + ### `embed_cleanup` Whether to clean up plot files after they have been embedded in HTML output (see @@ -622,6 +628,19 @@ output: lang: "zh-CN" ``` +#### The `plain-title` variable + +The plain-text version of the title, used in the `` tag of the HTML +output (which appears on the browser tab). It is automatically generated from +the `title` variable by stripping the Markdown markups, but you can override it +if you want a different browser-tab title from the document title. + +#### The `generator` variable + +The value of the `<meta name="generator">` tag in the HTML head, which +indicates the software used to generate the document. By default, it is +`litedown` and the package version. + -------------------------------------------------------------------------------- The following variables are for LaTeX templates: @@ -669,13 +688,39 @@ output: ### 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., +In addition to `meta` and `options`, a few other fields can be specified under +the format name. These fields correspond to the arguments of the output format +functions `litedown::html_format()` and `litedown::latex_format()`. + +The fields supported by both formats are: + +- `template`: The path to a custom template file (@sec:templates). It can also + be a logical value: `true` means to use the default template, and `false` + means to generate only a fragment document without any template. + +- `keep_md`: Whether to keep the intermediate `.md` file generated from the + `.Rmd` input (`false` by default). + +The LaTeX format supports these additional fields: + +- `keep_tex`: Whether to keep the intermediate `.tex` file when the output is + a `.pdf` file (`false` by default). + +- `latex_engine`: The LaTeX engine to compile the `.tex` file to PDF. The + default is `xelatex`. Other common choices include `pdflatex` and + `lualatex`. + +- `citation_package`: The LaTeX package for processing citations + (@sec:citations). Possible values are `natbib` (the default), `biblatex`, + and `none`. + +For example: ``` yaml output: latex: latex_engine: xelatex - keep_md: true + keep_tex: true + citation_package: biblatex template: custom-template.tex ``` diff --git a/docs/07-editor.Rmd b/docs/07-editor.Rmd index d80a81e..b40ec50 100644 --- a/docs/07-editor.Rmd +++ b/docs/07-editor.Rmd @@ -78,7 +78,7 @@ There is a button group at the top right of the preview page. You can also use the keyboard shortcuts `Alt + Left` / `Alt + Right`. - The `add` button (with the plus icon, [+](){.larger}): Create a new `.Rmd` / - `.md` / `.R` file with selected HTML features. + `.md` / `.R` file with selected HTML features (@sec:new-file). - The `refresh` button (with the refresh icon, [⟳](){.larger}): Refresh the page. If you are previewing an `.Rmd` file, refreshing the page will rebuild @@ -99,6 +99,30 @@ before they can take effect. This is important when you are viewing a page inside RStudio or other IDEs, because the viewer may not gain focus automatically, and you will have to explicitly click on it. +### Creating new files {#sec:new-file} + +The `add` button ([+](){.larger}) opens a dialog to create a new file. You type +a filename in the input box (a dropdown list of existing files is provided, and +existing filenames are marked with ❌ so that you do not accidentally overwrite +them). If you do not provide a filename extension, `.Rmd` will be appended +automatically. + +For `.Rmd` / `.md` / `.R` files, you can also select HTML features via +checkboxes, such as callouts (@sec:callout), tabsets (@sec:tabsets), and the +article format (@sec:article). See @tab:assets for the full list of features. +The corresponding CSS/JS assets will be added to the YAML metadata of the new +file automatically. + +The new file will be seeded with a YAML frontmatter containing a placeholder +title, the author name (detected from the system username), and the current +date, so you can start writing immediately. + +### Rendering a whole project + +When you preview the index file of a book or website project (@chp:sites), the +`render` button ([↯](){.larger}) will render the whole project (via +`fuse_book()` or `fuse_site()`) in a new R session and write the output to disk. + ### Cleaning up Previewing `.Rmd` and `.R` files that generate plots will leave `*__files/` diff --git a/docs/08-site.Rmd b/docs/08-site.Rmd index f02a7fc..9cfa6e9 100644 --- a/docs/08-site.Rmd +++ b/docs/08-site.Rmd @@ -14,6 +14,17 @@ 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 to contain a configuration file named `_litedown.yml`. +The project type (book or website) is determined by the presence of a top-level +`book` or `site` field in `_litedown.yml`. If both fields exist, or you want to +be explicit, you can set the top-level `type` field to either `book` or `site`, +e.g., + +``` yaml +type: book +book: + new_session: true +``` + If you want to customize the output formats for books or websites, you should do it in `_litedown.yml`, e.g., @@ -62,6 +73,7 @@ book: pattern: "[.]R?md$" chapter_before: "Information before a chapter." chapter_after: "This chapter was generated from `$input$`." + time: null ``` You can choose whether to render each input file in a new R session, whether to @@ -70,6 +82,15 @@ use `.md` or `.R` files if you want), and additional information to be included before/after each chapter, in which you can use some variables such as `$input$`, which is the path of each input file. +The `time` option provides a convenient way to collect timing data +(@sec:timing-data) across all chapters of a book. It takes a file path where +the timing data is stored (a relative path is interpreted as relative to the +first input file's cache directory). This is equivalent to setting the `time` +chunk option to the same file path in every chapter, but easier to configure in +one place. With this option set, you can print `litedown::timing_data()` in the +last chapter to see the timing data for the whole book. Remember to delete the +data file when you no longer need it. + ### Previewing a single chapter Rendering a whole book may be time-consuming[^08-site-1] and unnecessary when @@ -126,12 +147,65 @@ output: Basically, `include_before` can take a file or text input that will be used as the header of each web page, and `include_after` will be the footer. +The `rebuild` option controls when a page should be rebuilt: + +- `"outdated"` (default): Rebuild a page if the output file is older than the + input file (i.e., the input has been modified since the last build). + +- `"newfile"`: Rebuild a page only if the output file does not exist yet + (i.e., never rebuild existing output). + +- A number: Rebuild a page if the output file is older than the input file by + more than this number of seconds. This is a more relaxed version of + `"outdated"` (which is equivalent to `0`), useful to avoid rebuilding pages + for tiny modification-time differences. + The `standalone` option takes a character vector of filename patterns (supporting wildcards like `*` and `?`). Files matching any pattern will be built with a plain `fuse()` call without site-level CSS, JS, navigation, or footer being injected. This is useful for standalone pages such as slides that need their own self-contained styles and should not inherit the site layout. +### Default assets and layout {#sec:site-defaults} + +When building a website, **litedown** applies a set of default CSS/JS assets and +layout elements so that pages look reasonable without any configuration: + +- The default CSS assets are `@default`, `@article`, `@copy-button`, + `@heading-anchor`, and `@pages`; the default JS assets are `@sidenotes`, + `@appendix`, `@toc-highlight`, `@copy-button`, `@heading-anchor`, and + `@pages`. In other words, each page uses the article format (@sec:article) + by default. + +- If `include_before` is not provided, a navigation menu is automatically + generated from the top-level input files under the site root (plus any + one-level subdirectories that contain an `index.html`, such as + `playground/index.html`). The menu titles are derived from the filenames + (e.g., `about.Rmd` becomes "About", and `index.Rmd` becomes "Home"). + +- If `include_after` is not provided, a copyright footer (`© <year>`) is + automatically added. + +- The options `embed_resources` (@sec:embed-resources) and `toc` (@sec:toc) + default to `false` and `true`, respectively. + +If you want to customize the assets, you should provide the `css` and `js` meta +variables as usual, which will *override* the defaults. If you want to *add* to +the default assets instead of replacing them, use the `css2` and `js2` variables +(which are appended to the built-in defaults), e.g., + +``` yaml +output: + html: + meta: + css2: ["custom.css"] + js2: ["custom.js"] +``` + +Absolute paths in links (i.e., paths starting with `/`) are automatically +rewritten to relative paths, so a link like `[Home](/index.html)` will work +correctly no matter which subdirectory the current page is in. + ## R package documentation {#sec:pkg-site} R package developers can build the full package documentation as either a book diff --git a/examples/027-raw-text.Rmd b/examples/027-raw-text.Rmd new file mode 100644 index 0000000..a83ac5c --- /dev/null +++ b/examples/027-raw-text.Rmd @@ -0,0 +1,20 @@ +--- +title: Raw output via raw_text() +--- + +`raw_text()` writes text to the output verbatim (interpreted as Markdown), so +you can mix normal output with raw output in the same code chunk without setting +`results = 'asis'` for the whole chunk: + +```{r} +1 + 1 # normal verbatim output +litedown::raw_text(c('A **raw** Markdown paragraph, e.g.,', + 'a bullet list:', '', '- one', '- two')) +``` + +With the `format` argument, the text is wrapped in a raw block that only appears +in the corresponding output format: + +```{r} +litedown::raw_text('<span style="color: red;">Red (HTML only).</span>', 'html') +``` diff --git a/examples/027-raw-text.md b/examples/027-raw-text.md new file mode 100644 index 0000000..da52c6a --- /dev/null +++ b/examples/027-raw-text.md @@ -0,0 +1,36 @@ +--- +title: Raw output via raw_text() +--- + +`raw_text()` writes text to the output verbatim (interpreted as Markdown), so +you can mix normal output with raw output in the same code chunk without setting +`results = 'asis'` for the whole chunk: + +``` {.r} +1 + 1 # normal verbatim output +``` + +``` +#> [1] 2 +``` + +``` {.r} +litedown::raw_text(c('A **raw** Markdown paragraph, e.g.,', + 'a bullet list:', '', '- one', '- two')) +``` +A **raw** Markdown paragraph, e.g., +a bullet list: + +- one +- two + +With the `format` argument, the text is wrapped in a raw block that only appears +in the corresponding output format: + +```` {.r} +litedown::raw_text('<span style="color: red;">Red (HTML only).</span>', 'html') +```` + +``` {=html} +<span style="color: red;">Red (HTML only).</span> +```