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
30 changes: 30 additions & 0 deletions .claude/rules/extension-subtrees.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
paths:
- src/resources/extension-subtrees/**
---

# Extension Subtrees

Files under `src/resources/extension-subtrees/<name>/` are git subtrees from external repos. **Do NOT edit directly here.**

Current subtrees (see [`src/command/dev-call/pull-git-subtree/cmd.ts`](../../src/command/dev-call/pull-git-subtree/cmd.ts) for the source of truth):

| Name | Upstream repo |
|---|---|
| `julia-engine` | `PumasAI/quarto-julia-engine` |
| `orange-book` | `quarto-ext/orange-book` |

## Workflow

1. Open a PR with the fix in the upstream repo
2. Wait for upstream merge
3. From quarto-cli, run:
```bash
quarto dev-call pull-git-subtree <name>
```
4. The command adds two commits (squash + merge) — **do not edit those commits**
5. **Do not rebase** a branch that contains the subtree-pull commits — they cannot be rebased cleanly. Merge to `main` without rebasing, or remove the two commits before rebasing and re-run the pull command.

## Reference

Full workflow: [`dev-docs/subtree-extensions.md`](../../dev-docs/subtree-extensions.md)
50 changes: 49 additions & 1 deletion dev-docs/subtree-extensions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Subtree extensions

Subtree extensions live in `src/resources/subtree-extensions`.
Subtree extensions live in `src/resources/extension-subtrees`.

Each is the complete git repository of a Quarto extension, e.g. the directory tree for the Julia engine looks like

Expand All @@ -14,6 +14,20 @@ src/resources/extension-subtrees/
...
```

The list of subtrees and their upstream repos lives in the `SUBTREES` table in [`src/command/dev-call/pull-git-subtree/cmd.ts`](../src/command/dev-call/pull-git-subtree/cmd.ts).

## Updating an extension

Fixes to extension files **must be authored upstream**, never edited directly inside `src/resources/extension-subtrees/<name>/`. The correct workflow:

1. Open a PR with the fix in the upstream repo (e.g. `quarto-ext/orange-book`, `PumasAI/quarto-julia-engine`)
2. Merge the PR upstream
3. From quarto-cli, run the pull command (see [Pulling subtree updates](#pulling-subtree-updates))

Editing directly inside the subtree prefix is wrong: the change will be overwritten the next time the subtree is pulled, and anyone who forked the upstream extension will not benefit from it.

## Pulling subtree updates

The command to add or update a subtree is

```
Expand All @@ -39,3 +53,37 @@ So you must either

- run the command when ready to merge to main, or
- remove the commits when rebasing, and run the `dev-call` command again

## Recovery: edits made in-tree by mistake

If a fix has already been committed directly inside the subtree prefix (wrong workflow), it needs to be re-authored upstream before resuming the normal flow. Two paths:

### Option A — re-author upstream manually (recommended)

Faster and more predictable, especially in repos with many commits where `git subtree split` walks the full history.

1. Clone the upstream repo locally (e.g. `git clone https://github.com/quarto-ext/orange-book.git`)
2. Create a feature branch from upstream `main`
3. Apply the same change at the upstream repo's path (the subtree's `_extensions/...` becomes the repo root)
4. Commit (preserve original author and message) and push to the upstream repo
5. Open a PR upstream and merge

### Option B — `git subtree push`

Extracts the prefix-scoped history into a synthetic branch and pushes it. Works but is slow on large repos (the split walks every commit) and untested in this codebase.

```
git fetch <upstream-url> <upstream-branch>
git subtree push --prefix=src/resources/extension-subtrees/<name> \
<upstream-url> <feature-branch>
```

Then open a PR upstream from `<feature-branch>`.

### After the upstream PR merges

Back in quarto-cli, on the branch holding the original in-tree commit:

1. Remove the in-tree edit from the local commit (amend or rebase out the lines under the subtree prefix) so `pull-git-subtree` does not conflict with itself
2. Run `quarto dev-call pull-git-subtree <name>` to bring the upstream change in via the normal two-commit pattern
3. Merge the branch to `main` without rebasing (the subtree-pull commits cannot be rebased — see [Pulling subtree updates](#pulling-subtree-updates))
6 changes: 3 additions & 3 deletions llm-docs/localization-architecture.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
main_commit: 4aa86e524
analyzed_date: 2026-05-20
main_commit: eca40cdab
analyzed_date: 2026-05-21
key_files:
- src/resources/language/_language.yml
- src/resources/language/_language-fr.yml
Expand Down Expand Up @@ -204,7 +204,7 @@ Localization paths:
2. **Pandoc template `$var$` via meta** — same channel as HTML.
- `$toc-title$` (resolved via 2b in `pandoc.ts:498`) used in `typst-show.typ:93-95` as `toc_title:`.
- `$labels.abstract$` (written by `authors.lua` `computeLabels`) used in `typst-show.typ:30` as `abstract-title:`.
For orange-book (`src/resources/extension-subtrees/orange-book/_extensions/orange-book/typst-show.typ`): as of this writing the template still uses the legacy channel-2b form `$if(crossref.lof-title)$$crossref.lof-title$$else$$crossref-lof-title$$endif$` (and similarly for `lot-title`) to set `list-of-figure-title` and `list-of-table-title` on `book.with(...)`. The fallback `$crossref-lof-title$` resolves against `format.metadata` (channel 2b), so on writers like `+yaml_metadata_block` it can leak into the rendered markdown YAML header. There is no `supplement-chapter` argument wired today. Migration of orange-book's `typst-show.typ` to the `$quarto.language.*$` form (channel 2d), including adding `supplement-chapter`, is tracked at GitHub #14524 — once that lands the leakage path disappears.
For orange-book (`src/resources/extension-subtrees/orange-book/_extensions/orange-book/typst-show.typ`): the template uses the channel-2d form `$quarto.language.crossref-lof-title$` / `$quarto.language.crossref-lot-title$` / `$quarto.language.crossref-ch-prefix$` for `list-of-figure-title`, `list-of-table-title`, and `supplement-chapter` on `book.with(...)`. The `lof` and `lot` pipes use nested `$if(...)$` guards so pre-#14530 Quarto omits the argument entirely and `book()`'s built-in defaults apply. User-override path via the `crossref:` block (`$crossref.lof-title$` / `$crossref.lot-title$`) is preserved as the first cascade branch. Migration shipped via #14525 and [quarto-ext/orange-book#4](https://github.com/quarto-ext/orange-book/pull/4).

3. **Lua-injected supplements for refs** — `crossref/refs.lua:89-91` wraps every `@fig-foo`-style reference into `#ref(<label>, supplement: [<prefix>])` raw Typst. The supplement string comes from `param("crossref-<type>-prefix")` via `refPrefix()` in `crossref/format.lua:68`. This overrides Typst's native ref supplement so the language matches Quarto's localization.

Expand Down
1 change: 1 addition & 0 deletions news/changelog-1.10.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ All changes included in 1.10:
- ([#14261](https://github.com/quarto-dev/quarto-cli/issues/14261)): Fix theorem/example block titles containing inline code producing invalid Typst markup when syntax highlighting is applied.
- ([#14460](https://github.com/quarto-dev/quarto-cli/issues/14460)): Fix CSS `border` and `border-color` declarations losing tokens that precede an `rgb()`/`rgba()` color (e.g. `border: 0px solid rgb(255, 0, 0)` rendering as a 2.25pt border instead of being suppressed). Also fixes: `var(--brand-NAME)` references crashing the Typst CSS translator when `NAME` contained digits (e.g. `--brand-red-50`); a crash when an `rgba()` alpha is unparseable; the `dvmin` length unit being silently rejected (a stray space in the unit table); CSS keywords like `BOLD` not matching as `bold` (CSS keywords are case-insensitive); invalid hex colors like `#fffff` being silently accepted as 2-component colors.
- ([#14511](https://github.com/quarto-dev/quarto-cli/issues/14511)): Fix brand fonts downloaded for a Typst book project not being passed to `typst compile`, causing `unknown font family` warnings and fallback to Libertinus Serif.
- ([#14524](https://github.com/quarto-dev/quarto-cli/issues/14524), [quarto-ext/orange-book#4](https://github.com/quarto-ext/orange-book/pull/4)): Fix orange-book Typst book running header not honoring `lang:` — chapter heading band stayed `Chapter N.` instead of the locale's word (e.g. `Chapitre N.` for `lang: fr`). Also fixes the orange-book `list-of-figure-title` / `list-of-table-title` template pipes which were silently rendering as empty strings. Consumes the `$quarto.language.*$` template-variable namespace from [#14530](https://github.com/quarto-dev/quarto-cli/pull/14530).

### `revealjs`

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
title: Typst Orange Book Format
author: Quarto
version: 0.1.0
version: 0.2.0
quarto-required: ">=1.9.17"
contributes:
formats:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,25 @@ $if(toc-depth)$
outline-depth: $toc-depth$,
$endif$
$if(lof)$
list-of-figure-title: "$if(crossref.lof-title)$$crossref.lof-title$$else$$crossref-lof-title$$endif$",
$if(crossref.lof-title)$
list-of-figure-title: "$crossref.lof-title$",
$else$
$if(quarto.language.crossref-lof-title)$
list-of-figure-title: "$quarto.language.crossref-lof-title$",
$endif$
$endif$
$endif$
$if(lot)$
list-of-table-title: "$if(crossref.lot-title)$$crossref.lot-title$$else$$crossref-lot-title$$endif$",
$if(crossref.lot-title)$
list-of-table-title: "$crossref.lot-title$",
$else$
$if(quarto.language.crossref-lot-title)$
list-of-table-title: "$quarto.language.crossref-lot-title$",
$endif$
$endif$
$endif$
$if(quarto.language.crossref-ch-prefix)$
supplement-chapter: "$quarto.language.crossref-ch-prefix$",
$endif$
$if(margin-geometry)$
padded-heading-number: false,
Expand Down
2 changes: 1 addition & 1 deletion src/resources/filters/common/meta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function metaInjectHtml(meta, func)
end


function readMetaOptions(meta)
function readMetaOptions(meta)
local options = {}
for key,value in pairs(meta) do
if type(value) == "table" and value.clone ~= nil then
Expand Down
5 changes: 5 additions & 0 deletions tests/docs/smoke-all/typst/orange-book-lang/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/.quarto/
/_book/
/index.typ
**/*.quarto_ipynb
*_files/
17 changes: 17 additions & 0 deletions tests/docs/smoke-all/typst/orange-book-lang/_quarto.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
project:
type: book

book:
title: "Livre Test"
author: "Auteur Test"
chapters:
- index.qmd
- chapter1.qmd

lang: fr

format:
typst:
keep-typ: true
lof: true
lot: true
3 changes: 3 additions & 0 deletions tests/docs/smoke-all/typst/orange-book-lang/chapter1.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Premier chapitre

Voici le premier chapitre de ce livre de test.
16 changes: 16 additions & 0 deletions tests/docs/smoke-all/typst/orange-book-lang/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
keep-typ: true
_quarto:
render-project: true
tests:
typst:
ensureTypstFileRegexMatches:
-
- 'supplement-chapter: "Chapitre"'
- 'list-of-figure-title: "Liste des Figures"'
- 'list-of-table-title: "Liste des Tables"'
---

# Préface {.unnumbered}

Préface du livre de test.
Loading