Skip to main content

Module content_stager

Module content_stager 

Source
Expand description

Content staging — residual upstream-gap workarounds for the staticdatagen → staticweaver → metadata-gen pipeline.

§v0.0.46 residual scope

Most of v0.0.45’s shim layer was retired in v0.0.46 by upstream fixes:

  • staticdatagen 0.0.10 (closes upstream #67, #68, #69, #70, #71) handles missing layout: keys, absent main.js/sw.js, absent tags-page templates, nested-locale walk (_posts/<lang>/), and success-log ordering natively.
  • staticweaver 0.0.3 (closes upstream #28) added the Engine::with_lax_undefined(true) opt-in.
  • staticweaver 0.0.3 also made escape_html_into idempotent (closes ssg #589).
  • rss-gen 0.0.6 (closes upstream #34) prefixed validation errors with channel. / item. context and accepts relative URLs at item level.
  • metadata-gen 0.0.5 (closes upstream #20) collapses multi-line double-quoted YAML scalars internally.

What remains here are two narrow gaps the upstreams haven’t closed yet:

  1. Template-default injection. staticdatagen 0.0.10 doesn’t yet opt the staticweaver Engine into lax_undefined (tracked at staticdatagen #99), so unresolved {{ var }} tags still abort the build. collect_template_vars + stage_content_with_template_defaults pre-fill an empty var: "" for every key the templates reference but the content omits.

  2. Multi-line quoted-scalar collapse. staticdatagen 0.0.10 pins metadata-gen = "0.0.4" (the pre-#20 release; tracked at staticdatagen #100). copy_tree (the per-file staging helper) applies the same collapse pass that’s now upstream in metadata-gen 0.0.5, so the user’s content sees consistent behaviour regardless of which metadata-gen is transitively resolved.

Both shims auto-retire when the corresponding staticdatagen follow-up releases — the residual module shrinks to nothing.

staticdatagen’s RSS generator hard-fails the whole build when a post lacks permalink: front matter (rss-gen: “channel.link is missing”). Because every page passes through this stager before staticdatagen::compile, the stager can make that failure unreachable: when a staged .md file’s frontmatter carries neither permalink nor url, stage_content_with_site_defaults injects permalink: "{base_url}/{relative_output_path}" derived via crate::urls::derive_permalink. Author-specified permalinks always win — files that already declare permalink or url pass through verbatim. Only YAML --- fenced frontmatter flows through this stager (the template-default shim shares the same constraint); files without a frontmatter block are left untouched.

§Why staging instead of editing in-place?

The user’s checkout is sacred:

  • the build runs from a CI checkout the user expects to be read-only;
  • reruns of the build would re-inject defaults, doubling lines.

Instead we operate on a fresh directory under std::env::temp_dir() (FNV-1a-keyed by build_dir + pid) that’s recreated on every build.

Functions§

collect_template_vars
Walks template_dir recursively and returns the sorted, deduped set of every {{ <var> }} reference found in the template files.
inject_missing_keys
Injects empty key: "" entries into the frontmatter block for any key not already present. No-op for files without a frontmatter block.
inject_missing_keys_with_values
As inject_missing_keys, but derived supplies real values for the keys it names instead of the empty-string placeholder.
inject_permalink_if_missing
Injects permalink: "<permalink>" as the first key of the YAML frontmatter block when the block exists and declares neither permalink nor url (spec A2/B1, plan §2 item 1.2, issue #586).
stage_content_with_site_defaults
Like stage_content_with_template_defaults but also derives a permalink: for staged .md files that don’t declare one.
stage_content_with_template_defaults
Stages a copy of content_dir and injects empty defaults for every {{ var }} reference the templates make.