Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .claude/rules/dev-tools/dependency-updates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
description: "Bundled dependency version bumps (Deno, Pandoc, Dart Sass, Typst, esbuild, veraPDF)"
paths:
- "configuration"
- "src/command/check/check.ts"
---

# Bundled Dependency Updates

When updating a bundled binary, follow `dev-docs/upgrade-dependencies.md`. For Pandoc, also follow `dev-docs/update-pandoc-checklist.md`.
9 changes: 8 additions & 1 deletion .claude/rules/formats/pandoc-templates.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
---
paths:
- "src/resources/formats/pdf/pandoc/**"
- "src/resources/formats/beamer/pandoc/**"
- "src/resources/formats/typst/pandoc/**"
- "src/resources/formats/html/pandoc/**"
- "src/resources/formats/revealjs/pandoc/**"
- "src/resources/formats/asciidoc/pandoc/**"
- "package/src/common/update-pandoc.ts"
- "dev-docs/update-pandoc-checklist.md"
---

# Pandoc Templates (LaTeX & Typst)
# Pandoc Templates (LaTeX, Typst, HTML, Reveal.js, AsciiDoc)

For how Pandoc's LaTeX templates are copied into Quarto and restructured into a modular form (`latex.template`, `latex.common`, …), see `llm-docs/pandoc-quarto-latex-templates.md`.

For the equivalent Typst template integration (`typst.template`, `template.typst`), see `llm-docs/pandoc-quarto-typst-templates.md`.

When updating Pandoc templates, read `dev-docs/update-pandoc-checklist.md` for the per-format file list, reference-copy maintenance, and filename checks.
10 changes: 10 additions & 0 deletions .github/actions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Composite Actions

Reusable steps shared across workflows in this repo. See also `.github/workflows/actions/` for another set of composite actions (historical split, no functional difference).

| Action | Purpose |
|--------|---------|
| [`build-dist-tarball`](build-dist-tarball/action.yml) | Builds and uploads a versioned Quarto distribution tarball from the current checkout. |
| [`cache-typst`](cache-typst/action.yml) | Configures caching for Typst packages. |
| [`docker`](docker/action.yml) | Builds and pushes a Quarto Docker container to the GitHub Container Registry. |
| [`merge-extension-tests`](merge-extension-tests/action.yml) | Copies test files from extension subtrees into the main test directories. |
13 changes: 13 additions & 0 deletions .github/workflows/actions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Composite Actions

Reusable steps shared across workflows in this repo. See also `.github/actions/` for another set of composite actions (historical split, no functional difference).

| Action | Purpose |
|--------|---------|
| [`amplitude`](amplitude/action.yml) | Sends an event to Amplitude. |
| [`archive`](archive/action.yml) | Archives a dependency binary to S3. |
| [`keychain`](keychain/action.yml) | Configures a P12 certificate into the keychain for signing. |
| [`pandoc-override`](pandoc-override/action.yml) | Installs a Pandoc release for smoke tests before S3 archival and selects it through `QUARTO_PANDOC`. |
| [`prevent-rerun`](prevent-rerun/action.yml) | Fails if the workflow is re-run (`github.run_attempt > 1`). |
| [`quarto-dev`](quarto-dev/action.yml) | Configures the image for Quarto development (runs `configure.sh`/`.cmd`). |
| [`sign-files`](sign-files/action.yml) | Installs and configures the environment to sign files. |
48 changes: 48 additions & 0 deletions .github/workflows/actions/pandoc-override/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: "Pandoc Override"
description: "Installs a Pandoc release for smoke tests before S3 archival and selects it through QUARTO_PANDOC. If pandoc-version is empty, Quarto uses the configured binary."

inputs:
pandoc-version:
description: "Pandoc release tag to install and use instead of the archived/configured version (e.g. 3.10.1). Leave empty to skip."
required: false
default: ""

runs:
using: "composite"
steps:
- name: Install Pandoc override
if: inputs.pandoc-version != ''
uses: r-lib/actions/setup-pandoc@v2
with:
pandoc-version: ${{ inputs.pandoc-version }}

- name: Point QUARTO_PANDOC at override (Linux, macOS)
if: runner.os != 'Windows' && inputs.pandoc-version != ''
shell: bash
run: echo "QUARTO_PANDOC=$(command -v pandoc)" >> "$GITHUB_ENV"

- name: Point QUARTO_PANDOC at override (Windows)
if: runner.os == 'Windows' && inputs.pandoc-version != ''
shell: pwsh
run: |
"QUARTO_PANDOC=$((Get-Command pandoc).Source)" >> $env:GITHUB_ENV

