quarto-cli Documentation

Open-source scientific and technical publishing system built on Pandoc.

6,073 stars JavaScript JavaScript 1 file · ~28,935 tokens
RAW Doc

Technical Documentation: quarto-dev/quarto-cli

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (README.md)





Quarto

Quarto is an open-source scientific and technical publishing system built on Pandoc. Quarto documents are authored using Markdown, an easy to write plain text format.

In addition to the core capabilities of Pandoc, Quarto includes:

  1. Embedding code and output from Python, R, Julia, and JavaScript via integration with Jupyter, Knitr, and Observable.

  2. A variety of extensions to Pandoc Markdown useful for technical writing including cross-references, sub-figures, layout panels, hoverable citations and footnotes, callouts, and more.

  3. A project system for rendering groups of documents at once, sharing options across documents, and producing aggregate output like websites and books.

  4. Authoring using a wide variety of editors and notebooks including JupyterLab, RStudio, and VS Code.

  5. A visual Markdown editor that provides a productive writing interface for composing long-form documents.

Learn more about Quarto at https://quarto.org.

Development Version

To install the development version of the Quarto CLI, clone the quarto-cli repository then run the configure script for your platform (configure.sh for Linux/macOS or configure.cmd for Windows). For example:

bash
git clone https://github.com/quarto-dev/quarto-cli
cd quarto-cli
./configure.sh

The ./configure.sh script should add a symlink to quarto to your path. You can also run quarto by running package/dist/bin/quarto.

To update to the latest development version, run git pull from the local repo directory:

bash
cd quarto-cli
git pull

Running Tests

To run all unit tests, execute the script in the test directory.

bash
cd tests
./run-tests.sh

To run a specific unit test, specify the script name.

bash
cd tests
./run-tests.sh smoke/extensions/extension-render-doc.test.ts
./run-tests.sh smoke/extensions/

License

