diff --git a/.claude/rules/quarto-web-workflow.md b/.claude/rules/quarto-web-workflow.md index 9c75005cd1..c603940167 100644 --- a/.claude/rules/quarto-web-workflow.md +++ b/.claude/rules/quarto-web-workflow.md @@ -8,6 +8,16 @@ Always PR to `main` first for shared content. Never PR directly to `prerelease` for changes that apply to both stable and prerelease. +## `_freeze/` Updates + +Any source change to a `.qmd` that has a `_freeze/` entry — even non-executable content like text or includes — invalidates the freeze hash. A stale hash causes the deploy preview to show the old cached page. + +**Wrong reasoning to avoid:** "I only added markdown, not executable code, so no `_freeze/` update needed." The cache is per-page, not per-cell. + +**Before committing:** `git diff HEAD -- _freeze/` — every edited frozen `.qmd` must have a corresponding `_freeze/` change. (Use `HEAD` to show both staged and unstaged changes.) + +**If the freeze-check hook blocks a commit or push:** run `quarto render ` then commit the updated `_freeze/` output alongside the source change. + ## Avoid duplicating doc content When a plan touches 3+ pages with similar prose, **scan for an existing shared-partial / include pattern in the repo before locking duplication into the plan.** quarto-web uses Quarto's `{{< include _foo.md >}}` shortcode extensively — examples in `docs/computations/` (e.g. `_jupyter-rendering.md`, `_jupyter-install.md`, `_caching-more.md`), `docs/tools/` (`_chunk-options.md`), and `docs/get-started/authoring/` (`_text-editor.md`). Many partials pair `{{< include >}}` with `.content-visible when-meta="..."` so the same source renders differently per consuming page. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000000..e9bc259ba8 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,15 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "bash .githooks/claude-hook.sh" + } + ] + } + ] + } +} diff --git a/.githooks/README.md b/.githooks/README.md new file mode 100644 index 0000000000..3b124ab0ad --- /dev/null +++ b/.githooks/README.md @@ -0,0 +1,11 @@ +# Git Hooks + +This directory contains project git hooks. Activate with: + +```bash +git config core.hooksPath .githooks +``` + +## Hooks + +**`pre-commit`** — Blocks commits where a `.qmd` file with a `_freeze/` entry was edited but `_freeze/` was not updated. Fix: `quarto render `, then commit the updated `_freeze/` output alongside the source. diff --git a/.githooks/check-freeze.sh b/.githooks/check-freeze.sh new file mode 100755 index 0000000000..a5ddd16231 --- /dev/null +++ b/.githooks/check-freeze.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# check-freeze.sh [commit|push] +# +# Checks that _freeze/ hash is current for any .qmd files being committed or pushed. +# Quarto's freeze hash is the MD5 of the source file (LF-normalized). +# Any content change to a page with executable code requires a _freeze/ update. +# +# Compatible with bash 3.2+ (macOS system bash), Linux, and Windows Git Bash. + +# Cross-platform MD5 of stdin, LF-normalized (strips \r before hashing) +md5_lf() { + tr -d '\r' | ( + if command -v md5sum >/dev/null 2>&1; then + md5sum | cut -d' ' -f1 + else + md5 -r | cut -d' ' -f1 + fi + ) +} + +MODE="${1:-commit}" +REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0 +STALE_FILE=$(mktemp) +trap 'rm -f "$STALE_FILE"' EXIT + +if [ "$MODE" = "commit" ]; then + QMDS=$(git diff --cached --name-only 2>/dev/null | grep '\.qmd$' || true) +elif [ "$MODE" = "push" ]; then + REMOTE=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null) || exit 0 + [ -n "$REMOTE" ] || exit 0 + QMDS=$(git diff "${REMOTE}..HEAD" --name-only 2>/dev/null | grep '\.qmd$' || true) +else + exit 0 +fi + +[ -n "$QMDS" ] || exit 0 + +while IFS= read -r qmd; do + [ -n "$qmd" ] || continue + freeze_rel="_freeze/${qmd%.qmd}/execute-results/html.json" + + # Read freeze JSON from git objects, not working tree, to avoid false passes + # when the freeze file is updated on disk but not yet staged. + if [ "$MODE" = "commit" ]; then + freeze_content=$(git show ":${freeze_rel}" 2>/dev/null || git show "HEAD:${freeze_rel}" 2>/dev/null) + else + freeze_content=$(git show "HEAD:${freeze_rel}" 2>/dev/null) + fi + [ -n "$freeze_content" ] || continue + + stored_hash=$(printf '%s' "$freeze_content" | jq -r '.hash // empty' 2>/dev/null) + [ -n "$stored_hash" ] || continue + + if [ "$MODE" = "commit" ]; then + current_hash=$(git show ":$qmd" 2>/dev/null | md5_lf) + else + current_hash=$(git show "HEAD:$qmd" 2>/dev/null | md5_lf) + fi + + [ -n "$current_hash" ] || continue + [ "$current_hash" = "$stored_hash" ] || echo "$qmd" >> "$STALE_FILE" +done <<< "$QMDS" + +if [ -s "$STALE_FILE" ]; then + echo "_freeze/ not updated for:" >&2 + sed 's/^/ /' "$STALE_FILE" >&2 + echo "" >&2 + echo "Run: quarto render then commit the updated _freeze/ output." >&2 + exit 2 +fi + +exit 0 diff --git a/.githooks/claude-hook.sh b/.githooks/claude-hook.sh new file mode 100755 index 0000000000..8c9576473c --- /dev/null +++ b/.githooks/claude-hook.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Claude Code PreToolUse hook: check _freeze/ before git commit or push. +# Reads tool input JSON from stdin, routes to check-freeze.sh. + +COMMAND=$(jq -r '.tool_input.command // ""' 2>/dev/null) + +HOOK_DIR="$(cd "$(dirname "$0")" && pwd)" + +if echo "$COMMAND" | grep -qE 'git[[:space:]]+commit'; then + exec bash "$HOOK_DIR/check-freeze.sh" commit +elif echo "$COMMAND" | grep -qE 'git[[:space:]]+push'; then + exec bash "$HOOK_DIR/check-freeze.sh" push +fi + +exit 0 diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000000..0446d6ac7c --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,6 @@ +#!/bin/bash +# Git pre-commit hook: verify _freeze/ is current for staged .qmd files. +# Setup: git config core.hooksPath .githooks + +HOOK_DIR="$(cd "$(dirname "$0")" && pwd)" +exec bash "$HOOK_DIR/check-freeze.sh" commit diff --git a/_freeze/docs/computations/execution-options/execute-results/html.json b/_freeze/docs/computations/execution-options/execute-results/html.json index 5b5d66984f..00f22c67a7 100644 --- a/_freeze/docs/computations/execution-options/execute-results/html.json +++ b/_freeze/docs/computations/execution-options/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "669153733b808f6c8e1af4a3a39fbde5", + "hash": "b8212fe577789515aeef9a05161f1a86", "result": { "engine": "jupyter", - "markdown": "---\ntitle: Execution Options\nformat: html\n---\n\n## Output Options\n\nThere are a wide variety of options available for customizing output from executed code. All of these options can be specified either globally (in the document front-matter) or per code-block. For example, here's a modification of the Python example to specify that we don't want to \"echo\" the code into the output document:\n\n``` yaml\n---\ntitle: \"My Document\"\nexecute:\n echo: false\njupyter: python3\n---\n```\n\nNote that we can override this option on a per code-block basis. For example:\n\n```{{python}}\n#| echo: true\n\nimport matplotlib.pyplot as plt\nplt.plot([1,2,3,4])\nplt.show()\n```\n\nCode block options are included in a special comment at the top of the block (lines at the top prefaced with `#|` are considered options).\n\nOptions available for customizing output include:\n\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| Option | Description |\n+==============+===================================================================================================================================================================================================+\n| `eval` | Evaluate the code chunk (if `false`, just echos the code into the output). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `echo` | Include the source code in output |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `output` | Include the results of executing the code in the output (`true`, `false`, or `asis` to indicate that the output is raw markdown and should not have any of Quarto's standard enclosing markdown). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `warning` | Include warnings in the output. |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `error` | Include errors in the output (note that this implies that errors executing code will not halt processing of the document). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `include` | Catch all for preventing any output (code or results) from being included (e.g. `include: false` suppresses all output from the code block). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `renderings` | Specify rendering names for the plot or table outputs of the cell, e.g. `[light, dark]` |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n\nHere's a Knitr example with some of these additional options included:\n\n```` \n---\ntitle: \"Knitr Document\"\nexecute:\n echo: false\n---\n\n```{{r}}\n#| warning: false\n\nlibrary(ggplot2)\nggplot(airquality, aes(Temp, Ozone)) + \n geom_point() + \n geom_smooth(method = \"loess\", se = FALSE)\n```\n\n```{{r}}\nsummary(airquality)\n```\n````\n\n### Cell Renderings\n\nHere is an example of using `renderings` to provide light and dark versions of a plot. Note that the number of cell outputs must match the number of renderings.\n\n````\n---\ntitle: \"Dark mode\"\nformat: \n html:\n theme:\n light: flatly\n dark: darkly\n---\n\n```{{r}}\n#| renderings: [light, dark]\npar(bg = \"#FFFFFF\", fg = \"#000000\")\nplot(1:10) # Shown in `light` mode\n\npar(bg = \"#000000\", fg = \"#FFFFFF\", col.axis = \"#FFFFFF\")\nplot(1:10) # Shown in `dark` mode\n```\n````\n\n::: {layout-ncol=2}\n\n![light rendering](images/renderings-light-mode.png)\n\n![dark rendering](images/renderings-dark-mode.png)\n\n:::\n\nThe `renderings` cell option does not currently work correctly with cell cross-reference options (`label` starting with `fig-`, `tbl-`, etc.) or cell caption options (`fig-cap`, `tbl-cap`, etc.).\n\n\nTo combine `renderings` with crossrefs and/or captions, use the fenced div syntax:\n\n\n````\n---\ntitle: \"Dark mode\"\nformat:\n html:\n theme:\n light: flatly\n dark: darkly\n---\n\n::: {#fig-caption-crossref}\n\n```{{r}}\n#| label: caption-crossref\n#| renderings: [light, dark]\npar(bg = \"#FFFFFF\", fg = \"#000000\")\nplot(1:10) # Shown in `light` mode\n\n\npar(bg = \"#000000\", fg = \"#FFFFFF\", col.axis = \"#FFFFFF\")\nplot(1:10) # Shown in `dark` mode\n```\n\nLight and dark renderings with a caption and crossref\n\n:::\n````\n\nNote the use of a `label` that is not a cross-reference, i.e. that does not start with one of the [cross reference types](../authoring/cross-references.qmd#overview). It is a good practice to have named cells with `label`, for debuggability and stable resource names. However, cross-reference labels that start with `fig-`, `tbl-`, etc., will not work with `renderings`.\n\n\n\n::: callout-tip\nWhen using the Knitr engine, you can also use any of the available native options (e.g. `collapse`, `tidy`, `comment`, etc.). See the [Knitr options documentation](https://yihui.org/knitr/options/) for additional details. You can include these native options in option comment blocks as shown above, or on the same line as the `{r}` as shown in the Knitr documentation.\n:::\n\n::: callout-tip\nThe Knitr engine can also *conditionally* evaluate a code chunk using objects or expressions. See [Using R: Knitr Options](r.qmd#chunk-options).\n:::\n\n## Figure Options\n\nThere are a number of ways to control the default width and height of figures generated from code. First, it's important to know that Quarto sets a default width and height for figures appropriate to the target output format. Here are the defaults (expressed in inches):\n\n| Format | Default |\n|-------------------------|-----------|\n| Default | 7 x 5 |\n| HTML Slides | 9.5 x 6.5 |\n| HTML Slides (reveal.js) | 9 x 5 |\n| PDF | 5.5 x 3.5 |\n| PDF Slides (Beamer) | 10 x 7 |\n| PowerPoint | 7.5 x 5.5 |\n| MS Word, ODT, RTF | 5 x 4 |\n| EPUB | 5 x 4 |\n| Hugo | 8 x 5 |\n\nThese defaults were chosen to provide attractive well proportioned figures, but feel free to experiment to see whether you prefer another default size. You can change the default sizes using the `fig-width` and `fig-height` options. For example:\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: \n html:\n fig-width: 8\n fig-height: 6\n pdf:\n fig-width: 7\n fig-height: 5\n---\n```\n\nHow do these sizes make their way into the engine-level defaults for generating figures? This differs by engine:\n\n- For the Knitr engine, these values become the default values for the `fig.width` and `fig.height` chunk options. You can override these default values via chunk level options.\n\n- For Python, these values are used to set the [Matplotlib](https://matplotlib.org/stable/tutorials/introductory/customizing.html) `figure.figsize` rcParam (you can of course manually override these defaults for any given plot).\n\n- For Julia, these values are used to initialize the default figure size for the [Plots.jl](https://docs.juliaplots.org/stable/) GR backend.\n\n If you are using another graphics library with Jupyter and want to utilize these values, you can read them from `QUARTO_FIG_WIDTH` and `QUARTO_FIG_HEIGHT` environment variables.\n\n::: callout-caution\nWhen using the Jupyter engine, `fig-width` and `fig-height` are only supported if specified at the document- or project-level. \nHowever, when using the Knitr engine, these options are also supported as code cell options on a per-cell basis.\n:::\n\n### Caption and Alt Text\n\nYou can specify the caption and alt text for figures generated from code using the `fig-cap` and `fig-alt` options. For example, here we add these options to a Python code cell that creates a plot:\n\n```{{python}}\n#| fig-cap: \"Polar axis plot\"\n#| fig-alt: \"A line plot on a polar axis\"\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nr = np.arange(0, 2, 0.01)\ntheta = 2 * np.pi * r\nfig, ax = plt.subplots(subplot_kw={'projection': 'polar'})\nax.plot(theta, r)\nax.set_rticks([0.5, 1, 1.5, 2])\nax.grid(True)\nplt.show()\n```\n\n## Inline Code\n\nJupyter, Knitr and OJS all support executing inline code within markdown (e.g. to allow narrative to automatically use the most up to date computations). See [Inline Code](inline-code.qmd) for details.\n\n## Raw Output\n\nThe `output: asis` option enables you to generate raw markdown output. When `output: asis` is specified none of Quarto's standard enclosing divs will be included. For example, here we specify `output: asis` in order to generate a pair of headings:\n\n::: panel-tabset\n## Jupyter\n\n```{{python}}\n#| echo: false\n#| output: asis\n\nprint(\"# Heading 1\\n\")\nprint(\"## Heading 2\\n\")\n```\n\n## Knitr\n\n```{{r}}\n#| echo: false\n#| output: asis\n\ncat(\"# Heading 1\\n\")\ncat(\"## Heading 2\\n\")\n```\n:::\n\nWhich generates the following output:\n\n``` default\n# Heading 1\n\n## Heading 2\n```\n\nNote that we also include the `echo: false` option to ensure that the code used to generate markdown isn't included in the final output.\n\nIf we had not specified `output: asis` the output, as seen in the intermediate markdown, would have included Quarto's `.cell-output` div:\n\n```` default\n::: {.cell-output-stdout}\n```\n# Heading 1\n\n## Heading 2\n \n```\n:::\n````\n\nFor the Jupyter engine, you can also create raw markdown output using the functions in `IPython.display`. For example:\n\n```{{python}}\n#| echo: false\nradius = 10\nfrom IPython.display import Markdown\nMarkdown(f\"The _radius_ of the circle is **{radius}**.\")\n```\n\n## Knitr Options\n\nIf you are using the Knitr cell execution engine, you can specify default document-level [Knitr chunk options](https://yihui.org/knitr/options/) in YAML. For example:\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: html\nknitr:\n opts_chunk: \n collapse: true\n comment: \"#>\" \n R.options:\n knitr.graphics.auto_pdf: true\n---\n```\n\nYou can additionally specify global Knitr options using `opts_knit`.\n\nThe `R.options` chunk option is a convenient way to define R options that are set temporarily via [`options()`](https://rdrr.io/r/base/options.html) before the code chunk execution, and immediately restored afterwards.\n\nIn the example above, we establish default Knitr chunk options for a single document. You can also add shared `knitr` options to a project-wide `_quarto.yml` file or a project-directory scoped `_metadata.yml` file.\n\n\n## Jupyter Options\n\n### Expression Printing\n\nWhen multiple expressions are present in a code cell, by default, only the last top-level expression is captured in the rendered output. For example, consider the code cell:\n\n::: {layout-ncol=\"2\"}\n```` markdown\n```{{python}}\n\"first\"\n\"last\"\n```\n````\n:::\n\nWhen rendered to HTML the output generated is:\n\n``` markdown\n'last'\n```\n\nThis behavior corresponds to the `last_expr` setting for [Jupyter shell interactivity](https://ipython.readthedocs.io/en/stable/config/options/terminal.html#configtrait-InteractiveShell.ast_node_interactivity).\n\nYou can control this behavior with the `ipynb-shell-interactivity` option. For example, to capture all top-level expressions set it to `all`:\n\n``` yaml\n---\ntitle: All expressions\nformat: html\nipynb-shell-interactivity: all\n---\n```\n\nNow the above code cell results in the output:\n\n``` markdown\n'first'\n\n'last'\n```\n\n::: callout-note\n## All Expressions are Printed in Dashboards\n\nFor [dashboards](/docs/dashboards/index.qmd) the default setting of `ipynb-shell-interactivity` is `all.`\n:::\n\n## Intermediates\n\nOn the way from markdown input to final output, there are some intermediate files that are created and automatically deleted at the end of rendering. You can use the following options to keep these intermediate files:\n\n+--------------+------------------------------------------------------------------------------------------------+\n| Option | Description |\n+==============+================================================================================================+\n| `keep-md` | Keep the markdown file generated by executing code. |\n+--------------+------------------------------------------------------------------------------------------------+\n| `keep-ipynb` | Keep the notebook file generated from executing code (applicable only to markdown input files) |\n+--------------+------------------------------------------------------------------------------------------------+\n\nFor example, here we specify that we want to keep the jupyter intermediate file after rendering:\n\n``` yaml\n---\ntitle: \"My Document\"\nexecute:\n keep-ipynb: true\njupyter: python3\n---\n```\n\n## Fenced Echo\n\nIf you are writing a tutorial or documentation on using Quarto code blocks, you'll likely want to include the fenced code delimiter (e.g. ```` ```{python} ````) in your code output to emphasize that executable code requires that delimiter. You can do this using the `echo: fenced` option. For example, the following code block:\n\n```{{python}}\n#| echo: fenced\n1 + 1\n```\n\nWill be rendered as:\n\n::: {#a4df9156 .cell execution_count=1}\n```` { .cell-code}\n```{{python}}\n1 + 1\n```\n\n````\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\n2\n```\n:::\n:::\n\n\nThis is especially useful when you want to demonstrate the use of cell options. For example, here we demonstrate the use of the `output` and `code-overflow` options:\n\n```{{python}}\n#| echo: fenced\n#| output: false\n#| code-overflow: wrap\n1 + 1\n```\n\nThis code block appears in the rendered document as:\n\n::: {#dec0287c .cell execution_count=2}\n```` { .cell-code .code-overflow-wrap}\n```{{python}}\n#| output: false\n#| code-overflow: wrap\n1 + 1\n```\n\n````\n:::\n\n\nNote that all YAML options will be included in the fenced code output *except for* `echo: fenced` (as that might be confusing to readers).\n\nThis behavior can also be specified at the document level if you want all of your executable code blocks to include the fenced delimiter and YAML options:\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: html\nexecute:\n echo: fenced\n---\n```\n\n#### Unexecuted Blocks\n\n\n\nOften you'll want to include a fenced code block purely as documentation (not executable). You can do this by using two curly braces around the language (e.g. `python`, `r`, etc.) rather than one. For example:\n\n```{{{python}}}\n1 + 1\n```\n\nWill be output into the document as:\n\n```{{python}}\n1 + 1\n```\n\nIf you want to show an example with multiple code blocks and other markdown, just enclose the entire example in 4 backticks (e.g. ````` ```` `````) and use the two curly brace syntax for code blocks within. For example:\n\n ````\n ---\n title: \"My document\"\n ---\n\n Some markdown content.\n\n ```{{{python}}}\n 1 + 1\n ```\n\n Some additional markdown content.\n\n ````\n\n\n## Engine Binding\n\nEarlier we said that the engine used for computations was determined automatically. You may want to customize this---for example you may want to use the Jupyter [R kernel](https://github.com/IRkernel/IRkernel) rather than Knitr, or you may want to use Knitr with Python code (via [reticulate](https://rstudio.github.io/reticulate/)).\n\nHere are the basic rules for automatic binding:\n\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| Extension | Engine Binding |\n+===========+========================================================================================================================================================================================================================================+\n| .qmd | Use Knitr engine if an `{r}` code block is discovered within the file |\n| | |\n| | Use Jupyter engine if *any other* executable code block (e.g. `{python}`, `{julia}`, `{bash}`, etc.) is discovered within the file. The kernel used is determined based on the language of the first executable code block discovered. |\n| | |\n| | Use no engine if no executable code blocks are discovered. |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| .ipynb | Jupyter engine |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| .Rmd | Knitr engine |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| .md | No engine (note that if an `md` document does contain executable code blocks then an error will occur) |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n\n::: callout-note\n\n## Using python and r together\n\nIf your quarto document includes both `{python}` and `{r}` code blocks, then quarto will automatically use Knitr engine and [reticulate](https://rstudio.github.io/reticulate/) R package to execute the python content.\n:::\n\nFor `.qmd` files in particular, you can override the engine used via the `engine` option. For example:\n\n``` markdown\nengine: jupyter\n```\n\n``` markdown\nengine: knitr\n```\n\nYou can also specify that no execution engine should be used via `engine: markdown`.\n\nThe presence of the `knitr` or `jupyter` option will also override the default engine:\n\n``` markdown\nknitr: true\n```\n\n``` markdown\njupyter: python3\n```\n\nVariations with additional engine-specific options also work to override the default engine:\n\n``` markdown\nknitr:\n opts_knit:\n verbose: true\n```\n\n``` markdown\njupyter:\n kernelspec:\n display_name: Python 3\n language: python\n name: python3\n```\n\n## Shell Commands\n\nUsing shell commands (from Bash, Zsh, etc.) within Quarto computational documents differs by engine. If you are using the Jupyter engine you can use [Jupyter shell magics](https://jakevdp.github.io/PythonDataScienceHandbook/01.05-ipython-and-shell-commands.html). For example:\n\n```` markdown\n---\ntitle: \"Using Bash\"\nengine: jupyter\n---\n\n```{{python}}\n!echo \"foo\"\n```\n````\n\nNote that `!` preceding `echo` is what enables a Python cell to be able to execute a shell command.\n\nIf you are using the Knitr engine you can use ```` ```{bash} ```` cells, for example:\n\n```` markdown\n---\ntitle: \"Using Bash\"\nengine: knitr\n---\n\n```{{bash}}\necho \"foo\" \n```\n````\n\nNote that the Knitr engine also supports ```` ```{python} ```` cells, enabling the combination of R, Python, and Bash in the same document\n\n", + "markdown": "---\ntitle: Execution Options\nformat: html\n---\n\n## Output Options\n\nThere are a wide variety of options available for customizing output from executed code. All of these options can be specified either globally (in the document front-matter) or per code-block. For example, here's a modification of the Python example to specify that we don't want to \"echo\" the code into the output document:\n\n``` yaml\n---\ntitle: \"My Document\"\nexecute:\n echo: false\njupyter: python3\n---\n```\n\nNote that we can override this option on a per code-block basis. For example:\n\n```{{python}}\n#| echo: true\n\nimport matplotlib.pyplot as plt\nplt.plot([1,2,3,4])\nplt.show()\n```\n\nCode block options are included in a special comment at the top of the block (lines at the top prefaced with `#|` are considered options).\n\nOptions available for customizing output include:\n\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| Option | Description |\n+==============+===================================================================================================================================================================================================+\n| `eval` | Evaluate the code chunk (if `false`, just echos the code into the output). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `echo` | Include the source code in output |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `output` | Include the results of executing the code in the output (`true`, `false`, or `asis` to indicate that the output is raw markdown and should not have any of Quarto's standard enclosing markdown). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `warning` | Include warnings in the output. |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `error` | Include errors in the output (note that this implies that errors executing code will not halt processing of the document). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `include` | Catch all for preventing any output (code or results) from being included (e.g. `include: false` suppresses all output from the code block). |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| `renderings` | Specify rendering names for the plot or table outputs of the cell, e.g. `[light, dark]` |\n+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n\nHere's a Knitr example with some of these additional options included:\n\n```` \n---\ntitle: \"Knitr Document\"\nexecute:\n echo: false\n---\n\n```{{r}}\n#| warning: false\n\nlibrary(ggplot2)\nggplot(airquality, aes(Temp, Ozone)) + \n geom_point() + \n geom_smooth(method = \"loess\", se = FALSE)\n```\n\n```{{r}}\nsummary(airquality)\n```\n````\n\n### Cell Renderings\n\nHere is an example of using `renderings` to provide light and dark versions of a plot. Note that the number of cell outputs must match the number of renderings.\n\n````\n---\ntitle: \"Dark mode\"\nformat: \n html:\n theme:\n light: flatly\n dark: darkly\n---\n\n```{{r}}\n#| renderings: [light, dark]\npar(bg = \"#FFFFFF\", fg = \"#000000\")\nplot(1:10) # Shown in `light` mode\n\npar(bg = \"#000000\", fg = \"#FFFFFF\", col.axis = \"#FFFFFF\")\nplot(1:10) # Shown in `dark` mode\n```\n````\n\n::: {layout-ncol=2}\n\n![light rendering](images/renderings-light-mode.png)\n\n![dark rendering](images/renderings-dark-mode.png)\n\n:::\n\nThe `renderings` cell option does not currently work correctly with cell cross-reference options (`label` starting with `fig-`, `tbl-`, etc.) or cell caption options (`fig-cap`, `tbl-cap`, etc.).\n\n\nTo combine `renderings` with crossrefs and/or captions, use the fenced div syntax:\n\n\n````\n---\ntitle: \"Dark mode\"\nformat:\n html:\n theme:\n light: flatly\n dark: darkly\n---\n\n::: {#fig-caption-crossref}\n\n```{{r}}\n#| label: caption-crossref\n#| renderings: [light, dark]\npar(bg = \"#FFFFFF\", fg = \"#000000\")\nplot(1:10) # Shown in `light` mode\n\n\npar(bg = \"#000000\", fg = \"#FFFFFF\", col.axis = \"#FFFFFF\")\nplot(1:10) # Shown in `dark` mode\n```\n\nLight and dark renderings with a caption and crossref\n\n:::\n````\n\nNote the use of a `label` that is not a cross-reference, i.e. that does not start with one of the [cross reference types](../authoring/cross-references.qmd#overview). It is a good practice to have named cells with `label`, for debuggability and stable resource names. However, cross-reference labels that start with `fig-`, `tbl-`, etc., will not work with `renderings`.\n\n\n\n::: callout-tip\nWhen using the Knitr engine, you can also use any of the available native options (e.g. `collapse`, `tidy`, `comment`, etc.). See the [Knitr options documentation](https://yihui.org/knitr/options/) for additional details. You can include these native options in option comment blocks as shown above, or on the same line as the `{r}` as shown in the Knitr documentation.\n:::\n\n::: callout-tip\nThe Knitr engine can also *conditionally* evaluate a code chunk using objects or expressions. See [Using R: Knitr Options](r.qmd#chunk-options).\n:::\n\n## Figure Options\n\nThere are a number of ways to control the default width and height of figures generated from code. First, it's important to know that Quarto sets a default width and height for figures appropriate to the target output format. Here are the defaults (expressed in inches):\n\n| Format | Default |\n|-------------------------|-----------|\n| Default | 7 x 5 |\n| HTML Slides | 9.5 x 6.5 |\n| HTML Slides (reveal.js) | 9 x 5 |\n| PDF | 5.5 x 3.5 |\n| PDF Slides (Beamer) | 10 x 7 |\n| PowerPoint | 7.5 x 5.5 |\n| MS Word, ODT, RTF | 5 x 4 |\n| EPUB | 5 x 4 |\n| Hugo | 8 x 5 |\n\nThese defaults were chosen to provide attractive well proportioned figures, but feel free to experiment to see whether you prefer another default size. You can change the default sizes using the `fig-width` and `fig-height` options. For example:\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: \n html:\n fig-width: 8\n fig-height: 6\n pdf:\n fig-width: 7\n fig-height: 5\n---\n```\n\nHow do these sizes make their way into the engine-level defaults for generating figures? This differs by engine:\n\n- For the Knitr engine, these values become the default values for the `fig.width` and `fig.height` chunk options. You can override these default values via chunk level options.\n\n- For Python, these values are used to set the [Matplotlib](https://matplotlib.org/stable/tutorials/introductory/customizing.html) `figure.figsize` rcParam (you can of course manually override these defaults for any given plot).\n\n- For Julia, these values are used to initialize the default figure size for the [Plots.jl](https://docs.juliaplots.org/stable/) GR backend.\n\n If you are using another graphics library with Jupyter and want to utilize these values, you can read them from `QUARTO_FIG_WIDTH` and `QUARTO_FIG_HEIGHT` environment variables.\n\n::: callout-caution\nWhen using the Jupyter engine, `fig-width` and `fig-height` are only supported if specified at the document- or project-level. \nHowever, when using the Knitr engine, these options are also supported as code cell options on a per-cell basis.\n:::\n\n### Caption and Alt Text\n\nYou can specify the caption and alt text for figures generated from code using the `fig-cap` and `fig-alt` options. For example, here we add these options to a Python code cell that creates a plot:\n\n```{{python}}\n#| fig-cap: \"Polar axis plot\"\n#| fig-alt: \"A line plot on a polar axis\"\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nr = np.arange(0, 2, 0.01)\ntheta = 2 * np.pi * r\nfig, ax = plt.subplots(subplot_kw={'projection': 'polar'})\nax.plot(theta, r)\nax.set_rticks([0.5, 1, 1.5, 2])\nax.grid(True)\nplt.show()\n```\n\n## Inline Code\n\nJupyter, Knitr and OJS all support executing inline code within markdown (e.g. to allow narrative to automatically use the most up to date computations). See [Inline Code](inline-code.qmd) for details.\n\n## Raw Output\n\nThe `output: asis` option enables you to generate raw markdown output. When `output: asis` is specified none of Quarto's standard enclosing divs will be included. For example, here we specify `output: asis` in order to generate a pair of headings:\n\n::: panel-tabset\n## Jupyter\n\n```{{python}}\n#| echo: false\n#| output: asis\n\nprint(\"# Heading 1\\n\")\nprint(\"## Heading 2\\n\")\n```\n\n## Knitr\n\n```{{r}}\n#| echo: false\n#| output: asis\n\ncat(\"# Heading 1\\n\")\ncat(\"## Heading 2\\n\")\n```\n:::\n\nWhich generates the following output:\n\n``` default\n# Heading 1\n\n## Heading 2\n```\n\nNote that we also include the `echo: false` option to ensure that the code used to generate markdown isn't included in the final output.\n\nIf we had not specified `output: asis` the output, as seen in the intermediate markdown, would have included Quarto's `.cell-output` div:\n\n```` default\n::: {.cell-output-stdout}\n```\n# Heading 1\n\n## Heading 2\n \n```\n:::\n````\n\nFor the Jupyter engine, you can also create raw markdown output using the functions in `IPython.display`. For example:\n\n```{{python}}\n#| echo: false\nradius = 10\nfrom IPython.display import Markdown\nMarkdown(f\"The _radius_ of the circle is **{radius}**.\")\n```\n\n## Knitr Options\n\nIf you are using the Knitr cell execution engine, you can specify default document-level [Knitr chunk options](https://yihui.org/knitr/options/) in YAML. For example:\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: html\nknitr:\n opts_chunk: \n collapse: true\n comment: \"#>\" \n R.options:\n knitr.graphics.auto_pdf: true\n---\n```\n\nYou can additionally specify global Knitr options using `opts_knit`.\n\nThe `R.options` chunk option is a convenient way to define R options that are set temporarily via [`options()`](https://rdrr.io/r/base/options.html) before the code chunk execution, and immediately restored afterwards.\n\nIn the example above, we establish default Knitr chunk options for a single document. You can also add shared `knitr` options to a project-wide `_quarto.yml` file or a project-directory scoped `_metadata.yml` file.\n\n\n## Jupyter Options\n\n### Expression Printing\n\nWhen multiple expressions are present in a code cell, by default, only the last top-level expression is captured in the rendered output. For example, consider the code cell:\n\n::: {layout-ncol=\"2\"}\n```` markdown\n```{{python}}\n\"first\"\n\"last\"\n```\n````\n:::\n\nWhen rendered to HTML the output generated is:\n\n``` markdown\n'last'\n```\n\nThis behavior corresponds to the `last_expr` setting for [Jupyter shell interactivity](https://ipython.readthedocs.io/en/stable/config/options/terminal.html#configtrait-InteractiveShell.ast_node_interactivity).\n\nYou can control this behavior with the `ipynb-shell-interactivity` option. For example, to capture all top-level expressions set it to `all`:\n\n``` yaml\n---\ntitle: All expressions\nformat: html\nipynb-shell-interactivity: all\n---\n```\n\nNow the above code cell results in the output:\n\n``` markdown\n'first'\n\n'last'\n```\n\n::: callout-note\n## All Expressions are Printed in Dashboards\n\nFor [dashboards](/docs/dashboards/index.qmd) the default setting of `ipynb-shell-interactivity` is `all.`\n:::\n\n## Intermediates\n\nOn the way from markdown input to final output, there are some intermediate files that are created and automatically deleted at the end of rendering. You can use the following options to keep these intermediate files:\n\n+--------------+------------------------------------------------------------------------------------------------+\n| Option | Description |\n+==============+================================================================================================+\n| `keep-md` | Keep the markdown file generated by executing code. |\n+--------------+------------------------------------------------------------------------------------------------+\n| `keep-ipynb` | Keep the notebook file generated from executing code (applicable only to markdown input files) |\n+--------------+------------------------------------------------------------------------------------------------+\n\nFor example, here we specify that we want to keep the jupyter intermediate file after rendering:\n\n``` yaml\n---\ntitle: \"My Document\"\nexecute:\n keep-ipynb: true\njupyter: python3\n---\n```\n\n## Fenced Echo\n\nIf you are writing a tutorial or documentation on using Quarto code blocks, you'll likely want to include the fenced code delimiter (e.g. ```` ```{python} ````) in your code output to emphasize that executable code requires that delimiter. You can do this using the `echo: fenced` option. For example, the following code block:\n\n```{{python}}\n#| echo: fenced\n1 + 1\n```\n\nWill be rendered as:\n\n::: {#3a57cd65 .cell execution_count=1}\n```` { .cell-code}\n```{{python}}\n1 + 1\n```\n\n````\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n2\n```\n:::\n:::\n\n\nThis is especially useful when you want to demonstrate the use of cell options. For example, here we demonstrate the use of the `output` and `code-overflow` options:\n\n```{{python}}\n#| echo: fenced\n#| output: false\n#| code-overflow: wrap\n1 + 1\n```\n\nThis code block appears in the rendered document as:\n\n::: {#26d1e5fe .cell execution_count=2}\n```` { .cell-code .code-overflow-wrap}\n```{{python}}\n#| output: false\n#| code-overflow: wrap\n1 + 1\n```\n\n````\n:::\n\n\nNote that all YAML options will be included in the fenced code output *except for* `echo: fenced` (as that might be confusing to readers).\n\nThis behavior can also be specified at the document level if you want all of your executable code blocks to include the fenced delimiter and YAML options:\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: html\nexecute:\n echo: fenced\n---\n```\n\n#### Unexecuted Blocks\n\n\n\nOften you'll want to include a fenced code block purely as documentation (not executable). You can do this by using two curly braces around the language (e.g. `python`, `r`, etc.) rather than one. For example:\n\n```{{{python}}}\n1 + 1\n```\n\nWill be output into the document as:\n\n```{{python}}\n1 + 1\n```\n\nIf you want to show an example with multiple code blocks and other markdown, just enclose the entire example in 4 backticks (e.g. ````` ```` `````) and use the two curly brace syntax for code blocks within. For example:\n\n ````\n ---\n title: \"My document\"\n ---\n\n Some markdown content.\n\n ```{{{python}}}\n 1 + 1\n ```\n\n Some additional markdown content.\n\n ````\n\n\n## Engine Binding\n\nEarlier we said that the engine used for computations was determined automatically. You may want to customize this---for example you may want to use the Jupyter [R kernel](https://github.com/IRkernel/IRkernel) rather than Knitr, or you may want to use Knitr with Python code (via [reticulate](https://rstudio.github.io/reticulate/)).\n\nHere are the basic rules for automatic binding:\n\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| Extension | Engine Binding |\n+===========+========================================================================================================================================================================================================================================+\n| .qmd | Use Knitr engine if an `{r}` code block is discovered within the file |\n| | |\n| | Use Jupyter engine if *any other* executable code block (e.g. `{python}`, `{julia}`, `{bash}`, etc.) is discovered within the file. The kernel used is determined based on the language of the first executable code block discovered. |\n| | |\n| | Use no engine if no executable code blocks are discovered. |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| .ipynb | Jupyter engine |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| .Rmd | Knitr engine |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n| .md | No engine (note that if an `md` document does contain executable code blocks then an error will occur) |\n+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n\n::: callout-note\n\n## Using python and r together\n\nIf your quarto document includes both `{python}` and `{r}` code blocks, then quarto will automatically use Knitr engine and [reticulate](https://rstudio.github.io/reticulate/) R package to execute the python content.\n:::\n\nFor `.qmd` files in particular, you can override the engine used via the `engine` option. For example:\n\n``` markdown\nengine: jupyter\n```\n\n``` markdown\nengine: knitr\n```\n\nYou can also specify that no execution engine should be used via `engine: markdown`.\n\nThe presence of the `knitr` or `jupyter` option will also override the default engine:\n\n``` markdown\nknitr: true\n```\n\n``` markdown\njupyter: python3\n```\n\nVariations with additional engine-specific options also work to override the default engine:\n\n``` markdown\nknitr:\n opts_knit:\n verbose: true\n```\n\n``` markdown\njupyter:\n kernelspec:\n display_name: Python 3\n language: python\n name: python3\n```\n\n## Shell Commands\n\nUsing shell commands (from Bash, Zsh, etc.) within Quarto computational documents differs by engine. If you are using the Jupyter engine you can use [Jupyter shell magics](https://jakevdp.github.io/PythonDataScienceHandbook/01.05-ipython-and-shell-commands.html). For example:\n\n```` markdown\n---\ntitle: \"Using Bash\"\nengine: jupyter\n---\n\n```{{python}}\n!echo \"foo\"\n```\n````\n\nNote that `!` preceding `echo` is what enables a Python cell to be able to execute a shell command.\n\nIf you are using the Knitr engine you can use ```` ```{bash} ```` cells, for example:\n\n```` markdown\n---\ntitle: \"Using Bash\"\nengine: knitr\n---\n\n```{{bash}}\necho \"foo\" \n```\n````\n\nNote that the Knitr engine also supports ```` ```{python} ```` cells, enabling the combination of R, Python, and Bash in the same document\n\n## Conditional Execution\n\nIn some cases you want code execution itself — not just visibility of its output — to depend on the active output format. For example, when rendering to PDF you may want to skip a cell that loads an interactive HTML widget, rather than execute it and hide the result.\n\nQuarto exposes the current rendering context in the `QUARTO_EXECUTE_INFO` environment variable. Cells can read this variable to detect the active format and branch accordingly. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the full JSON schema and examples in R, Python, and Julia.\n\nThis complements format-based [conditional content](/docs/authoring/conditional.qmd), which controls visibility of *already-executed* output. `QUARTO_EXECUTE_INFO` lets you skip work, choose a different code path, or load a different library before any output is produced.\n\n", "supporting": [ "execution-options_files" ], diff --git a/docs/authoring/_visibility-vs-execution.md b/docs/authoring/_visibility-vs-execution.md new file mode 100644 index 0000000000..fdace97557 --- /dev/null +++ b/docs/authoring/_visibility-vs-execution.md @@ -0,0 +1 @@ +The `.content-visible` and `.content-hidden` classes control whether content is *shown* in the rendered output. They do **not** prevent the code in cells they wrap from executing. If you need to skip execution entirely based on the output format — for example, to avoid loading a package or calling a service that only makes sense for one format — have the cell itself read the `QUARTO_EXECUTE_INFO` environment variable. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the JSON schema and examples in R, Python, and Julia. diff --git a/docs/authoring/conditional.qmd b/docs/authoring/conditional.qmd index 33b11cafb4..3ba08f8305 100644 --- a/docs/authoring/conditional.qmd +++ b/docs/authoring/conditional.qmd @@ -112,4 +112,8 @@ path: ```` This feature is often useful alongside [project profiles](/docs/projects/profiles.qmd). -Different profiles can set different metadata values, and so can control the metadata used in conditional content. \ No newline at end of file +Different profiles can set different metadata values, and so can control the metadata used in conditional content. + +## Conditional Execution + +{{< include _visibility-vs-execution.md >}} diff --git a/docs/authoring/cross-references-divs.qmd b/docs/authoring/cross-references-divs.qmd index 59dc99ab15..2285c37957 100644 --- a/docs/authoring/cross-references-divs.qmd +++ b/docs/authoring/cross-references-divs.qmd @@ -438,3 +438,8 @@ Scatterplot @fig-scatterplot ```` + +{{< include _visibility-vs-execution.md >}} + +When you want visibility to depend on something beyond output format — for example, the same document rendered as a draft vs. a final version, or for an internal vs. an external audience — combine `.content-visible`/`.content-hidden` with the `when-meta` attribute. +You can then control visibility with values you set in your metadata, either in your document header, or via [project profiles](/docs/projects/profiles.qmd). diff --git a/docs/computations/execution-options.qmd b/docs/computations/execution-options.qmd index 72cff721b8..dc6bd0d2d0 100644 --- a/docs/computations/execution-options.qmd +++ b/docs/computations/execution-options.qmd @@ -498,3 +498,11 @@ echo "foo" ```` Note that the Knitr engine also supports ```` ```{python} ```` cells, enabling the combination of R, Python, and Bash in the same document + +## Conditional Execution + +In some cases you want code execution itself — not just visibility of its output — to depend on the active output format. For example, when rendering to PDF you may want to skip a cell that loads an interactive HTML widget, rather than execute it and hide the result. + +Quarto exposes the current rendering context in the `QUARTO_EXECUTE_INFO` environment variable. Cells can read this variable to detect the active format and branch accordingly. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the full JSON schema and examples in R, Python, and Julia. + +This complements format-based [conditional content](/docs/authoring/conditional.qmd), which controls visibility of *already-executed* output. `QUARTO_EXECUTE_INFO` lets you skip work, choose a different code path, or load a different library before any output is produced. diff --git a/docs/computations/julia.qmd b/docs/computations/julia.qmd index 0376d3afd9..580948d5f6 100644 --- a/docs/computations/julia.qmd +++ b/docs/computations/julia.qmd @@ -543,6 +543,26 @@ Please direct questions and requests regarding this functionality to the [QuartoNotebookRunner](https://github.com/PumasAI/QuartoNotebookRunner.jl) repository. +## Conditional Execution + +To execute a cell only for certain output formats, read the [`QUARTO_EXECUTE_INFO`](/docs/advanced/quarto-execute-info.qmd) environment variable inside the cell. +For example, you could execute code only if the target format is based on HTML (e.g. for `html`, `revealjs`, and `dashboard` formats): + +```` markdown +```{{julia}} +using JSON + +info = JSON.parsefile(ENV["QUARTO_EXECUTE_INFO"]) +is_html = info["format"]["identifier"]["base-format"] == "html" + +if is_html + # HTML-only code, e.g. an interactive widget +end +``` +```` + +This pairs well with [conditional content](/docs/authoring/conditional.qmd) when both visibility and execution should depend on format. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the full JSON schema. + # Using the `jupyter` engine ### Installation {#installation} @@ -662,3 +682,22 @@ To use Jupyter Cache you'll want to first install the `jupyter-cache` package: To enable the cache for a document, add the `cache` option. For example: +## Conditional Execution + +To execute a cell only for certain output formats, read the [`QUARTO_EXECUTE_INFO`](/docs/advanced/quarto-execute-info.qmd) environment variable inside the cell. +For example, you could execute code only if the target format is based on HTML (e.g. for `html`, `revealjs`, and `dashboard` formats): + +```` markdown +```{{julia}} +using JSON + +info = JSON.parsefile(ENV["QUARTO_EXECUTE_INFO"]) +is_html = info["format"]["identifier"]["base-format"] == "html" + +if is_html + # HTML-only code, e.g. an interactive widget +end +``` +```` + +This pairs well with [conditional content](/docs/authoring/conditional.qmd) when both visibility and execution should depend on format. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the full JSON schema. diff --git a/docs/computations/python.qmd b/docs/computations/python.qmd index 76b55aa6a2..78e62d59ad 100644 --- a/docs/computations/python.qmd +++ b/docs/computations/python.qmd @@ -112,3 +112,26 @@ Note that this step is not required if you are merely using conda with Quarto. I ::: {{< include _jupyter-daemon.md >}} + +## Conditional Execution + +To execute a cell only for certain output formats, read the [`QUARTO_EXECUTE_INFO`](/docs/advanced/quarto-execute-info.qmd) environment variable inside the cell. +For example, you could execute code only if the target format is based on HTML (e.g. for `html`, `revealjs`, and `dashboard` formats): + +```` markdown +```{{python}} +import json +import os + +with open(os.environ["QUARTO_EXECUTE_INFO"]) as f: + info = json.load(f) + +is_html = info["format"]["identifier"]["base-format"] == "html" + +if is_html: + # HTML-only code, e.g. an interactive widget + ... +``` +```` + +This pairs well with [conditional content](/docs/authoring/conditional.qmd) when both visibility and execution should depend on format. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the full JSON schema. diff --git a/docs/computations/r.qmd b/docs/computations/r.qmd index 4559b946e9..8319b1c9a6 100644 --- a/docs/computations/r.qmd +++ b/docs/computations/r.qmd @@ -156,6 +156,26 @@ airquality$TempC <- (5 / 9) * (airquality$Temp - 32) Unless you want to specify a cross-reference avoid using the [reserved cross-reference prefixes](/docs/authoring/cross-references.qmd#reserved-prefixes) for chunk labels. +## Conditional Execution + +To execute a cell only for certain output formats, read the [`QUARTO_EXECUTE_INFO`](/docs/advanced/quarto-execute-info.qmd) environment variable inside the cell. +For example, you could execute code only if the target format is based on HTML (e.g. for `html`, `revealjs`, and `dashboard` formats): + +```` markdown +```{{r}} +info <- jsonlite::fromJSON(Sys.getenv("QUARTO_EXECUTE_INFO")) +is_html <- info$format$identifier$`base-format` == "html" + +if (is_html) { + # HTML-only code, e.g. an interactive widget +} +``` +```` + +This pairs well with [conditional content](/docs/authoring/conditional.qmd) when both visibility and execution should depend on format. See [Execution Context Information](/docs/advanced/quarto-execute-info.qmd) for the full JSON schema. + +For R cells using the knitr engine, knitr's `knitr::is_html_output()`, `knitr::is_latex_output()`, and `knitr::pandoc_to()` predicates are also available for the common format-detection cases. See the [knitr manual](https://pkg.yihui.org/knitr/manual#sec:man-output_type). + ## Output Formats {#output-formats} Another difference between R Markdown and Quarto is related to output formats. Quarto includes many more built in output formats (and many more options for customizing each format). Quarto also has native features for special project types like [Websites](/docs/websites/), [Books](/docs/books/), and [Blogs](/docs/websites/website-blog.qmd) (rather than relying on external packages).