WORK-260
ID:WORK-260Status:ready

Expand rune (resolver, extraction, level= demotion, canonical-link affordance)

The expand rune inlines a registered entity's content at the point of reference. Resolves the entity in the registry (populated for plan content by WORK-251), reads its sourceFile, extracts the entity's top-level rune subtree, and substitutes it into the host page. Sets data-outline-scope on its wrapper so the WORK-259 walkers isolate the embed's headings from the host TOC and namespace their IDs. Optional level= demotion suppresses the outline-scope attribute and merges the embed into the host outline.

The canonical-link affordance composes with the xref resolver from WORK-253: when the embedded entity has a canonical URL (via sourceUrl or pattern resolution), expand renders a "view canonical" link.

Priority:mediumComplexity:complexMilestone:v0.15.0Source:SPEC-066
claude/modal-drawer-pattern-a1Wgb View source

Criteria completion

Criteria completion: 0 of 15 (0%) checked; tracking started on May 23, no incremental history yet0%25%50%75%100%May 23Jun 15

Tracking started May 23 — check back for trends.

Branches 2
claude/modal-drawer-pattern-a1Wgb current ready
main doneclaude/v0.15.0 done
History 1
  1. c15804e
    Created (ready)by bjornolofandersson

Acceptance Criteria

  • {% expand "ID" /%} resolves the entity via the EntityRegistry, reads its sourceFile, and inlines its top-level rune subtree
  • Unresolved IDs (no entity in the registry) fail with a build error naming the ID and the source file
  • Entities without a sourceFile (cannot be expanded) fail with a clear build error
  • sourceFile is read with the same sandbox rules as snippet (SPEC-062); traversal escape rejected
  • Source-file parsing is cached per build (one parse per file, regardless of how many pages expand it)
  • Expand wrapper carries data-outline-scope="{entityId}" (e.g., data-outline-scope="SPEC-023") when level= is unset
  • When level= is set, data-outline-scope is not emitted; the embed participates in the host outline as authored sub-content
  • When level= is set, embedded headings are demoted by N - 1 levels; clamping at H6 with a build warning naming the affected headings
  • When level= is set, heading IDs go through the normal slugifier (no prefix)
  • Embedded heading levels are preserved by default (no demotion when level= is unset)
  • Canonical-link affordance: when the entity has a sourceUrl (via registry or SPEC-065 pattern), expand renders a "view canonical" link with a sensible default label (entity title or type) that authors can override
  • expand honors label= attribute on the canonical link
  • CSS in packages/lumina/styles/runes/expand.css covers the wrapper, the embedded-content area, and the canonical-link affordance
  • refrakt inspect expand shows the expected HTML
  • Authoring docs cover the rune syntax, attribute reference, the level= sub-section pattern, the data-outline-scope convention, and canonical-link customization

Approach

Per the spec:

  • packages/runes/src/tags/expand.ts — schema (createContentModelSchema)
  • packages/runes/src/config.tsExpand config entry; wrapper sets data-outline-scope (or omits when level= is set)
  • PostProcess hook resolves the entity from the registry, reads + parses the source file, extracts the top-level rune subtree, runs heading processing (level shift when level= is set; heading-ID walker handles the prefix via outline-scope), and splices into the host page's tree
  • Per-build cache keyed by sourceFile (same machinery as snippet's caching open question)
  • Canonical-link rendering uses the same xref resolution chain as {% ref %} (WORK-253) — entity lookup gives metadata, URL comes from sourceUrl or patterns

Dependencies

  • WORK-251 — plan entities registered with sourceFile and extract (primary content source for expand)
  • WORK-259 — generic data-outline-scope walkers (consume the attribute expand sets)
  • WORK-253 — xref resolver (canonical-link affordance reuses it)

References

  • SPEC-066 — expand-rune spec (full)
  • SPEC-064 — plan-entity registration (the primary content source)
  • SPEC-065 — xref resolution (canonical-link composition)
  • SPEC-060 — drawer rune (common composition target: expand inside drawer body)