Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
e013293
claude: Add Typst book support using orange-book template
gordonwoodhull Dec 25, 2025
9a39204
claude: Remove Typst unnumbered heading workaround, use Pandoc native…
gordonwoodhull Dec 25, 2025
cb74dbb
claude: Add cross-reference tests for Typst books
gordonwoodhull Dec 25, 2025
d93cd28
claude: Replace static figure with R plot(cars) in Typst book test
gordonwoodhull Dec 25, 2025
3b03325
claude: Add *_files/ to Typst book test .gitignore
gordonwoodhull Dec 25, 2025
af84877
claude: Add notebook embedding test to Typst book
gordonwoodhull Dec 25, 2025
ba70f55
claude: Add bibliography and citations test for Typst books
gordonwoodhull Dec 25, 2025
2c20411
claude: Add book parts and appendices support for Typst
gordonwoodhull Dec 25, 2025
5882459
claude: Add sub-figure support with chapter-based numbering for Typst…
gordonwoodhull Dec 25, 2025
1e53b2a
claude: Add callout support with chapter-based numbering for Typst books
gordonwoodhull Dec 25, 2025
a8310eb
claude: Fix duplicate Appendices entries in Typst book TOC
gordonwoodhull Dec 25, 2025
c1c9f69
claude: Fix appendix numbering for callouts and subfigures in Typst b…
gordonwoodhull Dec 25, 2025
c5d8388
claude: Add dynamic counter reset for Typst book chapter boundaries
gordonwoodhull Dec 25, 2025
3f7912c
claude: Add custom crossref type test for Typst book counter reset
gordonwoodhull Dec 25, 2025
256c90d
claude: Add Appendix B test for multi-appendix numbering in Typst books
gordonwoodhull Dec 25, 2025
58474b0
claude: Add equation cross-references with chapter-based numbering fo…
gordonwoodhull Dec 25, 2025
d003f90
claude: Add theorem cross-references with chapter-based numbering for…
gordonwoodhull Dec 25, 2025
f8215b4
claude: Add listing cross-reference tests for Typst books
gordonwoodhull Dec 25, 2025
69f197c
gitignore
gordonwoodhull Dec 25, 2025
51eeaf6
claude: Refactor Typst numbering into separate template files for boo…
gordonwoodhull Dec 25, 2025
4501bc9
claude: Add brand color support for Typst books main-color
gordonwoodhull Dec 25, 2025
9f1fbd5
claude: Add brand logo support for Typst books
gordonwoodhull Dec 25, 2025
8ae737a
claude: Add toc-depth mapping and use local orange-book 0.7.0
gordonwoodhull Dec 25, 2025
ced8e15
claude: Add lof/lot infrastructure for Typst books (pending orange-bo…
gordonwoodhull Dec 25, 2025
bdb50ee
claude: Fix brand-color variable ordering in Typst output
gordonwoodhull Jan 6, 2026
8a04664
claude: Add visual demos for citecolor and filecolor in template test
gordonwoodhull Jan 6, 2026
a9ab8cd
claude: Refactor Typst book support to use extension-provided partials
gordonwoodhull Jan 24, 2026
22cbdd6
claude: Expose file_metadata_filter and combineFilters to extensions
gordonwoodhull Jan 24, 2026
82a4076
claude: Expose quarto.doc.language for extension access to localization
gordonwoodhull Jan 24, 2026
4701dd0
claude: Expose crossref.categories to extensions
gordonwoodhull Jan 24, 2026
6f46587
claude: Extend smoke-all test infra for Typst book projects
gordonwoodhull Jan 24, 2026
7b158a7
claude: Move Typst book support to orange-book extension
gordonwoodhull Jan 24, 2026
769b6d7
claude: Refactor schema to reuse filter-entry-point enum
gordonwoodhull Jan 7, 2026
c3ee9fd
claude: Aggregate errors in ensurePdfRegexMatches for better debugging
gordonwoodhull Jan 9, 2026
d400474
claude: Extend smoke-all test infra for Typst book projects
gordonwoodhull Jan 9, 2026
d7e9761
claude: orange-book tests - Replace hardcoded section numbers with cr…
gordonwoodhull Jan 9, 2026
855b0e0
claude: orange-book extension - Add page.typ to omit logo from page b…
gordonwoodhull Jan 9, 2026
a58ac74
claude: Add LuaDoc documentation for new extension APIs
gordonwoodhull Jan 24, 2026
4e30381
claude: Replace ctheorems with theorion for Typst theorem environments
gordonwoodhull Jan 25, 2026
b155d97
claude: Add theorem-appearance option for configurable Typst theorem …
gordonwoodhull Jan 25, 2026
59a741c
claude: Add theorion and fontawesome to typst-gather packages
gordonwoodhull Jan 25, 2026
054a212
claude: Add Typst preview packages for offline builds
gordonwoodhull Jan 25, 2026
d6a0ce3
claude: Add changelog entry for theorem-appearance option
gordonwoodhull Jan 25, 2026
bc8f1fa
claude: Add bibliography aggregation tests to orange-book
gordonwoodhull Jan 25, 2026
22227cd
claude: Enable citeproc and add inline citation tests for orange-book
gordonwoodhull Jan 25, 2026
506b5ff
claude: Add references page for orange-book bibliography
gordonwoodhull Jan 25, 2026
8882d25
claude: Skip standalone tests for orange-book chapter files
gordonwoodhull Jan 25, 2026
f8a8b5d
claude: Fix book output path detection for multi-file vs single-file …
gordonwoodhull Jan 25, 2026
f6aa43a
claude: Add .quarto to gitignore and remove tracked cache files
gordonwoodhull Jan 25, 2026
021ba46
claude: Configure orange-book extension for local 0.7.1 package
gordonwoodhull Jan 25, 2026
5f92fdf
claude: Gather orange-book 0.7.1 local package
gordonwoodhull Jan 25, 2026
4f4c479
claude: Fix listing centering in Typst book templates
gordonwoodhull Jan 25, 2026
da29258
claude: Add minimal test for code listing alignment verification
gordonwoodhull Jan 25, 2026
ba2fb29
claude: Add pdf-tag-tree.ts tool for debugging PDF structure
gordonwoodhull Jan 25, 2026
246331d
claude: Fix CI test failures from typst-books changes
gordonwoodhull Jan 25, 2026
f39dca5
claude: Remove quarto- prefix from Typst numbering variables
gordonwoodhull Jan 25, 2026
c4ee80f
claude: Add orange-book subtree extension configuration
gordonwoodhull Jan 25, 2026
8a27804
claude: Auto-load orange-book extension for typst book projects
gordonwoodhull Jan 25, 2026
4c4fc43
claude: Update inspect-extensions test for new bundled extension
gordonwoodhull Jan 26, 2026
df5c0c6
claude: Update typst-listings tests for new alignment approach
gordonwoodhull Jan 26, 2026
95ab7a1
claude: Fix user filter scriptFile handling in emulatedfilter.lua
gordonwoodhull Jan 26, 2026
868adfd
claude: Fix skip syntax for orange-book chapter tests
gordonwoodhull Jan 26, 2026
1d81269
claude: Read full version from version.txt in packaging config
gordonwoodhull Jan 26, 2026
a5e5cb0
Revert "claude: Read full version from version.txt in packaging config"
gordonwoodhull Jan 26, 2026
c1ce891
claude: Pass explicit version to prepare-dist in CI workflows
gordonwoodhull Jan 26, 2026
7a882e3
claude: Add changelog entry for Typst book projects
gordonwoodhull Jan 26, 2026
a7b5238
claude: Consolidate listing alignment to show rule, add position tests
gordonwoodhull Jan 26, 2026
2136a74
claude: Update caption formatting test for new alignment approach
gordonwoodhull Jan 26, 2026
fc4379c
claude: Include page number in PDF position assertion failures
gordonwoodhull Jan 27, 2026
cfddd75
claude: Fix duplicate error for ambiguous text in PDF assertions
gordonwoodhull Jan 27, 2026
b120cfe
claude: Avoid duplicate error output in PDF position assertions
gordonwoodhull Jan 27, 2026
3bae1fc
claude: Add margin layout support for callouts in Typst
gordonwoodhull Jan 27, 2026
a1f1f6a
claude: Fix --keep-outputs flag for book projects
gordonwoodhull Jan 27, 2026
cf821c6
claude: Improve pdf-tag-tree to search all pages and highlight matches
gordonwoodhull Jan 27, 2026
5a266b4
claude: Add granularity attribute to PDF text position assertions
gordonwoodhull Jan 27, 2026
cb51e21
claude: Add orange-book-margin test suite for Typst margin layouts
gordonwoodhull Jan 28, 2026
ee81b35
artifacts
gordonwoodhull Jan 28, 2026
8a3a1bb
Squashed 'src/resources/extension-subtrees/orange-book/' content from…
gordonwoodhull Jan 28, 2026
668a06f
Merge commit '8a3a1bb99e37575d9c1c7ed8e207754eaae3e3b7' as 'src/resou…
gordonwoodhull Jan 28, 2026
d59c991
claude: Add skip metadata to orange-book-margin chapter tests
gordonwoodhull Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/performance-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
pushd package/src

bundle_start=$(date +%s.%3N)
./quarto-bld prepare-dist
./quarto-bld prepare-dist --set-version $(cat ../../version.txt)
bundle_end=$(date +%s.%3N)
bundle_elapsed=$(printf '%.3f\n' $(echo "scale=3; $bundle_end - $bundle_start" | bc))

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-bundle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
shell: bash
run: |
pushd package/src
./quarto-bld prepare-dist
./quarto-bld prepare-dist --set-version $(cat ../../version.txt)
mv ../../src/quarto.ts ../../src/quarto1.ts
pushd ../pkg-working/bin
./quarto check
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ tools/sass-variable-explainer/_publish.yml

# generated by tests
tests/docs/callouts.pdf

# quarto cache directories (populated at render time)
.quarto
2 changes: 2 additions & 0 deletions news/changelog-1.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ All changes included in 1.9:
- Two-column layout now uses `set page(columns:)` instead of `columns()` function, fixing compatibility with landscape sections.
- Title block now properly spans both columns in multi-column layouts.
- ([#13870](https://github.com/quarto-dev/quarto-cli/issues/13870)): Add support for `alt` attribute on cross-referenced equations for improved accessibility. (author: @mcanouil)
- ([#13950](https://github.com/quarto-dev/quarto-cli/pull/13950)): Replace ctheorems with theorion package for theorem environments. Add `theorem-appearance` option to control styling: `simple` (default, classic LaTeX style), `fancy` (colored boxes with brand colors), `clouds` (rounded backgrounds), or `rainbow` (colored start border and colored title).
- ([#13954](https://github.com/quarto-dev/quarto-cli/issues/13954)): Add support for Typst book projects via format extensions. Quarto now bundles the `orange-book` extension which provides a textbook-style format with chapter numbering, cross-references, and professional styling. Book projects with `format: typst` automatically use this extension.

### `pdf`

Expand Down
5 changes: 0 additions & 5 deletions package/src/common/prepare-dist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,6 @@ export async function prepareDist(
inlineFilters(config);
info("");

// Appease the bundler testing by patching the bad version from `configuration`
if (config.version.split(".").length === 2) {
config.version = `${config.version}.1`;
}

// Write a version file to share
info(`Writing version: ${config.version}`);
Deno.writeTextFileSync(
Expand Down
7 changes: 6 additions & 1 deletion src/command/dev-call/pull-git-subtree/cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ const SUBTREES: SubtreeConfig[] = [
remoteUrl: "https://github.com/gordonwoodhull/quarto-julia-engine.git",
remoteBranch: "main",
},
// Add more subtrees here as needed
{
name: "orange-book",
prefix: "src/resources/extension-subtrees/orange-book",
remoteUrl: "https://github.com/gordonwoodhull/quarto-orange-book.git",
remoteBranch: "main",
},
];

async function findLastSplit(
Expand Down
4 changes: 4 additions & 0 deletions src/command/dev-call/typst-gather/typst-gather.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
destination = "src/resources/formats/typst/packages"
discover = ["src/resources/formats/typst/pandoc/quarto"]

[preview]
fontawesome = "0.5.0"
theorion = "0.4.1"
8 changes: 7 additions & 1 deletion src/command/render/output-typst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import {
safeRemoveSync,
} from "../../deno_ral/fs.ts";
import {
builtinSubtreeExtensions,
inputExtensionDirs,
readExtensions,
readSubtreeExtensions,
} from "../../extension/extension.ts";
import { projectScratchPath } from "../../project/project-scratch.ts";
import { resourcePath } from "../../core/resources.ts";
Expand Down Expand Up @@ -62,8 +64,12 @@ async function stageTypstPackages(

// 2. Add packages from extensions (can override built-in)
const extensionDirs = inputExtensionDirs(input, projectDir);
const subtreePath = builtinSubtreeExtensions();
for (const extDir of extensionDirs) {
const extensions = await readExtensions(extDir);
// Use readSubtreeExtensions for subtree directory, readExtensions for others
const extensions = extDir === subtreePath
? await readSubtreeExtensions(extDir)
: await readExtensions(extDir);
for (const ext of extensions) {
const packagesDir = join(ext.path, "typst/packages");
if (existsSync(packagesDir)) {
Expand Down
21 changes: 17 additions & 4 deletions src/command/render/render-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,24 @@ const readExtensionFormat = async (
extensionContext: ExtensionContext,
project?: ProjectContext,
) => {
// Determine effective extension - use default for certain project/format combinations
let effectiveExtension = formatDesc.extension;

// For book projects with typst format and no explicit extension,
// use orange-book as the default typst book template
if (
!effectiveExtension &&
formatDesc.baseFormat === "typst" &&
project?.config?.project?.[kProjectType] === "book"
) {
effectiveExtension = "orange-book";
}

// Read the format file and populate this
if (formatDesc.extension) {
if (effectiveExtension) {
// Find the yaml file
const extension = await extensionContext.extension(
formatDesc.extension,
effectiveExtension,
file,
project?.config,
project?.dir,
Expand All @@ -696,7 +709,7 @@ const readExtensionFormat = async (
(extensionFormat[fmtTarget] || extensionFormat[formatDesc.baseFormat] ||
{}) as Metadata;
extensionMetadata[kExtensionName] = extensionMetadata[kExtensionName] ||
formatDesc.extension;
effectiveExtension;

const formats = await resolveFormatsFromMetadata(
extensionMetadata,
Expand All @@ -707,7 +720,7 @@ const readExtensionFormat = async (
return formats;
} else {
throw new Error(
`No valid format ${formatDesc.baseFormat} is provided by the extension ${formatDesc.extension}`,
`No valid format ${formatDesc.baseFormat} is provided by the extension ${effectiveExtension}`,
);
}
} else {
Expand Down
26 changes: 22 additions & 4 deletions src/extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,9 @@ export function filterExtensions(

// Read git subtree extensions (pattern 3 only)
// Looks for top-level directories containing _extensions/ subdirectories
const readSubtreeExtensions = async (
export async function readSubtreeExtensions(
subtreeDir: string,
): Promise<Extension[]> => {
): Promise<Extension[]> {
const extensions: Extension[] = [];

const topLevelDirs = safeExistsSync(subtreeDir) &&
Expand All @@ -303,7 +303,7 @@ const readSubtreeExtensions = async (
}

return extensions;
};
}

// Loads all extensions for a given input
// (note this needs to be sure to return copies from
Expand Down Expand Up @@ -628,6 +628,24 @@ export function discoverExtensionPath(
return builtinExtensionDir;
}

// check for built-in subtree extensions (pattern: extension-subtrees/*/\_extensions/name)
const subtreePath = builtinSubtreeExtensions();
if (safeExistsSync(subtreePath)) {
for (const topLevelDir of Deno.readDirSync(subtreePath)) {
if (!topLevelDir.isDirectory) continue;
const subtreeExtDir = join(subtreePath, topLevelDir.name, kExtensionDir);
if (safeExistsSync(subtreeExtDir)) {
const subtreeExtensionDir = findExtensionDir(
subtreeExtDir,
extensionDirGlobs,
);
if (subtreeExtensionDir) {
return subtreeExtensionDir;
}
}
}
}

// Start in the source directory
const sourceDir = Deno.statSync(input).isDirectory ? input : dirname(input);
const sourceDirAbs = normalizePath(sourceDir);
Expand Down Expand Up @@ -661,7 +679,7 @@ function builtinExtensions() {
}

// Path for built-in subtree extensions
function builtinSubtreeExtensions() {
export function builtinSubtreeExtensions() {
return resourcePath("extension-subtrees");
}

Expand Down
15 changes: 15 additions & 0 deletions src/format/typst/format-typst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import { join } from "../../deno_ral/path.ts";

import { RenderServices } from "../../command/render/types.ts";
import { ProjectContext } from "../../project/types.ts";
import { BookExtension } from "../../project/types/book/book-shared.ts";
import {
kCiteproc,
kColumns,
Expand Down Expand Up @@ -38,6 +40,11 @@ import {
import { fillLogoPaths, resolveLogo } from "../../core/brand/brand.ts";
import { LogoLightDarkSpecifierPathOptional } from "../../resources/types/zod/schema-types.ts";

const typstBookExtension: BookExtension = {
selfContainedOutput: true,
// multiFile defaults to false (single-file book)
};

export function typstFormat(): Format {
return createFormat("Typst", "pdf", {
execute: {
Expand All @@ -51,6 +58,9 @@ export function typstFormat(): Format {
[kWrap]: "none",
[kCiteproc]: false,
},
extensions: {
book: typstBookExtension,
},
resolveFormat: typstResolveFormat,
formatExtras: async (
_input: string,
Expand All @@ -59,6 +69,8 @@ export function typstFormat(): Format {
format: Format,
_libDir: string,
_services: RenderServices,
_offset?: string,
_project?: ProjectContext,
): Promise<FormatExtras> => {
const pandoc: FormatPandoc = {};
const metadata: Metadata = {};
Expand Down Expand Up @@ -106,10 +118,13 @@ export function typstFormat(): Format {
}

// Provide a template and partials
// For Typst books, a book extension overrides these partials
const templateDir = formatResourcePath("typst", join("pandoc", "quarto"));

const templateContext = {
template: join(templateDir, "template.typ"),
partials: [
"numbering.typ",
"definitions.typ",
"typst-template.typ",
"page.typ",
Expand Down
12 changes: 12 additions & 0 deletions src/project/types/book/book.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
isEpubOutput,
isHtmlOutput,
isLatexOutput,
isTypstOutput,
} from "../../../config/format.ts";
import { PandocFlags } from "../../../config/types.ts";
import {
Expand Down Expand Up @@ -256,6 +257,17 @@ export const bookProjectType: ProjectType = {
},
},
);
} else if (isTypstOutput(format.pandoc)) {
// Typst book: use chapter divisions, disable Quarto TOC (orange-book generates its own)
extras = mergeConfigs(
extras,
{
pandoc: {
[kTopLevelDivision]: "chapter",
[kToc]: false,
},
},
);
}

// return
Expand Down
Loading
Loading