Skip to content

Config paths Phase 3: extension project fragments as virtual files; site-rooted spelling for rebased website assets (bd-0x1znhgb) - #959

Merged
cscheid merged 1 commit into
mainfrom
feature/bd-0x1znhgb-config-paths-phase-3
Oct 28, 2026
Merged

cscheid merged 1 commit into
mainfrom
feature/bd-0x1znhgb-config-paths-phase-3

Conversation

@cscheid

@cscheid cscheid commented Oct 28, 2026

Copy link
Copy Markdown
Member

Stacked on #958 (base branch feature/bd-7328beha-url-space-config-paths); retarget to main after #958 merges.

What was wrong

resolve_metadata_path re-derived a value's base directory from its source span. Two cases broke that: a value rebased by rebase_fragment_paths kept its _extension.yml span while its string was already project-root-relative, and an href: index.qmd in an extension's contributes.project fragment names a project page but was authored under _extensions/<ext>/. bd-74ktvzv7 patched both with a file-name check on _extension.yml — not shared by config_paths::declaring_dir or the glob provenance, and wrong for the manifest's contributes.metadata / contributes.formats values, which do name bundled files.

What this does

  • Site-rooted spelling (plan §4.4 option a). Rebased FRAGMENT_SITE_PATH_PATTERNS strings (website.favicon, navbar.logo, navbar.logo-href, sidebar.logo) are now /_extensions/<ext>/…: self-describing in URL space; every consumer already strips the /. Visible in get-config (documented in the extensions guide). A file outside the project keeps its OS-absolute form.
  • The project fragment is a virtual file. At config time the fragment's spans are re-keyed to config_paths::project_fragment_file_id (rekey_project_fragment), and the merge stage plus every config-source binder (config_sources::config_file_ids, register_config_source, bind_config_source, project_resources, compile_theme_css) register that id with the manifest's path and bytes. One rule, config_paths::file_base_dir(id, path, project_dir), gives the project root for a fragment id and the file's directory otherwise; declaring_dir, resolve_metadata_path and glob::provenance::BaseDirContext::base_dir_for all call it. Diagnostics still render into _extension.yml; the file-name check is gone; a fragment listing.contents / resources: glob now anchors at the project root too.

Design note

A per-value provenance wrapper (Generated { by: config-base, from: [invocation anchor] }) was the first cut and is what the strand asked for. It was rejected: the published quarto-error-reporting renders a location from start_offset() / length(), which are 0 for Generated, so three CLI tests lost their _extension.yml snippet. ConfigValue has ~216 struct-literal sites, so a new field was out. The virtual-file id keeps every span Original and needs no plumbing. The plan's Phase 3 handoff records this; file_base_dir is the one place to switch if the source-map crate gains a first-class base.

Tests

  • config_paths: fragment id resolves against the root, the manifest's own id against the extension dir; re-keying reaches every span and leaves other files alone.
  • navigation_href: fragment id → project-root-relative; a plain _extension.yml span → its own dir (the file-name rule is gone).
  • glob::provenance, custom_project_type (new spelling), metadata_path_resolution (existing fragment logo/favicon/href tests unchanged; new fragment resources: glob test).
  • cargo xtask verify --skip-hub-build green locally (WASM rebuilt first).

🤖 Generated with Claude Code

…-rooted spelling for rebased website assets (bd-0x1znhgb)

Two things `resolve_metadata_path` got wrong by re-deriving the base
directory from the source span: a value rebased by
`rebase_fragment_paths` kept its `_extension.yml` span while its string
was already project-root-relative, and an `href: index.qmd` in an
extension's `contributes.project` fragment names a project page but was
authored under `_extensions/<ext>/`. bd-74ktvzv7 patched both with a
file-name check on `_extension.yml`, which no other consumer shared and
which was wrong for the manifest's `contributes.metadata` /
`contributes.formats` values (those do name bundled files).

- Rebased `FRAGMENT_SITE_PATH_PATTERNS` strings (`website.favicon`,
  `navbar.logo`, `navbar.logo-href`, `sidebar.logo`) now carry the
  site-rooted spelling `/_extensions/<ext>/…` (plan §4.4 option a):
  self-describing in URL space, and every consumer already strips the
  `/`. A file outside the project keeps its OS-absolute form.
- The project fragment is a virtual file of its own: at config time its
  spans are re-keyed to `config_paths::project_fragment_file_id`
  (`rekey_project_fragment`), and the merge stage plus every
  config-source binder (`config_sources::config_file_ids`,
  `register_config_source`, `bind_config_source`, project_resources,
  compile_theme_css) register that id with the manifest's path and
  bytes. `config_paths::file_base_dir(id, path, project_dir)` is the
  one rule — project root for a fragment id, the file's directory
  otherwise — and `declaring_dir`, `resolve_metadata_path` and
  `glob::provenance::BaseDirContext::base_dir_for` all use it. Snippets
  still render into `_extension.yml`; the file-name check is gone.

A provenance wrapper on each value (`Generated` + invocation anchor)
was tried first and rejected: the published error-reporting crate
renders a location from `start_offset()`, which is 0 for `Generated`,
so every fragment-anchored diagnostic lost its snippet. The plan
records the trade-off.

Tests: config_paths (fragment id resolves against the root, the
manifest's own id against the extension dir; re-keying reaches every
span), navigation_href, glob provenance, custom_project_type (new
spelling), a new integration test for a fragment `resources:` glob.
Docs: extensions guide notes the merged spelling.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

✅ 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.

Base automatically changed from feature/bd-7328beha-url-space-config-paths to main October 28, 2026 22:47
@cscheid
cscheid merged commit adcc7ef into main Oct 28, 2026
5 checks passed
@cscheid
cscheid deleted the feature/bd-0x1znhgb-config-paths-phase-3 branch October 28, 2026 22:49
@cscheid
cscheid restored the feature/bd-0x1znhgb-config-paths-phase-3 branch October 28, 2026 22:50
@cscheid
cscheid deleted the feature/bd-0x1znhgb-config-paths-phase-3 branch October 28, 2026 22: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.

2 participants