# Lets check-versions-no-mismatch.test.ts tell an intentional override
# apart from a real bundled-version mismatch. Passed via env so the
# dispatch input is never interpolated into the shell script.
- name: Record expected Pandoc version for the version-mismatch test
if: inputs.pandoc-version != ''
shell: bash
env:
PANDOC_VERSION: ${{ inputs.pandoc-version }}
run: echo "QUARTO_TEST_EXPECTED_PANDOC=$PANDOC_VERSION" >> "$GITHUB_ENV"

- name: Confirm Pandoc override is live (Linux, macOS)
if: runner.os != 'Windows' && inputs.pandoc-version != ''
shell: bash
run: quarto pandoc --version

- name: Confirm Pandoc override is live (Windows)
if: runner.os == 'Windows' && inputs.pandoc-version != ''
shell: pwsh
run: quarto pandoc --version
11 changes: 11 additions & 0 deletions .github/workflows/test-smokes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ on:
required: false
type: string
default: ""
pandoc-override-version:
description: "Pandoc release tag to download from GitHub for smoke tests before S3 archival (e.g. 3.10.1). Quarto selects it through QUARTO_PANDOC. Leave empty to use the configured binary."
required: false
type: string
default: ""

# this is required to cleanup julia cache
permissions:
Expand Down Expand Up @@ -504,6 +509,12 @@ jobs:
echo "QUARTO_TEST_EXPECTED_VERSION=$QUARTO_VERSION_INPUT" >> "$GITHUB_ENV"
fi

# Guarded at the step so runs on older refs, which lack this action, never load it.
- if: inputs.pandoc-override-version != ''
uses: ./.github/workflows/actions/pandoc-override
with:
pandoc-version: ${{ inputs.pandoc-override-version }}

- name: Install Tinytex
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
68 changes: 62 additions & 6 deletions dev-docs/update-pandoc-checklist.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
## Updating the bundled version of Pandoc

Carlos needs to run this:
Updating Pandoc happens in two phases. Phase 1 (prep) needs no S3 access and can be done by anyone; Phase 2 (archival) is done by whoever holds S3 write credentials, right before merge.

- [ ] Ensure archives are upgraded
- [ ] Run `AWS_PROFILE=... ./package/src/quarto-bld update-pandoc PANDOC_VERSION`
- [ ] look at `git diff`, specifically for changes in Pandoc templates, and adjust as needed.
### Phase 1 - prep (no S3, anyone)

