Publish source: file brand fonts beside the theme CSS (bd-ve916wr8) - #668
Merged
Conversation
Contributor
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
…Ls mis-based
Plan skeleton + committed repro fixtures (website and single-doc) with
evidence in NOTES.md. Confirms the strand at HEAD and adds two findings:
single-doc renders are equally broken (styles.css lives in {stem}_files/),
and the persistent SASS cache key omits the font URL prefix, so pages
alias onto whichever compiled first.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CoQm2W4rtvPQNDtkYKdb6D
Records the design decisions agreed with the user (artifact placement, collision-is-an-error, leading-slash semantics, format() hint, warn on unknown file-entry keys, conflict expectation with bd-5fseopxy, merge-time comment on bd-r1y48cx0) and expands the phases into a TDD checklist. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoQm2W4rtvPQNDtkYKdb6D
Local fonts declared in _brand.yml (`source: file`) were never copied into the output, and the @font-face URL was document-relative while the compiled theme CSS lives in site_libs/quarto/ (website) or {stem}_files/ (single doc) — so every local brand font 404'd. The per-document prefix also split a site into one theme bundle per page depth on a cold SASS cache, and aliased pages onto whichever compiled first on a warm one, because the cache key never included it. Fonts are now published as project-scope artifacts in a `fonts/` directory beside whichever theme CSS references them (`site_libs/quarto/fonts/`, `{stem}_files/fonts/`, `…/revealjs/fonts/`), and the SCSS layer emits the constant `url('fonts/<basename>')` with a `format()` hint from the extension. The URL no longer depends on the document, so one compiled theme serves every page and the cache key is complete by construction. Artifacts flush through both the native sink and the preview VFS, so the same mechanism covers `q2 preview`. - quarto-brand: `published_font_name`; `BrandFontFileEntry::Explicit` is a struct that tolerates unsettled per-file keys (`format:`, `display:`) and exposes them; `ResolvedBrand` remembers its file. - quarto-sass: `brand_to_layers(&Brand)` drops the font-path prefix; `ThemeContext::with_brand` drops `brand_dir`; `resolve_brand_layers` is gone (reveal resolves the brand and publishes fonts itself). - quarto-core: new `brand_fonts` module (publish, resolve `/` as project root, dedupe identical bytes); `ArtifactMergeConflict` carries the producers' `source` metadata and font clashes map to Q-14-10 from both the serial tail and the parallel Pass-2 reducer. - Diagnostics: Q-14-9 (font file missing, warn + continue), Q-14-10 (same name, different bytes — hard error naming both sources), Q-14-11 (unsupported key on a file entry, warn + ignore), each with its docs page and sidebar entry. - Tests: 12 end-to-end cases through render_to_file / ProjectPipeline (website depths, single doc, reveal, rooted paths, brand subdir, light/dark, dedupe, both collision shapes, both warnings), plus quarto-sass / quarto-brand unit coverage. - Docs: "Local font files" section in the brand guide; inventory row in the path-resolution contract. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoQm2W4rtvPQNDtkYKdb6D
…bering Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoQm2W4rtvPQNDtkYKdb6D
cscheid
force-pushed
the
feature/bd-ve916wr8-brand-file-fonts
branch
from
September 9, 2026 19:30
1f91465 to
b6b1e94
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes bd-ve916wr8.
Problem
Local fonts declared in
_brand.yml(source: file) were never copied into the output, and the@font-faceURL was document-relative while the compiled theme CSS lives insite_libs/quarto/(website) or{stem}_files/(single doc). Every local brand font 404'd. The per-document prefix also split a site into one theme bundle per page depth on a cold SASS cache, and aliased pages onto whichever compiled first on a warm one, because the cache key never included it. Evidence and repro fixtures:claude-notes/plans/brand-file-fonts-website-investigation/NOTES.md.Fix
Fonts are published as project-scope artifacts in a
fonts/directory beside whichever theme CSS references them (site_libs/quarto/fonts/,{stem}_files/fonts/,…/revealjs/fonts/), and the SCSS layer emits the constanturl('fonts/<basename>') format('woff2'). The URL no longer depends on the document, so one compiled theme serves every page and the cache key is complete by construction. Artifacts flush through both the native sink and the preview VFS, so the same mechanism coversq2 preview.published_font_name;BrandFontFileEntry::Explicitbecomes a struct that tolerates unsettled per-file keys (format:,display:) and exposes them;ResolvedBrandremembers its file.brand_to_layers(&Brand)drops the font-path prefix;ThemeContext::with_branddropsbrand_dir;resolve_brand_layersis gone (reveal resolves the brand and publishes fonts itself).brand_fontsmodule (publish, leading/= project root per the path contract, dedupe identical bytes).ArtifactMergeConflictcarries the producers'sourcemetadata, and font clashes map toQ-14-10from both the serial tail and the parallel Pass-2 reducer.Q-14-9font file missing (warn, continue),Q-14-10same name / different bytes (hard error naming both sources),Q-14-11unsupported key on a file entry (warn, ignore). Numbered pastQ-14-6/7(Theme compile failures are structured hard errors, not silent DEFAULT_CSS (bd-jsvetdea) #661) andQ-14-8(Support brand.yml font weight ranges; make invalid weights a Q-14-8 error (bd-5fseopxy) #663).path-resolution-model.md.Design decisions (fonts as artifacts, collision is an error,
/= project root, warn on unknown keys) are recorded inclaude-notes/plans/2026-09-08-brand-file-fonts-website.md.Tests
crates/quarto-core/tests/integration/brand_fonts.rsthroughrender_to_file/ProjectPipeline: website at two depths (one bundle), nested-only page, rooted path, brand in a subdirectory, light/dark distinct fonts, identical-bytes dedupe, both collision shapes, missing file, unknown key, single doc, reveal. All confirmed failing at HEAD first.font_files_test.rs), quarto-sass (brand_layer_test.rs), quarto-core (brand_fontsmodule).cargo nextest run --workspace13,763 passed; clippy-D warningsclean on the touched crates;cargo xtask verify --skip-hub-testsgreen including the WASM leg (hub-client vitest is red onmainfrom the Node 26localStorageissue, bd-lh30hlvd).End-to-end
One bundle
site_libs/quarto/quarto-theme-<fp>.csslinked byindex.htmlandposts/one.html, containingand
site_libs/quarto/fonts/EBGaramond-VariableFont_wght.woff2byte-identical to the source. The single-doc fixture publishesdoc_files/fonts/…next todoc_files/styles.css.Coordination
Expected textual conflict with #663 (bd-5fseopxy) in
file_font_face_block,types.rs, and the theme stage; whichever lands second rebases. On merge: comment on bd-r1y48cx0 (css:files never copied) pointing at this mechanism.🤖 Generated with Claude Code
https://claude.ai/code/session_01CoQm2W4rtvPQNDtkYKdb6D