fix(pagination): avoid inline partial name collision with Hugo - #2119
Merged
Conversation
The pagination markup is defined as inline partials named
`_partials/inline/pagination/{default,terse}`. Hugo ships an embedded
template named `_partials/pagination.html`, and that name collides:
`partial "inline/pagination/default"` resolves to Hugo's embedded
pagination template instead of ours on roughly 58% of builds.
When it does, pagination renders Hugo's default markup — bare `«`
glyphs and a hardcoded `aria-label="First"` — instead of the themed
icons and the translated label. The icon classes are then absent from
the rendered HTML, so they never reach `hugo_stats.json`, and PurgeCSS
correctly strips the matching rules. The result is a production build
that nondeterministically ships pagination buttons with no glyph, and a
main.min.css whose hash changes between otherwise identical builds.
Rename the namespace to `_partials/inline/paginator/*`, which has no
embedded counterpart. `sidebar/*` and `bundlev3/*` are the only other
namespaced inline partials and neither collides.
Measured on this exampleSite with `HUGO_PAGINATION_PAGERSIZE=2`:
3/8 builds degraded before, 0/12 after. On gethinode.com, which hits
this on /docs/configuration/: 21/36 degraded before, 0/16 after.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for gethinode-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
markdumay
enabled auto-merge
August 4, 2026 10:15
Collaborator
Author
|
🎉 This PR is included in version 3.19.1 🎉 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.
Pagination nondeterministically renders Hugo's default markup instead of the theme's, which also strips the pagination icon rules out of the purged CSS. Three-line rename.
The bug
layouts/_partials/assets/pagination.htmldefines its markup as inline partials named_partials/inline/pagination/{default,terse}. Hugo ships an embedded template named_partials/pagination.html— the names collide, andpartial "inline/pagination/default"resolves to Hugo's embedded pagination template rather than ours on roughly 58% of builds.When that happens the pagination renders as:
instead of:
So the build silently loses both the themed icon and the translated
aria-label(T "paginationFirst"→ "First page" becomes a hardcoded "First").Knock-on effect on purged CSS
Because the icon classes never appear in the rendered HTML, they never reach
hugo_stats.json, so PurgeCSS correctly strips the matching rules:Net effect on a production site: the pagination first/last buttons ship with no glyph at all on a random ~58% of builds, and
main.min.csschanges hash between otherwise identical builds. That is how this was found — chasing a CSS hash that would not reproduce on gethinode.com.The fix
Rename the namespace to
_partials/inline/paginator/*, which has no embedded counterpart.sidebar/*andbundlev3/*are the only other namespaced inline partials in the theme, and neither collides with Hugo's embedded set (pagination,opengraph,twitter_cards,schema,disqus,google_analytics).Verification
exampleSite,
HUGO_PAGINATION_PAGERSIZE=2, checking/nl/blog/for Hugo's«markup:Independently on gethinode.com, which hits this on
/docs/configuration/:With the fix,
main.min.cssis byte-identical across 6 consecutive builds there; before it alternated between two hashes.Also run:
pnpm test(eslint + stylelint + markdownlint + template tests) → 0 issues;pnpm build:example→ 149 pages EN/FR/NL, exit 0.Ruled out
Recorded so nobody re-tests them: the dynamic
printfpartial name is not the cause (staticif/elsedispatch still degraded 7/10); there is no duplicate inline-partial definition; andGOMAXPROCS=1still degrades (2/6), so it is not simply a parallelism race. Shadowing the embedded template with a site-levellayouts/_partials/pagination.htmlalso suppresses it (14/14) but is a workaround, not a fix.Upstream
Hugo silently resolving a namespaced partial to an unrelated embedded template — nondeterministically, with no warning — looks like a Hugo defect in its own right, and is probably worth reporting separately. This PR is the theme-side fix.
🤖 Generated with Claude Code