As a reminder, our templates are kept in the same directories as Pandoc's templates, but with different names. `git diff` will show the diff in Pandoc's template; we have to manually patch
ours. (We can't just use `patch` because the templates have diverged too much)
Regenerate the reference copies and `src/core/pandoc/format-extension.ts`, port relevant changes to Quarto's templates, and verify rendering. Keep `configuration`'s `export PANDOC=` line at the archived version so `./configure.sh`/`.cmd` continues to work.

Run the template/variant regeneration with `--skip-archive`, pointing `QUARTO_PANDOC` at an executable of the target version:

```bash
QUARTO_PANDOC=/path/to/pandoc-3.10.1/bin/pandoc \
./package/src/quarto-bld update-pandoc 3.10.1 --skip-archive
```

`--skip-archive` skips S3 archival, the `configureDependency` download, and the `configuration` rewrite. It still runs `writePandocTemplates` to regenerate the mapped template files and `writeVariants` to regenerate `format-extension.ts`.

`QUARTO_PANDOC` is required: `writeVariants` uses that binary to enumerate formats and extensions. The command checks its version before regenerating files. Review and commit the resulting working-tree diff.

`writePandocTemplates` overwrites the reference copies and mapped Pandoc partials such as `fonts.latex` and `hypersetup.latex`. Port relevant changes to Quarto's templates using the [file list below](#pandoc-templates). Review generated changes to `format-extension.ts` as well. The same review applies to the full Phase 2 run.

To smoke-test rendering before archival, dispatch `.github/workflows/test-smokes.yml` with `pandoc-override-version` set to the new release tag (e.g. `3.10.1`). The workflow downloads Pandoc from GitHub and uses it via `QUARTO_PANDOC` for that run, without S3 access. Limit `buckets` to the relevant smoke-all directories (e.g. `typst`, `latex`, `table`) for a faster run.

For a full-suite run, the action sets `QUARTO_TEST_EXPECTED_PANDOC`. The version check accepts either OK or a strict-mismatch note for the requested version, normalized as in `check.ts`.

### Phase 2 - archival (S3 credential holder, before merge)

Whoever holds S3 write credentials does this last, right before merging:

- [ ] Bump `configuration`'s `export PANDOC=` line and the `Pandoc` entry in `src/command/check/check.ts`'s `versionConstraints` array to the new version (this constraint tracks the bundled version exactly).
- [ ] Ensure archives are upgraded.
- [ ] Run `AWS_PROFILE=... ./package/src/quarto-bld update-pandoc PANDOC_VERSION` (without `--skip-archive`) to archive the binary to S3, configure it locally, and regenerate templates/variants.
- [ ] Review `git diff` for regenerated reference copies, mapped Pandoc partials, and `format-extension.ts`. Port any remaining upstream changes to Quarto's templates and reapply any Quarto changes overwritten in mapped partials.
- [ ] Run the `create-release.yml` dry-run signing/notarization gate (see `dev-docs/upgrade-dependencies.md`), then merge.

Quarto's templates share directories with the Pandoc reference copies, but use different names. Review the reference-copy diffs and port relevant changes manually; the templates have diverged too much to use `patch`.

### Pandoc templates

Expand All @@ -25,6 +51,36 @@ Partials:
- Ours:
- src/resources/formats/beamer/pandoc/common.latex

#### pdf / latex

- Pandoc's: src/resources/formats/pdf/pandoc/latex.template
- Ours: src/resources/formats/pdf/pandoc/template.tex (see `llm-docs/pandoc-quarto-latex-templates.md` for the full partial breakdown, including `latex.common`/`common.latex`)

#### html

- Pandoc's: src/resources/formats/html/pandoc/html.template, src/resources/formats/html/pandoc/html.styles
- Ours: src/resources/formats/html/pandoc/template.html, src/resources/formats/html/pandoc/styles.html

#### revealjs

- Pandoc's: src/resources/formats/revealjs/pandoc/revealjs.template
- Ours: src/resources/formats/revealjs/pandoc/template.html

#### asciidoc

- Pandoc's: src/resources/formats/asciidoc/pandoc/asciidoc.template
- Ours: src/resources/formats/asciidoc/pandoc/template.asciidoc

#### typst

Typst keeps Pandoc's `template.typst` partial under its original name alongside the renamed `typst.template`. See `llm-docs/pandoc-quarto-typst-templates.md` for Quarto's partials.

The files labelled "Pandoc's" are reference copies used to review upstream changes. Rendering uses the corresponding "Ours" files and their partials, such as `tables.tex` and `toc.tex`.

- Regenerate reference copies from upstream with `writePandocTemplates`; apply rendering changes to Quarto's templates and partials.
- Keep reference copies identical to upstream, including any upstream typos. Manual edits are overwritten on regeneration. Fix upstream bugs in Quarto's templates.
- List the directory without filtering by extension when checking the files: `*.latex` excludes `latex.common`, which ends in `.common`.

## Manual steps

- [ ] Update schemas by inspecting [their changelog](https://github.com/jgm/pandoc/blob/main/changelog.md) for new commands, deprecation removals, etc
Expand Down
4 changes: 3 additions & 1 deletion dev-docs/upgrade-dependencies.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Change version numbers in `./configuration` to correspond to new versions.

Update hardcoded version strings in `src/command/check/check.ts` (the `versionConstraints` array in `checkVersions`) so that they match the new versions in `configuration`. The `configuration` file warns about this in a comment, and `tests/smoke/check/check-versions-no-mismatch.test.ts` fails until they match.
Update hardcoded version strings in `src/command/check/check.ts` (the `versionConstraints` array in `checkVersions`) so that they match the new versions in `configuration`. The `configuration` file warns about this in a comment, and `tests/smoke/check/check-versions-no-mismatch.test.ts` fails until they match. The constraint tracks the bundled version exactly, not a minimum floor.

For Pandoc, follow [update-pandoc-checklist.md](update-pandoc-checklist.md) for template updates and filename conventions, schema and Lua type checks, and CI smoke tests using `QUARTO_PANDOC` before S3 archival.

## Verify installer signing & notarization before merging (bundled binaries)

Expand Down
19 changes: 10 additions & 9 deletions llm-docs/localization-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ key_files:
- src/resources/filters/modules/authors.lua
- src/resources/filters/modules/callouts.lua
- src/resources/filters/layout/meta.lua
- src/resources/formats/html/pandoc/html.template
- src/resources/formats/html/pandoc/template.html
- src/resources/formats/html/pandoc/toc.html
- src/resources/formats/html/pandoc/title-block.html
- src/resources/formats/html/templates/title-metadata.html
- src/resources/formats/pdf/pandoc/latex.template
- src/resources/formats/pdf/pandoc/babel-lang.tex
- src/resources/formats/pdf/pandoc/toc.tex
- src/resources/formats/beamer/pandoc/beamer.template
- src/resources/formats/typst/pandoc/typst.template
- src/resources/formats/beamer/pandoc/toc.tex
- src/resources/formats/typst/pandoc/quarto/typst-template.typ
- src/resources/formats/typst/pandoc/quarto/typst-show.typ
- src/resources/extension-subtrees/orange-book/_extensions/orange-book/typst-show.typ
Expand Down Expand Up @@ -151,12 +150,14 @@ These bypass both Pandoc metadata and Lua filters. The string lands directly in

`quarto.*` is an internal namespace. The user-facing override path for localized strings is the top-level `language:` YAML key (resolved by `formatLanguage`, already merged into `options.format.language` before the builder runs). The schema does not advertise `variables.quarto.*` as a user option, but the merge in `generateDefaults` honors a user-set value on collision: it deep-merges via `mergeConfigs` (`src/core/config.ts`) so user-supplied keys win at any nesting depth while all other localized values remain available. For example, a user setting `variables.quarto.language.crossref-ch-prefix: Bouquin` overrides only that one leaf — `$quarto.language.toc-title-document$` still resolves to the localized fallback. (Same helper is used in `src/core/language.ts:formatLanguage` to merge user-supplied `language:` onto `_language.yml` defaults.) A non-object `variables.quarto` (string, number, array) is ignored defensively. New contributors to this file should design around the `language:` path, not around the escape hatch.

From any Pandoc template — built-in (`html.template`, `latex.template`, `typst-template.typ`), extension partial, or custom user template — every localized key is then accessible as:
From any Pandoc template — built-in (`template.html`, `template.tex`, `typst-template.typ`), extension partial, or custom user template — every localized key is then accessible as:

```pandoc
$quarto.language.<key>$
```

> **Naming note**: Citations below refer to Quarto's rendering templates: `template.html` (HTML), `template.tex` (LaTeX/PDF and Beamer), and `quarto/typst-template.typ` (Typst). See `dev-docs/update-pandoc-checklist.md` for the corresponding Pandoc reference copies.

For example, `$quarto.language.crossref-ch-prefix$` resolves to `Chapitre` when `lang: fr` is set. Hyphens within the leaf segment are valid Pandoc template-variable syntax (manual: *"Variable names can include letters, numbers, underscores, hyphens, and periods"*).

This is the channel of choice for new template consumers because:
Expand All @@ -173,9 +174,9 @@ It does **not** replace 2a — Lua filters still need `param("key")` because Pan

Localization paths used:

- **Document `lang` attribute**: `_language.yml` lookup not involved. `lang:` flows as Pandoc-native metadata, template renders `<html lang="$lang$" xml:lang="$lang$">` (`html.template:2`).
- **TOC title**: `$toc-title$` resolved via channel 2b. Used in `html.template:60`, `toc.html:3`.
- **Abstract title**: `$abstract-title$` resolved via 2b. Used in `html.template:51`, `title-block.html:15`.
- **Document `lang` attribute**: `_language.yml` lookup not involved. `lang:` flows as Pandoc-native metadata, template renders `<html$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$>` (`template.html:2`).
- **TOC title**: `$toc-title$` resolved via channel 2b. Used in `toc.html:3`.
- **Abstract title**: `$abstract-title$` resolved via 2b. Used in `title-block.html:15`.
- **Title block labels** (`Authors`, `Affiliations`, `Published`, `Modified`, `Doi`, `Abstract`, `Keywords`): `$labels.*$` written into meta by `modules/authors.lua:854-913` (`computeLabels`). Templates: `title-metadata.html:3,4,32,43,52,61,74,83`, `manuscript/title-metadata.html:6,7,37,48,57,66,83,92`.
- **Crossref text** (`Figure 1.1`, `Table 2.1`): assembled in Lua by `crossref/format.lua` using `title()` / `refPrefix()` which call `param("crossref-<type>-title"/"-prefix")`. Written as inline text directly into the AST. By the time Pandoc renders HTML, the localized prefix is already document content.
- **Callout titles** (`Tip`, `Note`, etc.): `modules/callouts.lua:15,185` reads `param("callout-<type>-title", default)`, writes into the callout node.
Expand All @@ -191,7 +192,7 @@ Three localization paths layered:

Other Lua filters use `metaInjectLatex` for non-language LaTeX customization (`crossref/custom.lua:78`, `layout/meta.lua`, `quarto-post/landscape.lua`, etc. — they inject packages or styling, not localized strings).

3. **Pandoc template `$var$`** — `pdf/pandoc/toc.tex:3` and `pdf/pandoc/latex.template:93-94` use `$toc-title$` to set `\contentsname`. Beamer templates (`beamer/pandoc/beamer.template:146-151`, `beamer/pandoc/toc.tex:3`) likewise.
3. **Pandoc template `$var$`** — `pdf/pandoc/toc.tex:2-3` uses `$toc-title$` to set `\contentsname`. Beamer's `beamer/pandoc/toc.tex:2-3` does the same.

PDF-side TS code does not read `format.language` directly except `src/format/pdf/format-pdf.ts:242` which registers `"babel-lang"` as a Quarto partial.

Expand Down
Loading
Loading