Changelog
All notable user-facing changes are recorded here. The format follows Keep a Changelog.
Until 1.0, Heine uses 0.y.0 for deliberate public contract additions or
changes that can require an author migration. It uses 0.y.z for
backward-compatible fixes and documentation improvements. Each incompatible
change names its smallest migration.
Maintaining this file
Update the Unreleased section in the same change that alters a user's
authored input, generated output, command behavior, supported environment, or
documented public contract. Group related work into one entry: a changelog
describes the difference a user experiences, not each commit or file changed.
Do not record internal refactors, routine dependency updates, test-only work,
or starter-site visual adjustments unless they change that public experience.
Use a non-empty Added, Changed, Deprecated, Removed, Fixed, or
Security subsection. Start every entry with a bold, short name, then state
what changed and why it matters. When an existing site, template, command, or
integration needs adjustment, label the smallest complete remedy as
Migration:. An intentional tightening that makes formerly accepted
authored input fail is incompatible and needs that guidance too.
At release, review Unreleased for omissions, move its contents unchanged
under ## [<version>] - YYYY-MM-DD, and begin a new empty Unreleased
section above it. The heading version must match Cargo.toml; released entries
are corrected only to repair an error or explain a missed material migration.
[Unreleased]
Added
Multilingual sitemap alternates. Sites may opt into
sitemap.hreflang = trueto emit checked, locale-sorted XHTML alternate sets for explicit, sitemap-includedtranslationidcounterparts. This keeps search-engine language discovery tied to the same authored relationships as Heine's language-switcher data.Checked absolute URLs. Configuring
site.originnow exposes the base-path-aware canonical root assite.urlandabsolute_urlon known page, asset, and generated-resource views. This supports canonical and metadata markup without exposing a raw origin or accepting unchecked template URL construction. Migration: configure an HTTP(S)site.originbefore a template reads either new field.Markdown word counts and reading-time estimates. Every declared Markdown input now exposes a deterministic Unicode
word_countthroughpage.markdown.<name>. Sites may opt into checked locale-specificreading_timeestimates with[reading_time.words_per_minute], keeping the chosen policy separate from the source fact.Color-scheme Markdown pictures. A standalone
:::pictureblock now connects checked light and dark copied assets to one native HTMLpicture, with an optional semanticfigurecaption. It keeps Markdown documentation and prose independent of template markup while preserving source-spanned asset diagnostics, intrinsic layout dimensions, and source-level search text.Semantic responsive Markdown tables. Sites can opt into localized, labelled
heine-table-scrollregions for parsed Markdown tables, allowing site CSS to provide keyboard-accessible narrow-screen horizontal scrolling without changing native table semantics. Trusted raw HTML tables remain author-owned. Migration: no existing table configuration changes. To add responsive regions, configure[markdown.tables].scroll_messageand define that Fluent message in the default locale, with ordinary locale fallback or translations as appropriate.Copied-asset licensing coverage. Sites can opt into
licensing.required = trueto require one checked REUSE-compatible declaration for every copied asset Heine publishes. Exact[[licensing.groups]]declarations let a coherent upstream or first-party asset set share facts without duplicated sidecars, while conflicts and incomplete coverage name their authored or copied paths deterministically.Draft publication previews. Pages may declare
draft = true; ordinary builds exclude them before resolving links and generated relationships, whileheine serve --draftspreviews them in their real site context. This lets an unfinished page remain private without making published navigation, feeds, indexes, or sitemaps inconsistent.Search documents now expose each entry's
draftfact and therefore use schema format2. Migration: update a search client that checksformatto accept2and its booleandraftfield.Checked Series. Rendered pages can join one or more named, locale-local reading sequences with independently checked positions, generated listings, pagination, and deliberate template-controlled navigation. This gives a reading order a first-class relationship without overloading collections, taxonomies, or page weight.
Margin-footnote presentation. A page can opt one declared Markdown input into local, semantic footnotes that CSS presents beside their prose on wide screens and below it elsewhere. This keeps references near their context without making JavaScript or a new Markdown notation part of the contract.
Accessible Markdown task lists. Task-list checkboxes now carry their authored checked state and accessible labels. This preserves ordinary Markdown authoring while making the generated control understandable beyond its visual checkmark.
Changed
Search result fragments. Search-document format
3replaces each document's singletextstring with orderedsections, each carrying text and an existing table-of-contents fragment when one applies. This lets a browser link a matching result to its nearest rendered heading without guessing from HTML. Migration: update a search client to indexsections[].text; join those strings when it needs one page-wide field, and append a non-null section fragment to the document URL when it presents a section-level result.Exactly rendered table-of-contents sources. A page with an effective table of contents must render its selected Markdown source exactly once with
markdown(content="…"). This keeps generated heading fragments unique and makes fragment-aware search results point at a real rendered location. Migration: replace an omitted or repeated selected-source render with onemarkdown(content="…")call in the page's template.Explicit sibling-weight opt-out.
weight = falsenow excludes a page from sibling ordering, replacing the former magic stringweight = "None". This makes the authored opt-out match Heine's other boolean exclusions and keeps the resolved ordering model finite. Migration: replace everyweight = "None"withweight = false.Checked ordinary footnote references. A
[^label]reference without a definition now fails at its Markdown source instead of appearing as literal text. This preserves the checked relationship promised by thefootnotesextension. Migration: add[^label]: ..., remove the reference, or write\[^label]when literal text is intended.Reserved generated footnote fragments. Ordinary and margin-footnote fragments now use the
__heine-footnote-...namespace, avoiding collisions with generated heading fragments. Migration: if authored raw HTML, templates, CSS, or inbound links depended on an old generated footnote ID, update them to the new generated output; avoid the reserved namespace for future authored IDs.
Fixed
Literal fenced footnotes. Fenced code examples containing
[^label]no longer trigger an ordinary-footnote missing-definition diagnostic. This keeps documented Markdown source literal while retaining checked references in prose.Development directory redirects.
heine servenow redirects an existing generated directory requested without its trailing slash to the slash form, retaining query parameters. This gives browsers the correct base URL for relative references while keeping directory-index serving a local preview convenience.