feat(utilities): add UniqueID helper, adopt AddModule#345
Merged
Conversation
UniqueID returns a page-unique, build-stable element id from a per-prefix counter in the page's Store. It replaces hashing `now` (which changes the id on every build, so a page carrying the component never renders byte-identically) and `.Ordinal` (which restarts at 0 inside an embedded RenderString, so ids collide). AddModule moves here from Hinode. No gethinode module declares a dependency on Hinode, so a partial there reaches them only because the site merges Hinode's layouts - an undeclared inverted dependency that breaks each module's own exampleSite build.
Hugo de-duplicates repeated headings by appending "-1", "-2", ..., so a page with two "FAQ" headings emits `faq` and `faq-1` - colliding head-on with the old bare `<prefix>-<n>` id shape. Insert a literal, uppercase "UID" segment that `anchorize` can never produce, making the collision structurally impossible. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 15, 2026
Collaborator
Author
|
🎉 This PR is included in version 6.5.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds two shared partials that the rest of the ecosystem depends on.
UniqueID.htmlReturns a page-unique, build-stable element id of the form
<prefix>-UID-<n>, from a per-prefix counter held in the page'sStore.It replaces two broken patterns found across the ecosystem:
md5(delimit (slice . now) "-")— hashing the current time, so the id changed on every build. Any page carrying such a component emitted different HTML each time, defeating output diffing and making caches treat an unchanged page as changed..Ordinal— which restarts at 0 inside an embeddedRenderString(exactly what theexampleshortcode performs), so two components in two{{< example >}}blocks on one page collide.page.Storewas measured to survive the embedded-RenderStringboundary where.Ordinaldoes not.The
UIDsegment is load-bearing, not decoration. Hugo derives heading anchors withanchorize, which lowercases and de-duplicates repeated headings by appending-1,-2. A page with two "FAQ" headings emitsfaqthenfaq-1— which would collide head-on with a barefaq-1container id, and Bootstrap'squerySelectorwould bind the accordion to the heading instead. An uppercase segment is unreachable foranchorize, so the collision cannot occur.AddModule.htmlMoved here from Hinode. No gethinode module declares a dependency on Hinode, yet mod-blocks'
listcomponent callsAddModule— so a partial in Hinode reached it only because the final site merges Hinode's layouts, an undeclared inverted dependency that breaks each module's own exampleSite build. It carries the two fixes it received recently: it appends-and-deduplicates rather than replacing the dependency list, and it honours an explicitly-passedpage.Release ordering
This is step 1 of three: mod-utils → mod-blocks → Hinode. mod-blocks and Hinode both bump their mod-utils pin to this release before they merge.
🤖 Generated with Claude Code