Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
a5af925
claude: Add Typst book support using orange-book template
gordonwoodhull Dec 25, 2025
f601503
claude: Remove Typst unnumbered heading workaround, use Pandoc native…
gordonwoodhull Dec 25, 2025
90ea8b8
claude: Add cross-reference tests for Typst books
gordonwoodhull Dec 25, 2025
27589be
claude: Replace static figure with R plot(cars) in Typst book test
gordonwoodhull Dec 25, 2025
2fef34c
claude: Add *_files/ to Typst book test .gitignore
gordonwoodhull Dec 25, 2025
1fac0f7
claude: Add notebook embedding test to Typst book
gordonwoodhull Dec 25, 2025
f0a3873
claude: Add bibliography and citations test for Typst books
gordonwoodhull Dec 25, 2025
fc0ff56
claude: Add book parts and appendices support for Typst
gordonwoodhull Dec 25, 2025
dbd438c
claude: Add sub-figure support with chapter-based numbering for Typst…
gordonwoodhull Dec 25, 2025
e579d4d
claude: Add callout support with chapter-based numbering for Typst books
gordonwoodhull Dec 25, 2025
ab2ca3f
claude: Fix duplicate Appendices entries in Typst book TOC
gordonwoodhull Dec 25, 2025
002688d
claude: Fix appendix numbering for callouts and subfigures in Typst b…
gordonwoodhull Dec 25, 2025
6456025
claude: Add dynamic counter reset for Typst book chapter boundaries
gordonwoodhull Dec 25, 2025
cb75f81
claude: Add custom crossref type test for Typst book counter reset
gordonwoodhull Dec 25, 2025
d3260fc
claude: Add Appendix B test for multi-appendix numbering in Typst books
gordonwoodhull Dec 25, 2025
f168e20
claude: Add equation cross-references with chapter-based numbering fo…
gordonwoodhull Dec 25, 2025
0f102f3
claude: Add theorem cross-references with chapter-based numbering for…
gordonwoodhull Dec 25, 2025
1c31342
claude: Add listing cross-reference tests for Typst books
gordonwoodhull Dec 25, 2025
70208cc
gitignore
gordonwoodhull Dec 25, 2025
d19183c
claude: Refactor Typst numbering into separate template files for boo…
gordonwoodhull Dec 25, 2025
0386dda
claude: Add brand color support for Typst books main-color
gordonwoodhull Dec 25, 2025
422b18b
claude: Add brand logo support for Typst books
gordonwoodhull Dec 25, 2025
c9e7eea
claude: Add toc-depth mapping and use local orange-book 0.7.0
gordonwoodhull Dec 25, 2025
919ebd3
claude: Add lof/lot infrastructure for Typst books (pending orange-bo…
gordonwoodhull Dec 25, 2025
c864892
claude: Fix brand-color variable ordering in Typst output
gordonwoodhull Jan 6, 2026
159e800
claude: Add visual demos for citecolor and filecolor in template test
gordonwoodhull Jan 6, 2026
e45cbfb
claude: Refactor Typst book support to use extension-provided partials
gordonwoodhull Jan 24, 2026
45db25f
claude: Expose file_metadata_filter and combineFilters to extensions
gordonwoodhull Jan 24, 2026
90b3855
claude: Expose quarto.doc.language for extension access to localization
gordonwoodhull Jan 24, 2026
0d82a10
claude: Expose crossref.categories to extensions
gordonwoodhull Jan 24, 2026
e297c75
claude: Extend smoke-all test infra for Typst book projects
gordonwoodhull Jan 24, 2026
5e91eeb
claude: Move Typst book support to orange-book extension
gordonwoodhull Jan 24, 2026
f54858b
claude: Refactor schema to reuse filter-entry-point enum
gordonwoodhull Jan 7, 2026
b559d8e
claude: Aggregate errors in ensurePdfRegexMatches for better debugging
gordonwoodhull Jan 9, 2026
b2f7663
claude: Extend smoke-all test infra for Typst book projects
gordonwoodhull Jan 9, 2026
6f152a3
claude: orange-book tests - Replace hardcoded section numbers with cr…
gordonwoodhull Jan 9, 2026
b98d6c9
claude: orange-book extension - Add page.typ to omit logo from page b…
gordonwoodhull Jan 9, 2026
8ed977e
claude: Add LuaDoc documentation for new extension APIs
gordonwoodhull Jan 24, 2026
84c125d
claude: Replace ctheorems with theorion for Typst theorem environments
gordonwoodhull Jan 25, 2026
3ed55c4
claude: Add theorem-appearance option for configurable Typst theorem …
gordonwoodhull Jan 25, 2026
9141a57
claude: Add theorion and fontawesome to typst-gather packages
gordonwoodhull Jan 25, 2026
301f353
claude: Add Typst preview packages for offline builds
gordonwoodhull Jan 25, 2026
d1cf234
claude: Add changelog entry for theorem-appearance option
gordonwoodhull Jan 25, 2026
d4fa104
claude: Add bibliography aggregation tests to orange-book
gordonwoodhull Jan 25, 2026
a3e9060
claude: Enable citeproc and add inline citation tests for orange-book
gordonwoodhull Jan 25, 2026
9e14b02
claude: Add references page for orange-book bibliography
gordonwoodhull Jan 25, 2026
9bf775d
claude: Skip standalone tests for orange-book chapter files
gordonwoodhull Jan 25, 2026
070289e
claude: Fix book output path detection for multi-file vs single-file …
gordonwoodhull Jan 25, 2026
8f85000
claude: Add .quarto to gitignore and remove tracked cache files
gordonwoodhull Jan 25, 2026
ceee6b8
claude: Configure orange-book extension for local 0.7.1 package
gordonwoodhull Jan 25, 2026
df366d0
claude: Gather orange-book 0.7.1 local package
gordonwoodhull Jan 25, 2026
dc3654e
claude: Fix listing centering in Typst book templates
gordonwoodhull Jan 25, 2026
2754cee
claude: Add minimal test for code listing alignment verification
gordonwoodhull Jan 25, 2026
9062ad5
claude: Add pdf-tag-tree.ts tool for debugging PDF structure
gordonwoodhull Jan 25, 2026
5fd7ff9
claude: Fix CI test failures from typst-books changes
gordonwoodhull Jan 25, 2026
0904395
claude: Remove quarto- prefix from Typst numbering variables
gordonwoodhull Jan 25, 2026
7012761
claude: Add orange-book subtree extension configuration
gordonwoodhull Jan 25, 2026
7db758c
Squashed 'src/resources/extension-subtrees/orange-book/' content from…
gordonwoodhull Jan 25, 2026
dbd0567
Merge commit '7db758c6fc53d8d9a723dc31c5fee13a39cc6cd6' as 'src/resou…
gordonwoodhull Jan 25, 2026
601eb9d
claude: Auto-load orange-book extension for typst book projects
gordonwoodhull Jan 25, 2026
3070af4
claude: Update inspect-extensions test for new bundled extension
gordonwoodhull Jan 26, 2026
585882d
claude: Update typst-listings tests for new alignment approach
gordonwoodhull Jan 26, 2026
2f14cf9
claude: Fix user filter scriptFile handling in emulatedfilter.lua
gordonwoodhull Jan 26, 2026
15018cc
claude: Fix skip syntax for orange-book chapter tests
gordonwoodhull Jan 26, 2026
059b457
claude: Read full version from version.txt in packaging config
gordonwoodhull Jan 26, 2026
cd960c7
Revert "claude: Read full version from version.txt in packaging config"
gordonwoodhull Jan 26, 2026
27d2d21
claude: Pass explicit version to prepare-dist in CI workflows
gordonwoodhull Jan 26, 2026
bd29e44
artifacts
gordonwoodhull Jan 26, 2026
a739143
claude: Add changelog entry for Typst book projects
gordonwoodhull Jan 26, 2026
c145d90
claude: Consolidate listing alignment to show rule, add position tests
gordonwoodhull Jan 26, 2026
97ce3d1
claude: Update caption formatting test for new alignment approach
gordonwoodhull Jan 26, 2026
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
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