Quarto is open source software available under the MIT license (https://opensource.org/license/mit/).


Tests Docs Axe Scan README (`tests/docs/axe-scan/README.md`)

Fixtures for `quarto call axe`

Deliberately inaccessible sites. Every violation is planted on purpose, so the
scanner's grouping, matrix and baseline behaviour can be asserted against known
intent rather than against whatever a real site happens to contain.

Do not fix the accessibility problems in these directories. They are the
test data.

One site per concern

There were once one site and one smoke test. Every concern shared one page list,
so adding a page moved assertions in unrelated verifiers. That happened twice.
Each site below now carries one concern, and each has its own smoke test.

site concern smoke test
sites/findings/ grouping, systemic against localized, the impact spread, baseline reconciliation, the report, and a page Quarto did not render tests/smoke/axe/axe-findings.test.ts
sites/matrix/ the viewport and mode axes: conditional failures each reachable by exactly one route tests/smoke/axe/axe-matrix.test.ts
sites/brand-light-only/ a _brand.yml with light values only, which must not read as a dark mode tests/smoke/axe/axe-brand.test.ts
sites/darkly/ a single dark-coloured theme: one default cell, annotated dark-coloured tests/smoke/axe/axe-darkly.test.ts

cells/ holds raw per-cell payloads captured from two of these sites. The unit
tests read them, so the aggregate stage can be exercised without a browser.

Ground rules for adding a fixture

Add the page to the site whose concern it belongs to. If it belongs to no site,
add a site. A page in the wrong site is how the coupling came back last time.

Keep each planted violation reachable by one route only. A finding that appears
in every cell proves nothing about the matrix.

The sites are source only. Each smoke test renders its site, scans it, then
removes the render and the scan artifacts. A committed render would carry
site_libs/ and go stale on every Quarto change.

Regenerating a site's observed table

Each site's README records what that site actually produces. axe chooses a
minimal unique selector from the DOM as it finds it, so a signature is
discovered, not decreed.

bash
cd tests/docs/axe-scan/sites/<site>
quarto render
quarto call axe _site          # writes _axe-checks/ next to _quarto.yml

Then update the table from _axe-checks/findings.json, and read the diff. A
change there is either a fixture change or a signature-scheme change, and the
two need different responses.


Tests Docs Manual README (`tests/docs/manual/README.md`)

Manual Tests

Tests that require interactive sessions, external services, or browser access that cannot run in automated CI.

Test Suites

Directory / File Area Skill Description
preview/ quarto preview /quarto-preview-test Live preview server behavior: URL routing, file watching, live reload, transient file cleanup
publish-connect-cloud/ quarto publish — Posit Connect Cloud publishing with OAuth flow
mermaid-svg-pdf-tooling.qmd quarto render — Mermaid SVG rendering to PDF with external tooling (rsvg-convert)

Running Tests

Each suite has its own README with test matrix and execution instructions. Test fixtures live alongside the README in each directory.

For preview tests, use the /quarto-preview-test skill which automates the start-verify-cleanup cycle.


Tests Docs Axe Scan Cells README (`tests/docs/axe-scan/cells/README.md`)

Captured per-cell axe payloads

Cells from scans of the fixture sites, saved verbatim as tests/unit/ fixtures.
They let the aggregate stage run against genuine axe-core output without
launching a browser.

Verbatim is the point. These are not trimmed to the fields the aggregate
stage happens to read. Keeping the whole payload means an axe upgrade that
changes its shape — how color-contrast reports its colour pair, how
failureSummary is worded — surfaces in a fast unit test rather than only in
the browser-driven smoke tests.

One directory per site, and the unit tests aggregate each set separately,
exactly as a real scan of either site would. Do not merge them. A union of two
sites is a scan that never happened, and its page list and cell counts would
mean nothing.

`findings/` — from `../sites/findings`

cell why it is here
index__1440x900__light the desktop and light baseline
index__390x844__light a second cell of the same page, for the matrix union
index__1440x900__dark with the two above and below, one page in all four cells
index__390x844__dark so a finding's per-page cell list can be asserted in full
about__1440x900__light a second page carrying the systemic image-alt
static_legacy__1440x900__default hand-written non-Quarto DOM: one-mode (default) cell, and the digit-run and volatile-attribute cases

`matrix/` — from `../sites/matrix`

cell why it is here
media__1440x900__light the baseline the other three are compared against
media__1440x900__dark the dark-only color-contrast failure
media__390x844__light the mobile-only color-contrast failure
media__390x844__dark both conditional failures in one cell

theme.qmd's failure — reachable only by seeding Quarto's colour-scheme
localStorage key — has no capture. Nothing about it is visible in an
aggregated payload, because mode selection is a property of the scan and not
of the result. tests/smoke/axe/axe-matrix.test.ts covers it.

Regenerating

Re-scan the site, then copy the matching files out of its _axe-checks/cells/:

bash
cd tests/docs/axe-scan/sites/findings
quarto render
quarto call axe _site
cp _axe-checks/cells/index__1440x900__light.json ../../cells/findings/

If the set changes, update this file and the site's observed table. The two
describe the same scan.


Tests Docs Books Visualization Curriculum Index (`tests/docs/books/visualization-curriculum/index.md`)

Introduction {.unnumbered}

A data visualization curriculum of interactive notebooks, using Vega-Lite and Altair. This book contains a series of Python-based Jupyter notebooks, a corresponding set of JavaScript notebooks are available online on Observable.

::: {.callout-note appearance="simple"}
This book was originally created using Jupyter Book and published at https://uwdata.github.io/visualization-curriculum/. This site is a port of the original book source to the Quarto publishing system in order to provide an example of it's use.
:::

Getting Started

The visualization curriculum can be used either online or on your local computer. You can view and interact with the plots directly in this Jupyter Book. If you want to modify the code, you have a few different options:

  • To read JavaScript notebooks online using Observable, navigate to the "Observable" page above and click the corresponding notebook.
  • To read Python notebooks online using Colab, click the corresponding section in this book, hover over the little rocket ship at the top of the page, and select "Colab" from the menu.
  • To read Python notebooks locally, follow the instructions below.

Local Installation

  1. Install Altair and a notebook environment. The most recent versions of these notebooks use Altair version 4.
  2. Download the notebooks from the releases page. Typically you will want to use the most recent release. (If you wish to use notebooks for Altair version 3, download the Altair v3.2 release.)
  3. Open the notebooks in your local notebook environment. For example, if you have JupyterLab installed (v1.0 or higher is required), run jupyter lab within the directory containing the notebooks.

Depending on your programming environment (and whether or not you have a live internet connection), you may want to specify a particular renderer for Altair.

Credits

Developed at the University of Washington by Jeffrey Heer, Dominik Moritz, Jake VanderPlas, and Brock Craft. Thanks to the UW Interactive Data Lab and Arvind Satyanarayan for their valuable input and feedback! Thanks also to the students of UW CSE512 Spring 2019, the first group to use these notebooks within an integrated course curriculum.


Tests Docs Manual Preview README (`tests/docs/manual/preview/README.md`)

Manual Preview Tests

Tests for quarto preview behavior that require an interactive session with file-save events. These cannot run in automated smoke tests.

Automation

Use the /quarto-preview-test command for the general workflow of starting preview, verifying with browser automation, and checking logs/filesystem. It documents the tools and patterns.

For browser interaction, /agent-browser is preferred over Chrome DevTools MCP (more token-efficient). See the command for details.

Test Matrix: quarto_ipynb Accumulation (#14281)

After every test involving Jupyter execution (Python/Julia cells), verify:

  1. ls *.quarto_ipynb* — at most one {name}.quarto_ipynb (no _1, _2 variants)
  2. After Ctrl+C exit — no .quarto_ipynb files remain (unless keep-ipynb: true)

For tests without Jupyter execution (T9, T10, T11), verify no .quarto_ipynb files are created at all.

P1: Critical

T1: Single .qmd with Python — re-render accumulation

  • Setup: test.qmd with Python code cell
  • Steps: quarto preview test.qmd, save 5 times, check files, Ctrl+C
  • Expected: At most one .quarto_ipynb at any time. Zero after exit.
  • Catches: invalidateForFile() not deleting transient file before cache eviction

T2: Single .qmd with Python — startup duplicate

  • Setup: Same test.qmd
  • Steps: quarto preview test.qmd, check files immediately after first render (before any saves), Ctrl+C
  • Expected: Exactly one .quarto_ipynb during render. Zero after exit.
  • Catches: cmd.ts not passing ProjectContext to preview()

T3: .qmd in project — project-level preview

  • Setup: Website project (_quarto.yml with type: website), index.qmd with Python cell
  • Steps: quarto preview (project dir), save index.qmd 3 times, check files, Ctrl+C
  • Expected: At most one index.quarto_ipynb. Zero after exit.
  • Catches: Fix works when projectContext() finds a real project

T4: .qmd in project — single file preview

  • Setup: Same project as T3
  • Steps: quarto preview index.qmd, save 3 times, check files, Ctrl+C
  • Expected: Same as T3. May redirect to project preview (expected behavior).
  • Catches: Context passing works for files inside serveable projects

P2: Important

T5: .qmd with Julia code cells

  • Setup: julia-test.qmd with Julia cell
  • Steps: Same as T1
  • Expected: Same as T1. Julia uses the same Jupyter engine path.

T6: Rapid successive saves

  • Setup: Same test.qmd as T1
  • Steps: Save 5 times within 2-3 seconds (faster than render completes)
  • Expected: At most one .quarto_ipynb. Debounce/queue coalesces saves.
  • Catches: Race condition in invalidation during in-progress render

T7: `keep-ipynb: true`

  • Setup: test.qmd with keep-ipynb: true in YAML
  • Steps: Preview, save 3 times, Ctrl+C, check files
  • Expected: test.quarto_ipynb persists after exit (not cleaned up). No _1 variants during preview.
  • Catches: invalidateForFile() respects the transient = false flag set by cleanupNotebook()

T8: `--to pdf` format

  • Setup: Same test.qmd (requires TinyTeX)
  • Steps: quarto preview test.qmd --to pdf, save 3 times
  • Expected: Same as T1. Transient notebook logic is format-independent.

T9: Plain .qmd — no code cells (regression)

  • Setup: plain.qmd with only markdown content
  • Steps: Preview, save 3 times, check for .quarto_ipynb files
  • Expected: No .quarto_ipynb files ever created.
  • Catches: Fix is a no-op when no Jupyter engine is involved

T10: .qmd with R/knitr engine (regression)

  • Setup: r-test.qmd with R code cell and engine: knitr
  • Steps: Preview, save 3 times, check for .quarto_ipynb files
  • Expected: No .quarto_ipynb files. Knitr doesn't use Jupyter intermediate.

T10b: File excluded from project inputs (regression)

  • Setup: Website project with _quarto.yml. Create _excluded.qmd with a Python cell (files starting with _ are excluded from project inputs by default)
  • Steps: quarto preview _excluded.qmd, save 3 times, check files, Ctrl+C
  • Expected: Falls back to single-file preview (not project preview). At most one .quarto_ipynb.
  • Catches: Context reuse from cmd.ts incorrectly applying project semantics to excluded files

P3: Nice-to-Have

T11: Native .ipynb file

  • Setup: notebook.ipynb (native Jupyter notebook)
  • Steps: Preview, save 3 times
  • Expected: No transient .quarto_ipynb — the .ipynb is the source, not transient.

T12: File with spaces in name

  • Setup: my document.qmd with Python cell
  • Steps: quarto preview "my document.qmd", save 3 times
  • Expected: At most one my document.quarto_ipynb. Path normalization handles spaces.

T13: File in subdirectory

  • Setup: subdir/deep/test.qmd with Python cell
  • Steps: Preview from parent dir, save 3 times
  • Expected: At most one transient notebook in subdir/deep/.

T14: Change code cell content

  • Setup: test.qmd with x = 1; print(x)
  • Steps: Change to x = 2, save; change to x = 3, save
  • Expected: At most one .quarto_ipynb. Code changes trigger re-execution but file is cleaned.

T15: Change YAML metadata

  • Setup: test.qmd with title: "Test"
  • Steps: Change title, save; add theme: cosmo, save
  • Expected: Same as T1. Metadata changes go through the same render/invalidation path.

T16: Multiple .qmd files in project

  • Setup: Website with index.qmd (Python), about.qmd (Python), plain.qmd (no code)
  • Steps: Preview project, edit index, navigate to about, edit about
  • Expected: At most one .quarto_ipynb per Jupyter-using file. No accumulation.

Test Matrix: Single-file Preview Root URL (#14298)

After every change to preview URL or handler logic, verify that single-file previews serve content at the root URL and print the correct Browse URL.

P1: Critical

T17: Single-file preview — root URL accessible

  • Setup: plain.qmd with only markdown content (no code cells)
  • Steps: quarto preview plain.qmd --port XXXX --no-browser, then curl -s -o /dev/null -w "%{http_code}" http://localhost:XXXX/
  • Expected: HTTP 200. Browse URL prints http://localhost:XXXX/ (no filename appended).
  • Catches: projectHtmlFileRequestHandler used for single files (defaultFile=index.html instead of output filename), or previewInitialPath returning filename instead of ""

T18: Single-file preview — named output URL also accessible

  • Setup: Same plain.qmd
  • Steps: quarto preview plain.qmd --port XXXX --no-browser, then curl -s -o /dev/null -w "%{http_code}" http://localhost:XXXX/plain.html
  • Expected: HTTP 200. The output filename path also serves the rendered content.
  • Catches: Handler regression where only root or only named path works

P2: Important

T19: Project preview — non-index file URL correct

  • Setup: Website project with _quarto.yml, index.qmd, and about.qmd
  • Steps: quarto preview --port XXXX --no-browser, navigate to http://localhost:XXXX/about.html
  • Expected: HTTP 200. Browse URL may include path for non-index files in project context.
  • Catches: isSingleFile guard accidentally excluding real project files from path computation

T33: knitr doc in a subdirectory — preview from that subdirectory (#14683)

  • Setup: Fixture knitr-subdir-14683/ — a website project with a knitr doc at labs/doc.qmd (an {r} chunk plus a QUARTO_DOCUMENT_PATH echo). Requires R + rmarkdown/knitr.
  • Steps: From knitr-subdir-14683/labs/ (the doc's own directory), run quarto preview doc.qmd --to html --no-watch-inputs --no-browser --port XXXX — the shape RStudio's Render button uses (bare filename, cwd = the doc's subdirectory).
  • Expected: Renders without Error in rmarkdown:::abs_path(input); _site/labs/doc.html is produced showing [1] 2 (the R chunk executed). The echoed QUARTO_DOCUMENT_PATH is the doc's absolute subdirectory (ends in labs), not . / the project root (#12401).
  • Catches: fileExecutionEngineAndTarget not normalizing the input to absolute — a cwd-relative target.input/source in the shared preview cache makes the knitr R subprocess (cwd = project dir) fail abs_path on the subdirectory-relative filename.
  • Automated coverage: tests/unit/preview-subdir-knitr-cwd.test.ts exercises this same scenario end-to-end (real R/knitr subprocess) plus a deterministic cache-key guard. Manual rerun of this test is optional — only needed to hand-verify against a real quarto preview CLI/browser session (e.g. after changing the preview HTTP/format-resolution layer), since the automated test calls the internal render functions directly rather than spinning up the actual preview server.

Test Matrix: Format Change Detection (#14533)

After every change to previewRenderRequestIsCompatible or the
fileInformationCache invalidation path, verify that a frontmatter
format edit is detected on the first render request.

P1: Critical

T20: Single .qmd — `format: html` → `format: typst`

  • Setup: 14533-format-change-detection.qmd with format: html
  • Steps: quarto preview tests/docs/manual/preview/14533-format-change-detection.qmd, edit frontmatter to format: typst, save, trigger one Preview render
  • Expected: Output switches to typst on the first request. Preview process restarts.
  • Catches: Stale fileInformationCache entry leaking previous format into previewRenderRequestIsCompatible

T21: Single .qmd — `format: typst` → `format: html`

  • Setup: Same doc but starting at format: typst
  • Steps: Same as T20 but reverse direction
  • Expected: Same as T20 — direction-independent
  • Catches: Asymmetric format-resolution path that only fires for html start state

P2: Important

T22: Multi-format frontmatter — first-format change detected

  • Setup: format: [html, pdf] initially
  • Steps: Edit to format: [typst, pdf], save, trigger one Preview render
  • Expected: First format (typst) drives the compatibility check, preview restarts
  • Catches: previewFormat picking up the wrong array element after invalidation

T23: Format change while preview is mid-render

  • Setup: Doc with code cell long enough to render for several seconds
  • Steps: Trigger preview, immediately edit frontmatter format mid-render, save
  • Expected: No deadlock. Next render request after the in-flight one finishes resolves the new format.
  • Catches: Cache-invalidation racing with cache-population in renderForPreview

P3: Nice-to-Have

T24: File with spaces in name

  • Setup: my doc.qmd with format: html
  • Steps: Same as T20
  • Expected: Same as T20. Path normalization handles the cache key correctly.

Regression Guard

T25: Unchanged frontmatter — no spurious restart

  • Setup: Any preview-able .qmd
  • Steps: Save the file without editing the frontmatter format, trigger a Preview render
  • Expected: No preview process restart. Render runs in the same process.
  • Catches: Over-eager invalidation triggering 404 when the format is in fact unchanged

Test Matrix: Brand Detection (#14593)

After every change to projectResolveBrand or the project.brandCache guard,
verify that a sibling _brand.yml added or removed while a preview is running
takes effect on the next render — without restarting the preview process. Fixture:
brand-detection/ (report.qmd, brand-imperial.yml); drive it with the
/quarto-preview-test workflow. The
brand signal in the kept report.typ is the line
#show link: set text(fill: rgb("#bc1e22") (present ⇒ brand applied). See
brand-detection/README.md for the on/off check.

P1: Critical

T28: Single .qmd — `_brand.yml` added mid-preview

  • Setup: brand-detection/report.qmd (format: typst, keep-typ: true), no _brand.yml present
  • Steps: quarto preview report.qmd --to typst --no-browser, copy brand-imperial.yml to _brand.yml, force one re-render (e.g. touch report.qmd), grep report.typ
  • Expected: report.typ gains the brand link-color line. Brand applies without restarting preview.
  • Catches: Stale project.brandCache serving "no brand" after a _brand.yml appeared

T29: Single .qmd — `_brand.yml` removed mid-preview

  • Setup: Same fixture with _brand.yml present and the link colored
  • Steps: Remove _brand.yml, force one re-render, grep report.typ
  • Expected: The brand link-color line disappears — output reverts to no-brand
  • Catches: Stale project.brandCache holding the previous brand after the file was removed

P2: Important

T30: HTML format — `_brand.yml` added mid-preview

  • Setup: report.qmd with format: html, no _brand.yml
  • Steps: As T28, inspect the rendered HTML/CSS for the brand primary color
  • Expected: Brand applies. projectResolveBrand is format-independent, so the same guard covers HTML.
  • Catches: A fix that only worked for the typst code path

T31: Project (`_quarto.yml`) — `_brand.yml` added/removed mid-preview

  • Setup: Website/book project with _quarto.yml, no project-level _brand.yml
  • Steps: quarto preview the project, add then remove a _brand.yml, force re-renders between
  • Expected: Brand applies on add and reverts on remove, both without restart
  • Catches: The project (multi-file) ProjectContext sharing the same stale brandCache

Regression Guard

T32: Unchanged `_brand.yml` — no spurious re-resolve cost

  • Setup: A preview with a stable _brand.yml
  • Steps: Save the source repeatedly without touching _brand.yml
  • Expected: Brand stays applied; the source-state token matches so the cache is reused (only cheap stat calls per resolve)
  • Catches: A guard that re-loads the brand on every render even when nothing changed

Test Matrix: Sass Cache Reuse (#14594)

After every change to SassCache.cleanup() or the _sassCache registry in
src/core/sass/cache.ts, verify that a book/website preview survives repeated
re-renders instead of crashing with BadResource: Bad resource ID. On each
re-render the serve/watch reload path runs refreshProjectConfig
(src/project/serve/watch.ts, ~line 277 for HTML; also on config changes,
~line 305), which calls project.cleanup() and closes the session Sass KV
handle; the next render must open a fresh handle rather than reuse the closed
one. Fixture: sass-cache-crash-14594/ (a flat multi-chapter book with
theme: cosmo + css:, which routes the theme through the session Sass cache);
drive it with the /quarto-preview-test workflow. Deterministic unit coverage
lives in tests/unit/sass-cache.test.ts — this matrix is the interactive
regression guide that path can't cover.

P1: Critical

T34: Book project preview — `_quarto.yml` edit does not crash on Sass recompile

  • Setup: sass-cache-crash-14594/ book (theme: cosmo, css: styles.css), no prior .quarto/ or _book/
  • Steps: From the fixture dir, quarto preview --no-browser --port XXXX; after the first render, edit _quarto.yml (tweak the title or append a comment line) and save 3-5 times, watching the preview log
  • Expected: Every re-render completes and reloads. No BadResource: Bad resource ID in the log. The cosmo theme + custom CSS keep recompiling/serving.
  • Catches: SassCache.cleanup() closing the KV handle but leaving the stale instance in _sassCache, so the next resolve reuses a closed handle (#14594, #13955)

P2: Important

T35: Book project preview — chapter content edit (content re-render path)

  • Setup: Same fixture
  • Steps: quarto preview --no-browser --port XXXX; after the first render, edit a chapter body (index.qmd / chapter1.qmd) and save 3-5 times
  • Expected: Same as T34 — no crash, pages keep reloading
  • Catches: The HTML reload path (refreshProjectConfig at watch.ts ~277) closes the session KV on a plain content re-render too, so a content save must not reuse a closed handle either

Regression Guard

T36: Single-file preview — unaffected by the registry cleanup

  • Setup: plain.qmd (markdown-only, no project)
  • Steps: quarto preview plain.qmd --no-browser --port XXXX, save 3-5 times
  • Expected: No crash and no behavior change — the fix is a no-op for the common single-file preview path
  • Catches: The registry-entry deletion in cleanup accidentally breaking or churning the non-project preview path

Extension Format PDF Preview (#14582)

P1: Core functionality

T26: Book preview with extension PDF format

  • Setup: extension-pdf-book/ fixture
  • Steps: quarto preview . --to dummy-extension-pdf --no-browser --port 4444
  • Expected: Browse URL contains web/viewer.html. PDF.js viewer loads in browser with live-reload.
  • Catches: isFormatTo startsWith check failing for extension format strings.

T27: Book preview with extension HTML format (no regression)

  • Setup: Same fixture
  • Steps: quarto preview . --to dummy-extension-html --no-browser --port 4444
  • Expected: Normal HTML preview with live-reload. No PDF.js viewer.
  • Catches: Fix doesn't accidentally enable PDF mode for non-PDF extension formats.

Test Matrix: Book `.llms.md` Cross-References (#14975)

Book chapters resolve cross-references in project post-render, and their
.llms.md files are converted after that resolution. Verify that a
preview re-render keeps this: the edited chapter's .llms.md is
regenerated with resolved numbers and cross-chapter links, and the served
HTML still has no llms-txt-only content. Fixture:
book-llms-crossrefs-14975/ (three-chapter book, llms-txt: true).
Rendered-output coverage lives in
tests/smoke/project/project-book-llms-crossrefs.test.ts.

P1: Critical

T37: Book preview — chapter edit regenerates resolved `.llms.md`

  • Setup: book-llms-crossrefs-14975/ book, no prior .quarto/ or _book/
  • Steps: From the fixture dir, quarto preview --no-browser; after the first render, check _book/second.llms.md. Append the line PREVIEWEDIT see @tbl-three. to second.qmd, save, and wait for the reload. Check _book/second.llms.md again.
  • Expected: Before and after the edit, second.llms.md has [Equation 1.1](#eq-one) and [Table 2.1](third.llms.md#tbl-three) (with a no-break space after the prefix). After the edit, it has the PREVIEWEDIT line, with its reference resolved to Table 2.1.
  • Catches: The preview re-render path skipping the book post-render step that converts held .llms.md pages, or not holding them, so .llms.md goes stale or unresolved.

Regression Guard

T38: Book preview — served HTML has no `llms-txt`-only content after a re-render

  • Setup: Same fixture, preview from T37 still running
  • Steps: Edit third.qmd (append a sentence), save, wait for reload, then fetch the served page: curl -s http://localhost:/third.html.
  • Expected: The response contains HTMLONLYCHAPTERTEXT. It contains neither LLMSONLYCHAPTERTEXT nor the classes llms-conditional-content / llms-hidden-content. _book/third.llms.md contains LLMSONLYCHAPTERTEXT.
  • Catches: Conditional-content cleanup of the HTML being skipped or delayed for books.

Test File Templates

Minimal Python .qmd:

yaml
---
title: "Preview Test"
---
text
```{python}
print("Hello from Python")
```
text
Edit this line to trigger re-renders.

Minimal website project (_quarto.yml):

yaml
project:
  type: website

keep-ipynb variant:

yaml
---
title: "Keep ipynb Test"
execute:
  keep-ipynb: true
---

Tests Docs Manual Publish Connect Cloud README (`tests/docs/manual/publish-connect-cloud/README.md`)

Manual Testing: quarto publish posit-connect-cloud

Testing protocol for the Posit Connect Cloud publish provider.

Prerequisites

  • Dev quarto built (./configure.cmd completed)
  • Browser available for OAuth flow

Setup

To test against staging instead of production, set the environment:

bash
export POSIT_CONNECT_CLOUD_ENVIRONMENT=staging

Dev quarto path (from repo root):

bash
# Windows
./package/dist/bin/quarto.cmd

# Linux/macOS
./package/dist/bin/quarto

Token storage location:

  • Windows: %LOCALAPPDATA%\quarto\publish\accounts\posit-connect-cloud\accounts.json
  • macOS/Linux: ~/.local/share/quarto/publish/accounts/posit-connect-cloud/accounts.json

Test 1: First-Time Authorization

Verify the OAuth device code flow works end-to-end.

Pre-condition: No existing posit-connect-cloud accounts. Check with:

bash
./package/dist/bin/quarto.cmd publish accounts

Run:

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd

Expected behavior:

  1. Prompt: "Authorize" confirmation
  2. Authorization code displayed (green, bold)
  3. Browser opens to login page (the code is pre-filled in URL)
  4. After approving in browser, terminal resumes automatically
  5. If no publishable accounts: browser opens account creation, spinner shows "Waiting for account setup"
  6. If one account: auto-selected with debug message
  7. If multiple accounts: interactive selection prompt
  8. Confirmation: "Authorized to publish as account-name"
  9. Rendering happens
  10. Spinner: "Uploading files"
  11. Spinner: "Publishing document"
  12. Final message: Published: https://...connect.posit.cloud/<account>/content/
  13. Browser opens to published content

Check:

  • Auth code shown in terminal
  • Browser opens automatically
  • No manual code entry required (pre-filled URL)
  • Account selected/created
  • Document published and accessible at URL
  • Content renders correctly in browser (title, formatting, link)
  • Account shows server URL in prompt (e.g. cderv (https://connect.posit.cloud))

Record: Account name: ___ | Content ID: ___ | URL: ___


Test 2: Token Persistence

Verify re-publish works without re-authorization.

Pre-condition: Test 1 completed. Close the terminal entirely.

Run (in fresh terminal):

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd

Check:

  • No authorization flow triggered
  • Existing target detected from _publish.yml
  • Publish succeeds
  • URL unchanged from Test 1

Test 3: Publish RevealJS Slides

Verify single-document revealjs publishing works (reveal.js assets bundled correctly).

Run:

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/revealjs-slides/slides.qmd

Check in browser:

  • Slides load with reveal.js navigation (arrow keys, progress bar)
  • Slide 3 has aquamarine background color
  • Slide 4 has syntax-highlighted Python code block
  • No broken assets (check browser console for 404s)
  • All reveal.js transitions and controls functional

Record: Content ID: ___ | URL: ___


Test 4: Publish a Website

Verify multi-page site publishing.

Run:

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/simple-website

Check in browser:

  • Home page loads with correct title
  • Navbar present with "Home" and "About" links
  • Click "About" -> about page loads
  • Click "Home" -> home page loads
  • Both pages render correctly
  • Published as new content (different URL from Test 1)

Record: Content ID: ___ | URL: ___


Test 5: Update Existing Content

Verify re-publishing updates content in-place.

Setup: Edit simple-website/index.qmd — add a line:

markdown
This content was updated for Test 5.

Run:

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/simple-website

Check:

  • URL is same as Test 4
  • Hard-refresh (Ctrl+F5) shows updated text
  • About page still works
  • No duplicate content created on dashboard

Cleanup: Revert the edit:

bash
git checkout tests/docs/manual/publish-connect-cloud/simple-website/index.qmd

Test 6: Account Management

Verify accounts listing and removal.

Run:

bash
./package/dist/bin/quarto.cmd publish accounts

Check:

  • Posit Connect Cloud account(s) listed
  • Account name from Test 1 shown
  • Server URL displayed next to account name

Remove the account (select it from the interactive menu, confirm removal).

Verify removed, then re-authorize (needed for remaining tests):

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd

Test 7: CI/CD Mode (Environment Token)

Verify non-interactive publishing with environment variables.

Setup: Extract the stored token:

bash
cat "$LOCALAPPDATA/quarto/publish/accounts/posit-connect-cloud/accounts.json"

Note the accessToken and accountId values.

Set env vars and remove stored account:

bash
export POSIT_CONNECT_CLOUD_ACCESS_TOKEN="<accessToken>"
export POSIT_CONNECT_CLOUD_ACCOUNT_ID="<accountId>"

Remove stored accounts via quarto publish accounts so only env var token is used.

Run:

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd --no-prompt

Check:

  • No browser opens
  • No interactive prompts
  • Token from environment variable used
  • Account resolved from ACCOUNT_ID
  • Publish succeeds
  • No ghost token persisted (run quarto publish accounts after — should show no posit-connect-cloud accounts)

7b: Multiple Accounts Without ACCOUNT_ID (--no-prompt)

If the access token has access to multiple publishable accounts:

bash
export POSIT_CONNECT_CLOUD_ACCESS_TOKEN="<accessToken>"
# Intentionally do NOT set POSIT_CONNECT_CLOUD_ACCOUNT_ID
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd --no-prompt
  • Publish fails with error: "Multiple publishable accounts found. Set POSIT_CONNECT_CLOUD_ACCOUNT_ID to select a specific account."
  • No content published

This matches other providers' behavior: ambiguous account selection fails in non-interactive mode.

Cleanup:

bash
unset POSIT_CONNECT_CLOUD_ACCESS_TOKEN
unset POSIT_CONNECT_CLOUD_ACCOUNT_ID

Re-authorize interactively for remaining tests.


Test 8: Provider Selection (Interactive)

Verify posit-connect-cloud appears in the interactive provider menu.

Run:

bash
./package/dist/bin/quarto.cmd publish tests/docs/manual/publish-connect-cloud/single-doc/document.qmd

(No provider argument — triggers interactive selection.)

Check:

  • "Provider:" prompt shown
  • "Posit Connect Cloud" listed as an option
  • Selecting it proceeds to publish flow
  • Ctrl+C to cancel (or complete the publish)

Test 9: posit-cloud Deprecation Warning

Verify the old provider name shows a helpful warning.

Run:

bash
./package/dist/bin/quarto.cmd publish posit-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd

Check:

  • Warning message displayed
  • Message mentions "no longer supported"
  • Message suggests posit-connect-cloud
  • Message includes link to docs.posit.co
  • Command fails (provider not found after warning)

Test 10: Error Cases

10a: Invalid Token

bash
export POSIT_CONNECT_CLOUD_ACCESS_TOKEN="invalid_garbage_token"
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd
  • Clear authentication error
  • No crash/stacktrace
bash
unset POSIT_CONNECT_CLOUD_ACCESS_TOKEN

10b: Deleted Content

  1. Publish the single doc (or use existing from Test 1)
  2. Delete the content from the Connect Cloud dashboard
  3. Re-publish:
bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd
  • Silently detects content is gone via resolveTarget (debug log: "not found" or "deleted")
  • No "Publish update to:" prompt for the deleted target
  • Falls through to new publish flow ("Publish with account:" prompt)
  • Publishes successfully with new content ID
  • Old stale entry remains in _publish.yml (not cleaned up — known limitation)

10c: --no-render Flag

bash
./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd --no-render
  • Skips rendering
  • Still uploads and publishes (uses last rendered output)

Known issue: --no-render may produce incomplete bundles for single documents (missing supporting resources). This affects all bundle-based providers, not just Connect Cloud.


Test 11: Token Refresh

Access tokens expire after some time. To test proactive refresh:

Pre-condition: The stored token file must contain a valid refreshToken (present by default after interactive auth in Test 1).

  1. Open the stored token file (see token storage path in Setup)
  2. Change expiresAt to a past timestamp (e.g., 1000)
  3. Publish:
    bash
    ./package/dist/bin/quarto.cmd publish posit-connect-cloud tests/docs/manual/publish-connect-cloud/single-doc/document.qmd
  • Publish succeeds (token refreshed automatically)
  • Check stored token file: expiresAt updated to future value
  • No re-authorization prompt

Results Template

# Test Result Notes
1 First-time authorization
2 Token persistence
3 Publish revealjs slides
4 Publish website
5 Update existing content
6 Account management
7 CI/CD mode
7b Multiple accounts without ACCOUNT_ID
8 Provider selection
9 posit-cloud deprecation
10a Invalid token error
10b Deleted content
10c --no-render flag
11 Token refresh

Post-Testing Cleanup

  1. Delete test content from the Connect Cloud dashboard
  2. Remove stored tokens:
    bash
    ./package/dist/bin/quarto.cmd publish accounts
  3. Unset env vars:
    bash
    unset POSIT_CONNECT_CLOUD_ENVIRONMENT
    unset POSIT_CONNECT_CLOUD_ACCESS_TOKEN
    unset POSIT_CONNECT_CLOUD_ACCOUNT_ID
  4. Revert any test fixture edits:
    bash
    git checkout tests/docs/manual/publish-connect-cloud/
  5. Test artifacts (_publish.yml, _site/, rendered HTML) are covered by .gitignore in each fixture directory.

Tests Docs Manuscript Ipynb Full README (`tests/docs/manuscript/ipynb-full/README.md`)

Notebooks Now! Submission Template

This submission template is for a markdown-based publication with additional supporting notebook and markdown files, as well as supporting data, bibliography, and MyST build configuration.

Source files

The primary source file for this template is a MyST markdown article. This file may reference notebook cells from other sub-articles to use the output of these cells as figures. It may also reference content from other markdown sub-articles. All of these supplementary source notebooks/articles should be saved in the notebooks/ folder. It also contains MyST blocks tagged in their metadata as "part": "abstract", or "part": "availability" - these cells will be extracted from the document and included as the specified part in the built output.

Supporting material

Supplementary data

By convention, all data should be saved in data/ directory. There is nothing magic about this directory; references to your data from your notebook must still specify the correct relative path.

Supplementary images

Similar to the data/ directory, images for figures should be specified in images/ directory.

Bibliography

Bibliography entries may be specified two ways, both described in the MyST docs. They may be listed explicitly in BibTeX format, by convention in the file references.bib, and referenced by key using a cite MyST role. They may also be specified as inline DOI links. These do not require full bibliographic information; the data is fetched implicitly on build from the DOI.

MyST configuration

A myst.yml file must be provided to configure notebook metadata and exports. This includes authors, affiliations, licenses, keywords, and much more.

Building output artifacts

To build PDF/JATS output from your source data, you must have the MyST CLI installed

bash
npm install myst-cli

Then build all exports defined in the myst.yml file:

bash
myst build --all

Tests Docs Manuscript Ipynb Single README (`tests/docs/manuscript/ipynb-single/README.md`)

Notebooks Now! Submission Template

This submission template is for a simple notebook-based publication with one source file, supporting data, bibliography, and Quarto build configuration.

Source file

The source file for this template is a Jupyter notebook. There is not necessarily anything special about this notebook. It may contain markdown cells, code cells, and outputs from common Python packages, including pandas, matplotlib, plotly, seaborn, and altair.

The notebook has an additional markdown cell at the top of the document which configures Quarto to render the notebook.

Supporting material

Supplementary data

By convention, all data should be saved in data/ directory. There is nothing magic about this directory; references to your data from your notebook must still specify the correct relative path.

Supplementary images

Similar to the data/ directory, images for figures should be specified in images/ directory.

Bibliography

Bibliography entries may be specific in the document as described in the Quarto documentation.

Quarto configuration

Configuration for the example is provided by a YAML block that appears as the first cell of the Notebook.

Building output artfiacts

To build PDF/JATS output from your source data, you must have the Quarto CLI installed - you can download or learn about installation at https://quarto.org/docs/download/

Then render the article using

text
quarto render article.ipynb

Tests Docs Manuscript Qmd Full README (`tests/docs/manuscript/qmd-full/README.md`)

Notebooks Now! Submission Template

This submission template is for a simple notebook-based publication with one source file, supporting data, bibliography, and Quarto build configuration.

Source file

The source file for this template is a Jupyter notebook. There is not necessarily anything special about this notebook. It may contain markdown cells, code cells, and outputs from common Python packages, including pandas, matplotlib, plotly, seaborn, and altair.

The notebook has an additional markdown cell at the top of the document which configures Quarto to render the notebook.

Supporting material

Supplementary data

By convention, all data should be saved in data/ directory. There is nothing magic about this directory; references to your data from your notebook must still specify the correct relative path.

Supplementary images

Similar to the data/ directory, images for figures should be specified in images/ directory.

Bibliography

Bibliography entries may be specific in the document as described in the Quarto documentation.

Quarto configuration

Configuration for the example is provided by a YAML block that appears as the first cell of the Notebook.

Building output artfiacts

To build PDF/JATS output from your source data, you must have the Quarto CLI installed - you can download or learn about installation at https://quarto.org/docs/download/

Then render the article using

text
quarto render article.ipynb

Tests Docs Manuscript Qmd Single README (`tests/docs/manuscript/qmd-single/README.md`)

Notebooks Now! Submission Template

This submission template is for a simple notebook-based publication with one source file, supporting data, bibliography, and Quarto build configuration.

Source file

The source file for this template is a Jupyter notebook. There is not necessarily anything special about this notebook. It may contain markdown cells, code cells, and outputs from common Python packages, including pandas, matplotlib, plotly, seaborn, and altair.

The notebook has an additional markdown cell at the top of the document which configures Quarto to render the notebook.

Supporting material

Supplementary data

By convention, all data should be saved in data/ directory. There is nothing magic about this directory; references to your data from your notebook must still specify the correct relative path.

Supplementary images

Similar to the data/ directory, images for figures should be specified in images/ directory.

Bibliography

Bibliography entries may be specific in the document as described in the Quarto documentation.

Quarto configuration

Configuration for the example is provided by a YAML block that appears as the first cell of the Notebook.

Building output artfiacts

To build PDF/JATS output from your source data, you must have the Quarto CLI installed - you can download or learn about installation at https://quarto.org/docs/download/

Then render the article using

text
quarto render article.ipynb

Tests Docs Reveal Mini README (`tests/docs/reveal/mini/README.md`)

Revealjs Mini Demos

This folder contains the source code for the embedded mini demos used in the Quarto Revealjs documentation.


Tests Docs Axe Scan Sites Brand Light Only README (`tests/docs/axe-scan/sites/brand-light-only/README.md`)

Fixture site: brand-light-only

A regression fixture for one decision: when does a page have a dark mode to
scan?

_brand.yml sets light values only. Quarto answers such a brand with the
colour-scheme link machinery but no dark mode behind it:

html
<link rel="stylesheet" class="quarto-color-scheme" data-mode="light" ...>
<link rel="stylesheet" class="quarto-color-scheme quarto-color-alternate"
      data-mode="light" href=".../bootstrap-dark-....min.css">
<link rel="stylesheet" class="quarto-color-scheme-extra" data-mode="light" ...>

Three traps sit in that markup. Every link is tagged data-mode="light", one
of them carries quarto-color-alternate, and one points at a dark Bootstrap
build. A probe that asks for [data-mode], or for the alternate class, or for
a -dark href, reads all this as "there is a dark theme". It then scans both
themes for nothing and reports duplicate coverage as if it were real. Found on
a live brand.yml site, 2026-08-20.

What the page does not carry is the inline before-body script (the one
that defines window.quartoToggleColorScheme): Quarto emits it iff the page
really has two modes. Mode discovery reads that marker, so each page here gets
exactly one cell, labelled default.

Do not add dark values to _brand.yml. That would make this an ordinary
two-mode site and delete the regression it guards.

Why a real project and not a hand-written page

The markup above belongs to Quarto. A hand-written page that reproduces it is
a mock of a contract we do not own, so it would keep passing after Quarto
changed what it emits. This site renders in the smoke test's setup, so the
fixture tracks Quarto. (The sniffer's reading of a distilled copy of this
markup is pinned browser-free in tests/unit/axe-mode-discovery.test.ts.)

The mock came first and was correct on the essential point. The real render is
richer: the mock had no quarto-color-alternate link and no dark Bootstrap
href, so it never covered two of the three traps.

Planted violation

One bare `` in index.qmd, so button-name fires and the
single default cell demonstrably scanned the page — a clean result would
look exactly like a page that was never scanned at all.

Keep this page minimal. A second, conditional finding would blur the one
comparison the site exists to make.

Intent against observed

Recorded from a full scan: 2/2 cells ok (one page, two viewports, one mode),
1 finding (1 new, 0 known), axe-core 4.10.3, signature scheme 1.

signature impact scope n pages viewports themes
button-name :: button critical localized 1 index.html both default

The cells are index__1440x900__default and index__320x568__default —
no light/dark pair, and no darkColoured annotation (the links measure
light).

One mode discovered means one presentation scanned. A page with hand-written
@media (prefers-color-scheme: dark) CSS and no Quarto dark mode still scans
once, and its dark-only findings are missed — the documented v1 blind spot
(see the design note's "The theme axis, settled").

Regenerating

bash
cd tests/docs/axe-scan/sites/brand-light-only
quarto render
quarto call axe _site          # writes _axe-checks/ next to _quarto.yml

Both _site/ and _axe-checks/ are throwaway. The smoke test removes them.


Tests Docs Axe Scan Sites Darkly README (`tests/docs/axe-scan/sites/darkly/README.md`)

Fixture site: darkly

A regression fixture for one decision: a one-mode page is one cell, whatever
colour that mode is.

theme: darkly ships a single dark-coloured presentation. Quarto's own
machinery still calls it the light slot: the rendered page says
body.quarto-light, and its sole id="quarto-bootstrap" link is tagged
data-mode="dark" only because the compiled CSS measures as dark (a blackness
sentinel, threshold 40%). So every declaration-level signal is misleading in
one direction or the other.

The scanner must:

  • discover one mode and label the cell default — never dark, and never
    a light/dark pair;
  • record the measured colour as an annotation — darkColoured: true in the
    cell payload, and a note on the console — never in the cell's name.

Do not add a light:/dark: theme pair here. That would make this an
ordinary two-mode site and delete the case it guards.

Planted violation

One bare `` in index.qmd, so button-name fires and the
default cell demonstrably scanned the page.

Intent against observed

Recorded from a full scan: 2/2 cells ok (one page, two viewports, one mode),
1 finding (1 new, 0 known), axe-core 4.10.3, signature scheme 1.

signature impact scope n pages viewports themes
button-name :: button critical localized 1 index.html both default

Both cells carry darkColoured: true, and the console prints the
dark-coloured note for index.html.

Regenerating

bash
cd tests/docs/axe-scan/sites/darkly
quarto render
quarto call axe _site          # writes _axe-checks/ next to _quarto.yml

Both _site/ and _axe-checks/ are throwaway. The smoke test removes them.


Tests Docs Axe Scan Sites Findings README (`tests/docs/axe-scan/sites/findings/README.md`)

Fixture site: findings

Grouping, the systemic against localized call, the impact spread, baseline
reconciliation, and the report. Also one page Quarto did not render.

The conditional findings that prove the scan matrix live in ../matrix/, and
light-only brand markup lives in ../brand-light-only/. Keep them there. This
site's assertions read page lists, and a conditional finding added here would
appear in some cells and not others for reasons unrelated to grouping.

Do not fix the accessibility problems in this directory. They are the test
data. _axe-baseline.json is committed for the same reason.

Planted violations

scope is what the scanner must conclude, not where the markup lives.
systemic means repeated from a shared source, which is three or more elements
or more than one page. localized means a one-off.

rule impact placement scope why it is here
image-alt critical _systemic.qmd, included by every content page systemic the critical end of the impact spread, and the systemic case
link-name serious index.qmd only localized the serious middle, and the localized case
heading-order moderate index.qmd only, h2 to h4 localized the moderate end
image-alt critical examples.qmd, marked .a11y-accepted-example localized a deliberate teaching example. v1 has no exclude-in-source, so the baseline absorbs it
button-name x2, image-alt, link-name critical and serious static/legacy.html systemic and localized signature edge cases in exact markup, and a page with no Quarto DOM

The page Quarto did not render

static/legacy.html is hand-written and copied through as a resource. A real
Quarto site does this whenever it ships a page Pandoc never touched.

The page earns its place for one reason: nothing in the scanner may require
Quarto's DOM. It has no colour-scheme machinery at all, so mode discovery must
give it one default cell per viewport while the Quarto pages around it get
the light/dark pair. The smoke test asserts both on the same scan, so a single
cell is provably a discovery about this page and not the scanner giving up
everywhere.

The page also carries exact markup for the signature-normalization edge cases,
which is convenient but not the reason it is here. Those cases are pinned
browser-free in tests/unit/axe-signature.test.ts and
tests/unit/axe-aggregate.test.ts.

Committed baseline

_axe-baseline.json exercises all four reconcile outcomes in one file.

entry outcome why
image-alt on the systemic include, pages: [] known site-wide acceptance, the right shape for shared chrome
link-name on index.html, pages: ["index.html"] known page-scoped acceptance that covers every page the finding occurs on
the .a11y-accepted-example image, page-scoped known stands in for exclude-in-source. When that ships, this entry must turn stale, which is a designed test of stale reporting
heading-order, accepted at impact: minor new planted as moderate, so escalation past the accepted impact re-alerts
a signature matching nothing stale reported for hand-pruning, never removed automatically

Intent against observed

axe chooses a minimal unique selector from the DOM as it finds it, so the
signature a planted violation produces is discovered, not decreed. The table
below records what this site actually produces. It is the contract the smoke
test asserts against.

Recorded from a full scan: 14/14 cells ok (three light+dark pages, one
default page), 9 findings (6 new, 3 known), axe-core 4.10.3, signature
scheme 1.

signature impact scope n pages viewports themes status
button-name :: button[data-widget-target="#panel-*"] critical systemic 3 static/legacy.html both default new
image-alt :: img critical systemic 2 about.html, index.html both both known
image-alt :: img[width="*"] critical localized 2 examples.html both both known
image-alt :: #hero critical localized 2 static/legacy.html both default new
button-name :: button[data-widget-target="#settings-dialog"] critical localized 1 static/legacy.html both default new
link-name :: a serious localized 2 static/legacy.html both default new
link-name :: p > a serious localized 1 index.html both both known
heading-order :: h4 moderate localized 1 index.html both both new
aria-allowed-role :: .navbar-toggler minor systemic 3 about.html, examples.html, index.html 320x568 both new

Stale baseline entries: region-fixture0.

Notes on the table

Three rows deserve a note.

  • aria-allowed-role :: .navbar-toggler comes from Quarto's own navbar, not
    from this fixture. It is a genuine finding and a useful one, systemic across
    three pages and mobile-only. It belongs to Quarto, so it can change or
    disappear on a Quarto upgrade. No test depends on it, and no test depends on
    the total finding count either.
  • image-alt :: #hero collapses two images whose id and style both
    differ. axe selected them by id (#hero-14, #hero-15), so the collapse came
    from the instance-id rule and not from the volatile-attribute rule. Either way
    the two become one finding, which is the intent.
  • link-name :: a is the widest collapse the scheme performs. axe keyed
    those two links on href, which is dropped as volatile, leaving the bare tag.
    Anything accepted at that signature is accepted for every unnamed a on the
    listed pages. That is exactly why the baseline's pages scope, and not the
    signature, is what keeps such an acceptance honest.

Regenerating

bash
cd tests/docs/axe-scan/sites/findings
quarto render
quarto call axe _site          # writes _axe-checks/ next to _quarto.yml

Both _site/ and _axe-checks/ are throwaway. The smoke test removes them.


Tests Docs Axe Scan Sites Matrix README (`tests/docs/axe-scan/sites/matrix/README.md`)

Fixture site: matrix

The two axes that justify scanning every page four times.

Every planted failure here is conditional, and each is reachable by exactly one
route. A cell that took the wrong route therefore fails an assertion, rather
than quietly reporting a duplicate.

Do not fix the accessibility problems in this directory. They are the test
data.

Keep unconditional violations out of this site. One would appear in all four
cells of every comparison the site exists to make. There is no
_axe-baseline.json here either, which also exercises a first run with no
ledger.

Planted violations

rule impact placement reachable by
color-contrast serious media.qmd, inside @media (prefers-color-scheme: dark) emulating a dark colour-scheme preference
color-contrast serious media.qmd, inside @media (max-width: 500px) the narrow viewport
color-contrast serious theme.qmd, from darkly's own palette seeding Quarto's colour-scheme localStorage key

Absence matters as much as presence. The dark-only findings must not appear
in the light cells, and the mobile-only finding must not appear at
1440x900.

Two routes into a dark cell

The theme axis tests the two presentations the author ships, not the two
states a user's OS can be in. A dark presentation can live in two places, and a
dark cell must select both:

  • media.qmd's failure is in author CSS under @media (prefers-color-scheme: dark), so emulation reaches it.
  • theme.qmd's failure is in darkly itself, so only seeding
    localStorage["quarto-color-scheme"] = "alternate" before navigation

    reaches it. Emulation cannot: Quarto's themes ignore prefers-color-scheme
    unless respect-user-color-scheme is set, and this site leaves it at its
    default of false. Without the seed, this failure is invisible and the dark
    cells render the light theme — which is why its assertion is the one that
    fails if mode selection regresses.

Every page here carries the before-body script marker, so discovery must give
every page the light/dark pair. A default cell on this site would mean a
dark cell silently vanished from the matrix; the smoke test asserts the pair
on every page. One-mode discovery is covered where it is correct, in
../brand-light-only/, ../darkly/ and on ../findings/static/legacy.html.

Intent against observed

Recorded from a full scan: 12/12 cells ok, 4 findings (4 new, 0 known),
axe-core 4.10.3, signature scheme 1.

signature impact scope n pages viewports themes
color-contrast :: #555555 on #333333 serious localized 1 media.html both dark
color-contrast :: #f8f8f8 on #f0f0f0 serious localized 1 media.html 320x568 both
color-contrast :: #6c757d on #222222 serious localized 1 theme.html both dark
aria-allowed-role :: .navbar-toggler minor systemic 3 index.html, media.html, theme.html 320x568 both

aria-allowed-role :: .navbar-toggler comes from Quarto's own navbar, not from
this fixture. It can change or disappear on a Quarto upgrade, so no test depends
on it.

Regenerating

bash
cd tests/docs/axe-scan/sites/matrix
quarto render
quarto call axe _site          # writes _axe-checks/ next to _quarto.yml

Both _site/ and _axe-checks/ are throwaway. The smoke test removes them.


Tests Docs Manual Preview Brand Detection README (`tests/docs/manual/preview/brand-detection/README.md`)

Brand detection during preview (#14593)

Manual fixture for the bug where quarto preview ignored a sibling _brand.yml
added or removed while the preview was running: project.brandCache was resolved
once and never invalidated, so the brand only took effect after restarting the
preview process. RStudio's "Render" button hits the same persistent preview
server, so it observed the same stale brand.

Drive this with the /quarto-preview-test workflow (start preview, mutate
_brand.yml, force a re-render, inspect output). See the parent
../README.md "Test Matrix: Brand Detection (#14593)" for the T28–T32 cases.

Files

File Role
report.qmd Minimal Typst doc with a link; keep-typ: true so the .typ is inspectable
brand-imperial.yml A brand setting primary: imperial-red (#BC1E22)

report.typ, report.pdf, _brand.yml, and .quarto/ are scratch produced by a
run — only report.qmd and brand-imperial.yml are tracked.

Brand signal

The brand is applied when the kept report.typ contains:

text
#show link: set text(fill: rgb("#bc1e22")

Present ⇒ brand ON (link colored). Absent ⇒ brand OFF.

Manual on/off check

  1. Start with no _brand.yml and preview the doc:
    quarto preview report.qmd --to typst --no-browser.
  2. ON — copy brand-imperial.yml to _brand.yml, force a re-render (touch
    report.qmd), and confirm report.typ gains the brand link-color line.
  3. OFF — remove _brand.yml, force another re-render, and confirm the
    line disappears.

Before the fix the brand stayed at its first-resolved state (OFF in the add case,
ON in the remove case) until the preview process was stopped. After the fix, the
resolve-time source-state guard on project.brandCache notices the _brand.yml
appear/disappear and re-resolves on the next render. A separate quarto render
(fresh context) always resolved the brand correctly, which is the disambiguator
that isolates the bug to the persistent preview context.


Tests Docs Manual Preview Sass Cache Crash 14594 README (`tests/docs/manual/preview/sass-cache-crash-14594/README.md`)

Sass cache reuse during preview (#14594)

Manual fixture for the bug where quarto preview of a book (or website) project
crashed with BadResource: Bad resource ID while recompiling the theme Sass on a
re-render. SassCache.cleanup() closed the session Deno.Kv handle but left the
stale instance in the module-level _sassCache registry, so the next
sassCache(path, temp) resolve reused the now-closed handle.

On each re-render the serve/watch reload path runs refreshProjectConfig
(src/project/serve/watch.ts, ~line 277 for HTML; also on any config change,
~line 305), which calls project.cleanup() and closes that session Sass KV
handle. The next render must open a fresh handle. RStudio's and Positron's live
preview hit the same persistent server, so they saw the same crash.

Drive this with the /quarto-preview-test workflow. See the parent ../README.md
"Test Matrix: Sass Cache Reuse (#14594)" for the T34-T36 cases.

Files

File Role
_quarto.yml Flat multi-chapter book with theme: cosmo + css: styles.css (routes the theme through the session Sass cache)
index.qmd, chapter1.qmd, chapter2.qmd Minimal chapters; a project preview re-renders these
styles.css Custom CSS so a real Sass compile runs alongside the cosmo theme

_book/ and .quarto/ are scratch produced by a run and are git-ignored.

Crash signal

Before the fix, after the first re-render the preview log shows:

text
BadResource: Bad resource ID

and pages stop reloading. After the fix, every re-render completes and reloads.

Deterministic unit coverage lives in tests/unit/sass-cache.test.ts; this fixture
is the interactive regression guide the unit test can't cover (live serve/watch
path).


Tests Docs Smoke All 2024 02 12 Issue 8712 README (`tests/docs/smoke-all/2024/02/12/issue-8712/README.md`)

A Quarto Manuscript Template

This is a template repo for generating a manuscript from Quarto that accompanies the tutorial at: Quarto Manuscripts: RStudio


Tests Docs Test Jupyter (`tests/docs/test-jupyter.md`)


title: Juptyer Test
jupyter:
kernelspec:
display_name: Python 3
language: python
name: python3



Tests Docs Unpaired Md (`tests/docs/unpaired-md.md`)


jupyter:
kernelspec:
display_name: Python 3
language: python
name: python3


python
print("Hello World")
python

Tests Docs Books Visualization Curriculum Requirements (`tests/docs/books/visualization-curriculum/requirements.txt`)

altair==4.1.0
altair-data-server==0.4.1
altair-saver==0.5.0
altair-viewer==0.3.0
anyio==3.0.1
appnope==0.1.2
argon2-cffi==20.1.0
async-generator==1.10
attrs==21.2.0
Babel==2.9.1
backcall==0.2.0
bleach==3.3.0
certifi==2020.12.5
cffi==1.14.5
chardet==4.0.0
decorator==5.0.9
defusedxml==0.7.1
entrypoints==0.3
idna==3.1
ipykernel==5.5.5
ipython==7.23.1
ipython-genutils==0.2.0
jedi==0.18.0
Jinja2==3.0.0
json5==0.9.5
jsonschema==3.2.0
jupyter-client==6.1.12
jupyter-core==4.7.1
jupyter-server==1.7.0
jupyterlab==3.0.15
jupyterlab-pygments==0.1.2
jupyterlab-server==2.5.1
MarkupSafe==2.0.0
matplotlib-inline==0.1.2
mistune==0.8.4
nbclassic==0.2.8
nbclient==0.5.3
nbconvert==6.0.7
nbformat==5.1.3
nest-asyncio==1.5.1
notebook==6.3.0
numpy==1.20.3
packaging==20.9
pandas==1.2.4
pandocfilters==1.4.3
parso==0.8.2
pexpect==4.8.0
pickleshare==0.7.5
portpicker==1.3.9
prometheus-client==0.10.1
prompt-toolkit==3.0.18
ptyprocess==0.7.0
pycparser==2.20
Pygments==2.9.0
pyparsing==2.4.7
pyrsistent==0.17.3
python-dateutil==2.8.1
pytz==2021.1
PyYAML==5.4.1
pyzmq==22.0.3
requests==2.25.1
selenium==3.141.0
Send2Trash==1.5.0
six==1.16.0
sniffio==1.2.0
terminado==0.9.5
testpath==0.4.4
toolz==0.11.1
tornado==6.1
traitlets==5.0.5
urllib3==1.26.4
vega-datasets==0.9.0
wcwidth==0.2.5
webencodings==0.5.1
websocket-client==0.59.0


Tests Docs Manual Preview 10392 Project Preview Stale Cache After Edit (`tests/docs/manual/preview/10392-project-preview-stale-cache-after-edit.md`)

Project preview serves stale rendered output after source edit (#10392)

Manual preview test for the fileInformationCache.fullMarkdown staleness bug on the project preview path (website / book). Reproduces deterministically.

What this catches

In a project preview, after editing a non-index .qmd:

  • The HTML file in _site/ IS regenerated (mtime advances).
  • The HTML body content does NOT contain the edit.
  • The browser reload signal fires but the served HTML is stale.
  • Stopping and restarting quarto preview clears the bug for the first edit; the second edit reproduces it.

Root cause: the persistent ProjectContext returned by watcher.project() owns a long-lived fileInformationCache. The HTTP-handler render in src/project/serve/serve.ts reuses that context. Without invalidation on watcher events, projectResolveFullMarkdownForFile (src/project/project-shared.ts) returned the pre-edit expanded markdown for the post-watcher HTTP-handler render call. The fix invalidates on watcher events (surgical) and adds an mtime + size freshness check to the cache (defense-in-depth).

Setup

Use the existing website fixture at tests/docs/manual/preview/project-preview/. It contains:

text
_quarto.yml          # type: website
index.qmd            # home page
about.qmd            # non-index page used by T1, T2, T6, T7
styles.css

The bug does not require code execution; pure prose edits to about.qmd trigger it. T7 needs a Jupyter-flavored input — use tests/docs/manual/preview/keep-ipynb.qmd or any .qmd with a Python code cell.

P1: Critical

T1: Edit a non-index `.qmd`, observe stale HTML body

  • Setup: Use the fixture tests/docs/manual/preview/project-preview/. The default body of about.qmd is About this site.
  • Steps:
    1. cd tests/docs/manual/preview/project-preview && quarto preview.
    2. Wait for preview to load and the default browser tab to open.
    3. Navigate the browser to http://localhost:/about.html.
    4. In about.qmd, replace About this site with MARKER-UNIQUE-STRING. Save.
    5. Wait 10 seconds (let watcher + re-render settle).
    6. Select-String -Path '_site/about.html' -Pattern MARKER-UNIQUE-STRING
    7. curl http://127.0.0.1:/about.html | Select-String MARKER-UNIQUE-STRING
    8. Reload the browser tab.
  • Expected (after fix): Step 6 and step 7 both return a match. Step 8 shows the new paragraph.
  • Catches: Persistent watcher.project().fileInformationCache.fullMarkdown returning stale expanded markdown to the HTTP-handler renderProject call site in src/project/serve/serve.ts.

T2: Repeat the edit a second time

  • Setup: Same as T1. Preview already running.
  • Steps:
    1. After T1 (do not restart preview).
    2. Edit about.qmd again, change MARKER-UNIQUE-STRING to MARKER-SECOND-STRING. Save.
    3. Wait 10 seconds.
    4. Repeat steps 6-8 of T1 with the new string.
  • Expected (after fix): Both checks find the new string.
  • Catches: Second-edit regression — verifies the fix invalidates the cache on every edit, not only on the first.

T3: Edit `index.qmd`

  • Setup: Same project.
  • Steps:
    1. Edit index.qmd, add INDEX-MARKER. paragraph. Save.
    2. Wait 10 seconds.
    3. Check _site/index.html and the served /index.html for INDEX-MARKER.
  • Expected: Both find the marker. This case worked before the fix too — keep it in the suite to confirm no regression on the index path.

P2: Important

T4: Edit affects sibling pages via cross-reference

  • Setup: Extend the fixture: add a secondary.qmd next to about.qmd containing a figure with #fig-x, then in about.qmd reference it via @fig-x.
  • Steps:
    1. Preview running.
    2. Edit the #fig-x label in secondary.qmd.
    3. Verify _site/about.html cross-reference text updates.
  • Catches: Cache invalidation does not propagate to other files in the project that reference the changed file. Lower priority because the immediate symptom (stale body on the directly-edited file) is the main bug.

T7: Concurrent saves during in-flight HTTP-handler render (Jupyter input)

This case proves the surgical-fix invalidation is correctly serialized with the render queue. Before the fix at the queue level, invalidateForFile ran before submitRender, so a concurrent in-flight render (typically the HTTP-handler's renderProject call) could lose its transient .quarto_ipynb mid-read and fail intermittently. After the fix, invalidation runs inside the submitRender callback so the queue serializes it with prior renders.

  • Setup: Use a Jupyter .qmd (e.g., tests/docs/manual/preview/keep-ipynb.qmd rendered into a website project, or copy a Python-cell .qmd into project-preview/). The input must produce a transient .quarto_ipynb for the race to be reachable.
  • Steps:
    1. quarto preview against the project containing the Jupyter .qmd.
    2. Open the page in the browser to trigger an HTTP-handler render that reads the transient .quarto_ipynb.
    3. While the HTTP-handler render is still in flight (best done by editing during a long-running Python cell), save the .qmd 5 times in quick succession (≤ 1s between saves). Aim to fire the watcher while step 2's render is still executing.
    4. Watch the quarto preview console for errors of the form "file not found" / "cannot read .quarto_ipynb" / ENOENT.
  • Expected (after fix): No file-not-found errors in the console (ENOENT / BadResource / "cannot read .quarto_ipynb"). All renders complete cleanly. The HTML reflects the last coalesced render — under a sub-second burst the watcher collapses the saves into a single execution, so the final body may correspond to the first read of the burst rather than the very last keystroke. That coalescing is render-scheduling behavior, not a cache-staleness failure; a single edit or edits seconds apart always render fresh. The trailing-render-after-coalesce gap is tracked separately as a follow-up.
  • Catches: Race between watcher-triggered invalidateForFile and an in-flight render holding the transient notebook open. Window is narrow but reproducible on slow Python cells (use a time.sleep(5) cell to widen it). This case asserts transient-notebook safety under concurrency, not last-keystroke freshness.

P3: Polish

T5: `freeze: auto` + pure markdown edit

  • Setup: Add execute: freeze: auto to _quarto.yml.
  • Steps:
    1. T1 with freeze: auto.
  • Expected: Same outcome as T1 (freeze should not affect plain markdown).

T6: WebSocket reload target points at the right page

  • Setup: Browser open on /about.html.
  • Steps: T1, watch the browser console.
  • Expected: WebSocket reload signal fires; the page reloads with the new content.

Blast-radius regression protocol

The fix touches two surfaces with different reach:

  • A — invalidateForFile(input) loop in src/project/serve/watch.ts. Runs in project preview only. Calls a function already used elsewhere (#14281, preview.ts); only the call site is new.
  • B — mtime + size guard in projectResolveFullMarkdownForFile (src/project/project-shared.ts). Runs everywhere the function is called: every render (single doc + project), the single-file project type, quarto inspect, and the knitr (rmd.ts) and jupyter (jupyter.ts) execute paths.

Outside preview, B is functionally a no-op (a one-shot context never sees the source change mid-life, so the guard always agrees with the old cache), but it adds one Deno.statSync per cache hit. The cases below confirm both that the fix works on its target surfaces and that the wide change B introduces no regression or perceptible cost elsewhere.

These are interactive preview tests (require real file-save events) and cannot run as automated smoke tests. Drive them with /quarto-preview-test. The #14281 accumulation matrix in README.md covers transient-notebook accumulation; the cases here cover content freshness after an edit, a different axis.

P1: Critical

T8: Single-document preview — freshness after body edit (guard B, single-file path)

  • Setup: tests/docs/manual/preview/plain.qmd (pure markdown, no project).
  • Steps:
    1. quarto preview tests/docs/manual/preview/plain.qmd.
    2. Edit a body line to MARKER-T8. Save. Wait 5s.
    3. curl http://127.0.0.1:/ | Select-String MARKER-T8 and reload the browser.
  • Expected: Both find MARKER-T8.
  • Catches: Guard B regressing the single-file project type's resolve path — the one surface where single-doc preview leans on B alone (no watcher invalidation A).

T9: Project + Jupyter `.qmd` — freshness after edit, no accumulation

  • Setup: In project-preview/, add pycell.qmd with a Python cell (print("v1")) and link it from index.qmd. Requires the Python test env.
  • Steps:
    1. cd tests/docs/manual/preview/project-preview && quarto preview.
    2. Open /pycell.html. Change the cell to print("v2"). Save. Wait 10s.
    3. Check _site/pycell.html and the served page for v2.
    4. ls *.quarto_ipynb* — confirm at most one pycell.quarto_ipynb, no _1/_2 variants.
  • Expected: Fresh v2 output; at most one transient notebook; zero after Ctrl+C.
  • Catches: A interacting badly with the #14281 transient cleanup, or stale jupyter output surviving the edit.

T10: Project + raw `.ipynb` input — source preserved, content fresh

  • Setup: Copy a native .ipynb (the T11 notebook from the README #14281 matrix, or any executed notebook) into project-preview/ as notebook.ipynb; link from index.qmd.
  • Steps:
    1. quarto preview the project. Open /notebook.html.
    2. Edit a markdown cell in notebook.ipynb to add MARKER-T10. Save. Wait 10s.
    3. After Ctrl+C, confirm notebook.ipynb still exists on disk.
  • Expected: MARKER-T10 in served HTML; notebook.ipynb not deleted (its cache entry has transient = false, so invalidateForFile must not safeRemoveSync it).
  • Catches: The new A call site firing invalidateForFile on a user .ipynb and wrongly deleting the source.

P2: Important

T11: Project + knitr `.qmd` — freshness after edit (regression for guard B on `rmd.ts`)

  • Setup: In project-preview/, add rcell.qmd with engine: knitr and an R cell (print("r-v1")); link from index.qmd. Requires the R test env.
  • Steps: Preview the project; change the cell to print("r-v2"); save; wait 10s; check served /rcell.html.
  • Expected: Fresh r-v2. No .quarto_ipynb files (knitr has no jupyter intermediate).
  • Catches: Guard B regressing the knitr resolve path (src/execute/rmd.ts:245).

T12: Format-change + stale-body invalidation coexist in one project preview

  • Setup: project-preview/about.qmd, default format: html.
  • Steps:
    1. Preview the project. Edit about.qmd body to MARKER-T12a. Save. Confirm fresh (the #10392 path, A).
    2. Without restarting, edit about.qmd frontmatter to format: typst. Save. Trigger one render.
  • Expected: Step 1 serves fresh body; step 2 detects the format change (#14533) without the two invalidation sites — watch.ts (A) and preview.ts compatibility check — conflicting.
  • Catches: Double-invalidation interaction (over-eager eviction → spurious 404, or under-eager → stale format). Cross-ref README.md #14533 T20–T25.

P3: Polish

T13: `quarto inspect` after an edit (guard B + added `statSync`)

  • Setup: Any project file.
  • Steps: quarto inspect <file>, edit the file, quarto inspect <file> again in the same shell.
  • Expected: Both succeed; second reflects the edit. No error from the added Deno.statSync.
  • Catches: Guard B or the stat breaking the inspect resolve calls (src/inspect/inspect.ts).

T14: Book / many-file project — perf sanity for per-hit `statSync`

  • Setup: A multi-chapter book (10+ inputs), e.g. quarto create project book.
  • Steps: quarto render the book cold, then quarto preview and edit one chapter.
  • Expected: No perceptible slowdown vs upstream/main; edited chapter renders fresh.
  • Catches: The extra Deno.statSync per cache hit (guard B) becoming a noticeable cost at scale. Expected negligible; this is the explicit check.

Cleanup

quarto preview exit (Ctrl+C). No persistent state to clean up beyond _site/ which the next preview run rebuilds. Remove any ad-hoc fixtures added for T9–T14 (pycell.qmd, notebook.ipynb, rcell.qmd) — they are not committed.

  • tests/docs/manual/preview/README.md — manual preview test matrix
  • tests/docs/manual/preview/14281-quarto-ipynb-accumulation.qmd — neighboring manual test (different bug, similar structure)

Tests Docs Manual Preview 14359 Positron Kill Quarto Ipynb (`tests/docs/manual/preview/14359-positron-kill-quarto-ipynb.md`)

Manual Test: .quarto_ipynb cleanup on ungraceful termination (#14359)

Purpose

Verify that .quarto_ipynb files are cleaned up after render even when preview
is killed ungracefully (e.g., Positron terminal bin icon). This tests the fix
that restores immediate deletion in cleanupNotebook().

Why manual? Ungraceful termination bypasses normal cleanup handlers.
The fix ensures deletion happens right after execution, before any signal
could interrupt the process.

Automated coverage

The smoke-all test tests/docs/smoke-all/2025/05/21/keep_ipynb_single-file/14359.qmd
verifies the core behavior (file deleted after render). This manual test
covers the interactive preview scenario.

Steps

  1. Open Positron (or VS Code with Quarto extension)
  2. Open tests/docs/manual/preview/14281-quarto-ipynb-accumulation.qmd
  3. Start Quarto Preview (terminal or Quarto extension)
  4. Wait for first render to complete
  5. Check directory: ls *.quarto_ipynb* — should be zero files (file was deleted after render)
  6. Edit and save the file to trigger a re-render
  7. After re-render completes, check again — still zero .quarto_ipynb files
  8. Kill preview ungracefully (Positron terminal bin icon / close terminal)
  9. Check directory — still zero .quarto_ipynb files

Expected

  • Zero .quarto_ipynb files at all times (the file is deleted immediately
    after each execution, not deferred to cleanup handlers)
  • Ungraceful termination does not leave stale files because deletion already
    happened

Note on Positron fix

Quarto extension v1.131.0 (posit-dev/positron#13006) now sends
previewTerminateRequest() when the terminal is closed, giving Quarto
a clean shutdown. Our fix (immediate deletion after execution) and their
fix (clean shutdown signal) are complementary — either alone prevents
stale files, both together provide defense in depth.

  • #14281 — within-session accumulation (fixed by PR #14287)
  • #12780 — keep-ipynb support (PR #12793 introduced this regression)
  • posit-dev/positron#13006 — Killing Quarto Preview should exit process (fixed in extension v1.131.0)

Tests Docs Project Ai Config Files AGENTS (`tests/docs/project/ai-config-files/AGENTS.md`)


title: "Agents Configuration"

This is an agents.md configuration file that should be ignored during project scanning.


Tests Docs Project Ai Config Files CLAUDE (`tests/docs/project/ai-config-files/CLAUDE.md`)


title: "Claude Configuration"

This is an AI assistant configuration file that should be ignored during project scanning.


Tests Docs Project Output Dir Parent Ref Marker (`tests/docs/project/output-dir-parent-ref/marker.txt`)

This file should NOT be deleted when rendering with output-dir: ../output-dir-parent-ref
This pattern references the project directory via parent traversal.


Tests Docs Project Output Dir Safety Marker (`tests/docs/project/output-dir-safety/marker.txt`)

This file should NOT be deleted when rendering with output-dir: ./
If this file is missing after render, the bug is present.


Tests Docs Playwright Html Code Highlight Body (`tests/docs/playwright/html/code-highlight/_body.md`)

Light and Dark Mode Testing

This document can be viewed in both light mode and dark mode to test code highlighting in both color schemes.

{.julia}
function divide_floats(x::Float64, y::Float64)
    return x / y
end

And here the inline version function divide_floats(x::Float64, y::Float64){.julia}.

::: {.callout-note}
The tests will automatically check the highlighting in both light and dark modes using Playwright's color scheme testing capabilities.
:::


Tests Docs Directives Include Test1 Sub Include 1 (`tests/docs/directives/include/test1/sub/include-1.md`)

Inner-1

Here is a relative link.

inherited fixup

{{< include sub/include-2.md >}}

forced fixup

{{< include sub/include-2.md fixup=true >}}

forced no fixup

{{< include sub/include-2.md fixup=false >}}


Tests Docs Smoke All 2023 09 13 Knitr Warning Panel Layout (`tests/docs/smoke-all/2023/09/13/knitr-warning-panel-layout.md`)


title: Knitr Table Test keep-md: true

::: {#tbl-tables .cell layout-ncol="2" tbl-cap='Tables'}

{.r .cell-code}
library(knitr)

::: {.cell-output .cell-output-stderr}

text
Warning: le package 'knitr' a été compilé avec la version R 4.2.3

:::

{.r .cell-code}
kable(head(cars), caption = "Cars {#tbl-cars}")

::: {.cell-output-display}

Table: Cars {#tbl-cars}

speed dist
4 2
4 10
7 4
7 22
8 16
9 10

:::

{.r .cell-code}
kable(head(pressure), caption = "Pressure {#tbl-pressure}")

::: {.cell-output-display}

Table: Pressure {#tbl-pressure}

temperature pressure
0 0.0002
20 0.0012
40 0.0060
60 0.0300
80 0.0900
100 0.2700

:::
:::

See @tbl-cars for more information.


Tests Docs Smoke All 2023 09 18 6871 Adoc (`tests/docs/smoke-all/2023/09/18/6871-adoc.md`)


title: Knitr Table Test format: asciidoc keep-md: true \_quarto: tests: asciidoc: ensureFileRegexMatches: # The checks here are looser than I'd like, because checking for asciidoc # nested structures in line-by-line regexes seems impossible, but this # is the only smoke-all test we can run in asciidoc.. # # TODO this is a problem. - - "\\[\\[tbl-cars\\]\\]" - "\\[\\[tbl-pressure\\]\\]" - "\\[#tbl-tables\\]" # TODO understand the difference between [[foo]] and [#foo]. From my reading of the asciidoc docs it seems ok but we should double-check. - "\\. Tables" - "\\. Cars" - "\\. Pressure" - []

::: {#tbl-tables .cell layout-ncol="2" tbl-cap='Tables'}

{.r .cell-code}
library(knitr)

::: {.cell-output .cell-output-stderr}

text
Warning: le package 'knitr' a été compilé avec la version R 4.2.3

:::

{.r .cell-code}
kable(head(cars), caption = "Cars {#tbl-cars}")

::: {.cell-output-display}

Table: Cars {#tbl-cars}

speed dist
4 2
4 10
7 4
7 22
8 16
9 10

:::

{.r .cell-code}
kable(head(pressure), caption = "Pressure {#tbl-pressure}")

::: {.cell-output-display}

Table: Pressure {#tbl-pressure}

temperature pressure
0 0.0002
20 0.0012
40 0.0060
60 0.0300
80 0.0900
100 0.2700

:::
:::

See @tbl-cars for more information.


Tests Docs Smoke All 2023 09 18 6871 (`tests/docs/smoke-all/2023/09/18/6871.md`)


title: Knitr Table Test
format: jats
keep-md: true
_quarto:
tests:
jats:
ensureJatsXpath:
- - '//fig//fig[@id="tbl-cars"]//table'
- '//fig//fig[@id="tbl-cars"]//caption'
- '//fig//fig[@id="tbl-pressure"]//table'
- '//fig//fig[@id="tbl-pressure"]//caption'
- '//fig[@id="tbl-tables"]/caption'
- []


::: {#tbl-tables .cell layout-ncol="2" tbl-cap='Tables'}

{.r .cell-code}
library(knitr)

::: {.cell-output .cell-output-stderr}

text
Warning: le package 'knitr' a été compilé avec la version R 4.2.3

:::

{.r .cell-code}
kable(head(cars), caption = "Cars {#tbl-cars}")

::: {.cell-output-display}

Table: Cars {#tbl-cars}

speed dist
4 2
4 10
7 4
7 22
8 16
9 10

:::

{.r .cell-code}
kable(head(pressure), caption = "Pressure {#tbl-pressure}")

::: {.cell-output-display}

Table: Pressure {#tbl-pressure}

temperature pressure
0 0.0002
20 0.0012
40 0.0060
60 0.0300
80 0.0900
100 0.2700

:::
:::

See @tbl-cars for more information.


Tests Docs Smoke All 2023 09 18 6873 (`tests/docs/smoke-all/2023/09/18/6873.md`)


title: "table" format: html keep-md: true

::: {#tbl-unetable .cell}

{.r .cell-code}
library(gt)
start_date <- "2010-06-07"
end_date <- "2010-06-14"
sp500 |>
  dplyr::filter(date >= start_date & date <= end_date) |>
  dplyr::select(-adj_close) |>
  gt() |>
  tab_header(
    title = "S&P 500",
    subtitle = glue::glue("{start_date} to {end_date}")
  ) |>
  fmt_currency() |>
  fmt_date(columns = date, date_style = "wd_m_day_year") |>
  fmt_number(columns = volume, suffixing = TRUE)

::: {.cell-output-display}

text
/* Detailed source-code truncated for AI context efficiency. */

:::
:::


Tests Docs Smoke All 2024 02 12 8711.Pdf (`tests/docs/smoke-all/2024/02/12/8711.pdf.md`)


title: "Untitled"
format:
pdf:
keep-md: true
crossref:
custom:
- kind: float
key: out
latex-env: notoutput
reference-prefix: Output


::: {.cell}

{.r .cell-code}
knitr::kable(mtcars)

::: {.cell-output-display}

mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2

:::
:::

::: {#out-2}

::: {.cell}
::: {.cell-output .cell-output-stdout}

text
Call:
   aov(formula = yield ~ block + N * P + K, data = npk)

Terms:
                   block        N        P        K      N:P Residuals
Sum of Squares  343.2950 189.2817   8.4017  95.2017  21.2817  218.9033
Deg. of Freedom        5        1        1        1        1        14

Residual standard error: 3.954232
Estimated effects may be unbalanced

:::
:::

Sample ANOVA output

:::

See @out-2


Tests Docs Smoke All 2024 02 13 8711.Pdf (`tests/docs/smoke-all/2024/02/13/8711.pdf.md`)


title: "Untitled"
format: latex
crossref:
custom:
- kind: float
key: out
latex-env: notoutput
reference-prefix: Output
caption-location: top
_quarto:
tests:
latex:
ensureFileRegexMatches:
- ["\\begin\{longtable"]
- []


:::{#tbl-1}

::: {.cell}
::: {.cell-output-display}

mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2

:::
:::

Table caption.

:::

See @tbl-1.

::: {#out-2}

::: {.cell}
::: {.cell-output .cell-output-stdout}

text
Call:
   aov(formula = yield ~ block + N * P + K, data = npk)

Terms:
                   block        N        P        K      N:P Residuals
Sum of Squares  343.2950 189.2817   8.4017  95.2017  21.2817  218.9033
Deg. of Freedom        5        1        1        1        1        14

Residual standard error: 3.954232
Estimated effects may be unbalanced

:::
:::

Sample ANOVA output

:::

See @out-2


Tests Docs Smoke All 2024 02 16 8711.Pdf (`tests/docs/smoke-all/2024/02/16/8711.pdf.md`)


title: "Untitled"
format:
latex:
keep-md: true
crossref:
custom:
- kind: float
key: out
latex-env: notoutput
reference-prefix: Output
_quarto:
tests:
latex:
ensureFileRegexMatches:
- ["\\begin\{longtable"]
- ["\\begin\{tabular"]


::: {#tbl-1 .cell tbl-cap='Table caption'}

{.r .cell-code}
knitr::kable(mtcars)

::: {.cell-output-display}

mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2

:::
:::

::: {.cell}

{.r .cell-code}
knitr::kable(mtcars)

::: {.cell-output-display}

mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2

:::
:::

Default Left Right Center
12 12 12 12
123 123 123 123
1 1 1 1

: Demonstration of pipe table syntax

::: {#out-2}

::: {.cell}
::: {.cell-output .cell-output-stdout}

text
Call:
   aov(formula = yield ~ block + N * P + K, data = npk)

Terms:
                   block        N        P        K      N:P Residuals
Sum of Squares  343.2950 189.2817   8.4017  95.2017  21.2817  218.9033
Deg. of Freedom        5        1        1        1        1        14

Residual standard error: 3.954232
Estimated effects may be unbalanced

:::
:::

Sample ANOVA output

:::

See @out-2


Tests Docs Smoke All 2024 06 05 9696 (`tests/docs/smoke-all/2024/06/05/9696.md`)


title: "dash-test"
format: dashboard
keep-md: true
editor: visual
editor_options:
chunk_output_type: console
_quarto:
tests:
dashboard:
ensureHtmlElements:
- []
- ["div.cell.hidden"]


Heading

::: {.cell title='a title0'}
::: {.cell-output-display}

text
/* Detailed source-code truncated for AI context efficiency. */

:::
:::


Tests Docs Extensions Format Resources 9918 Extensions Test Dummy 4 (`tests/docs/extensions/format-resources/9918/_extensions/test/dummy-4.txt`)

This file should be copied to root project for rendering as it is included as a format-resources


Tests Docs Smoke All Typst Relative Font Path Artifacts Fonts OFL (`tests/docs/smoke-all/typst/relative-font-path/artifacts/fonts/OFL.txt`)

Copyright 2016 The Amaranth Project Authors (https://github.com/googlefonts/amaranth)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org


SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:

  1. Neither the Font Software nor any of its individual components,
    in Original or Modified Versions, may be sold by itself.

  2. Original or Modified Versions of the Font Software may be bundled,
    redistributed and/or sold with any software, provided that each copy
    contains the above copyright notice and this license. These can be
    included either as stand-alone text files, human-readable headers or
    in the appropriate machine-readable metadata fields within text or
    binary files as long as those fields can be easily viewed by the user.

  3. No Modified Version of the Font Software may use the Reserved Font
    Name(s) unless explicit written permission is granted by the corresponding
    Copyright Holder. This restriction only applies to the primary font name as
    presented to the users.

  4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font
    Software shall not be used to promote, endorse or advertise any
    Modified Version, except to acknowledge the contribution(s) of the
    Copyright Holder(s) and the Author(s) or with their explicit written
    permission.

  5. The Font Software, modified or unmodified, in part or in whole,
    must be distributed entirely under this license, and must not be
    distributed under any other license. The requirement for fonts to
    remain under this license does not apply to any document created
    using the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.


Tests Docs Extensions Format Resources 9918 Extensions Test Files To Root Dummy 2 (`tests/docs/extensions/format-resources/9918/_extensions/test/files-to-root/dummy-2.txt`)

This file should be copied to root project for rendering as it is included as a format-resources


Tests Docs Extensions Format Resources 9918 Extensions Test Files To Root Dummy 3 (`tests/docs/extensions/format-resources/9918/_extensions/test/files-to-root/dummy-3.txt`)

This file should be copied to root project for rendering as it is included as a format-resources


Tests Docs Extensions Format Resources 9918 Extensions Test Folder To Root Dummy (`tests/docs/extensions/format-resources/9918/_extensions/test/folder-to-root/dummy.txt`)

This file should be copied to root project for rendering as it is included as a format-resources


--- METRICS ---