Skip to content

fix(preview): re-resolve _brand.yml added/removed mid-preview#14609

Merged
cderv merged 3 commits into
mainfrom
wip/preview-brand-cache-red
Jun 22, 2026
Merged

fix(preview): re-resolve _brand.yml added/removed mid-preview#14609
cderv merged 3 commits into
mainfrom
wip/preview-brand-cache-red

Conversation

@cderv

@cderv cderv commented Jun 22, 2026

Copy link
Copy Markdown
Member

When quarto preview is running and a sibling _brand.yml is added or removed, the output ignores the change until the preview process is restarted.

Root Cause

projectResolveBrand (src/project/project-shared.ts) populated project.brandCache on first resolve and returned it unconditionally on all subsequent calls. During a long-lived preview session the project context persists across re-renders, so the cached brand state — "no brand" or "brand present" — is frozen from the first render. The render-request path (including RStudio's Render button) carries no change signal: the source .qmd is unchanged, and _brand.yml is not in the file watcher.

Fix

Guard the cache with a source-state token over the candidate brand file paths the resolver already consults — each path's existence, mtime, and size, joined into a string. The cache is reused only while that token matches; any add, remove, or content edit re-resolves. Mirrors the fullMarkdown mtime+size guard in the same function. Format-independent: both typst and HTML go through projectResolveBrand, so both are covered by construction.

Test Plan

Tested manually against tests/docs/manual/preview/brand-detection/ (T28–T32 from the preview test matrix):

  • T28: _brand.yml added mid single-file Typst preview → report.typ gains #show link: set text(fill: rgb("#bc1e22"), )
  • T29: _brand.yml removed mid single-file Typst preview → line disappears from report.typ
  • T30: HTML format — Bootstrap CSS hash changes; new CSS carries --bs-primary: #BC1E22
  • T31: Project with _quarto.yml — brand applies on add and reverts on remove (CSS hash ece4cb9dece4)
  • T32: Stable _brand.yml with repeated saves — CSS hash stays constant (cache hit, no spurious re-resolve)

Unit coverage in tests/unit/preview-brand-cache.test.ts.

Fixes #14593

cderv added 3 commits June 16, 2026 18:19
projectResolveBrand caches the project-level brand on first resolve and never
invalidates it. In a long-lived preview context a _brand.yml added or removed
mid-session is ignored until the process restarts. These tests drive the fix at
the resolve level (no preview server): single-file and project, add and remove.
preview-architecture.md covered the per-file fileInformationCache (fullMarkdown
guard, invalidateForFile) but never the caches that live directly on
ProjectContext. brandCache and outputNameIndex are write-once and survive every
re-render, reset only on a full context rebuild. The doc also conflated
project.brandCache with the per-file frontmatter brand field.

Records why #14593 needs a resolve-time filesystem guard rather than active
invalidation: the render-request path (RStudio Render button) re-renders an
unchanged .qmd while a sibling _brand.yml appears or disappears, so there is no
change event to invalidate on.
projectResolveBrand populated project.brandCache on first resolve and
early-returned it forever. During a long-lived preview the context persists
across re-renders, so a sibling _brand.yml added or removed mid-session was
ignored until the process restarted. The render-request path (RStudio Render
button) carries no change signal — the input .qmd is unchanged and the watcher
does not watch _brand.yml — so only a resolve-time filesystem check can notice.

Guard the cache with a source-state token over the candidate brand paths the
resolver already consults (existence + mtime + size), mirroring the fullMarkdown
mtime+size guard. The cache is reused only while that token matches; any add,
remove, or content edit re-resolves. Format-independent, so typst and HTML are
both covered by construction.
@posit-snyk-bot

posit-snyk-bot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@cderv cderv merged commit 839139a into main Jun 22, 2026
53 of 54 checks passed
@cderv cderv deleted the wip/preview-brand-cache-red branch June 22, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preview does not pick up an added or removed _brand.yml until restarted

2 participants