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 `` 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 (`© `) 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('Red (HTML only).', '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('Red (HTML only).', 'html')
+````
+
+``` {=html}
+Red (HTML only).
+```