From fe51d8ea7939eef986c8674fe977ca352a45da86 Mon Sep 17 00:00:00 2001 From: Mark Dumay <61946753+markdumay@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:37:12 +0200 Subject: [PATCH 1/5] fix: adopt mod-fontawesome v6.1.1 and thread the owning page through icon call sites Bump mod-fontawesome to v6.1.1, whose icon partial accepts a 'page' argument and dual-writes symbol registrations to the page Scratch and Store (render-once D2). The Font-Awesome upstream snapshot rides along (webfonts change bytes). Thread the owning page through hinode's assets/icon.html call sites so sprite symbols land on the page that emits them, whichever context triggers the render: shortcodes pass .Page, partials their in-scope page. The button and card-icon argument structures gain an optional 'page' argument (Q6 posture: omitted pages fall back to the global page context) so their callers can thread it through. utilities/GetIllustration.html has no rendering page in scope and stays on the global fallback. Co-Authored-By: Claude Fable 5 --- data/structures/button.yml | 2 ++ data/structures/card-icon.yml | 2 ++ exampleSite/go.mod | 2 -- exampleSite/go.sum | 4 ---- exampleSite/hinode.work.sum | 1 + go.mod | 4 ++-- go.sum | 4 ++++ layouts/404.html | 2 +- layouts/_markup/render-blockquote.html | 2 +- layouts/_markup/render-heading.html | 2 +- layouts/_partials/assets/breadcrumb.html | 2 +- layouts/_partials/assets/button.html | 4 ++-- layouts/_partials/assets/card-group.html | 3 ++- layouts/_partials/assets/card-icon.html | 6 ++--- layouts/_partials/assets/card.html | 23 ++++++++++++------ layouts/_partials/assets/download.html | 3 ++- .../assets/featured-illustration.html | 2 +- .../_partials/assets/helpers/navbar-item.html | 5 ++-- .../assets/helpers/navbar-languages.html | 4 ++-- .../_partials/assets/helpers/navbar-mode.html | 9 +++---- .../assets/helpers/navbar-versions.html | 2 +- .../_partials/assets/lightbox-trigger.html | 2 +- layouts/_partials/assets/lightbox.html | 2 +- layouts/_partials/assets/link.html | 2 +- layouts/_partials/assets/links.html | 3 ++- layouts/_partials/assets/menu-item.html | 1 + layouts/_partials/assets/nav.html | 2 +- layouts/_partials/assets/navbar.html | 5 ++-- layouts/_partials/assets/pagination.html | 24 +++++++++---------- layouts/_partials/assets/sidebar.html | 12 +++++----- layouts/_partials/assets/testimonial.html | 5 ++-- layouts/_partials/assets/timeline.html | 8 ++++--- layouts/_partials/assets/toc-dropdown.html | 5 ++-- .../_partials/assets/toc-parse-content.html | 2 ++ layouts/_partials/footer/social.html | 2 +- layouts/_partials/page/navigation.html | 4 ++-- layouts/_partials/page/sharing.html | 5 +++- layouts/_partials/page/tags.html | 4 ++-- layouts/_shortcodes/alert.html | 2 +- layouts/_shortcodes/button.html | 3 ++- layouts/_shortcodes/release.html | 3 ++- layouts/_shortcodes/tooltip.html | 3 ++- layouts/form/single.html | 2 +- 43 files changed, 110 insertions(+), 79 deletions(-) diff --git a/data/structures/button.yml b/data/structures/button.yml index 9a861f071..b8230b96a 100644 --- a/data/structures/button.yml +++ b/data/structures/button.yml @@ -2,6 +2,8 @@ comment: >- Display a button with a hyperlink. icon: touch_app arguments: + page: + optional: true title: preview: true class: diff --git a/data/structures/card-icon.yml b/data/structures/card-icon.yml index 0b9c34148..175deda14 100644 --- a/data/structures/card-icon.yml +++ b/data/structures/card-icon.yml @@ -2,6 +2,8 @@ comment: >- Renders a card icon including optional rounding. group: partial arguments: + page: + optional: true icon: padding: icon-rounded: diff --git a/exampleSite/go.mod b/exampleSite/go.mod index b4c4fb3ce..7a7cc59b5 100644 --- a/exampleSite/go.mod +++ b/exampleSite/go.mod @@ -3,11 +3,9 @@ module github.com/gethinode/hinode-example go 1.19 require ( - github.com/FortAwesome/Font-Awesome v0.0.0-20260625220317-70fb2dd154b6 // indirect github.com/cloudcannon/bookshop/hugo/v3 v3.18.5 // indirect github.com/gethinode/mod-bootstrap-icons/v2 v2.0.1 // indirect github.com/gethinode/mod-cookieyes/v2 v2.2.6 // indirect github.com/gethinode/mod-docs v1.15.2 // indirect - github.com/gethinode/mod-fontawesome/v6 v6.0.2 // indirect github.com/twbs/icons v1.13.1 // indirect ) diff --git a/exampleSite/go.sum b/exampleSite/go.sum index 8e733eed5..1495faa97 100644 --- a/exampleSite/go.sum +++ b/exampleSite/go.sum @@ -1,5 +1,3 @@ -github.com/FortAwesome/Font-Awesome v0.0.0-20260625220317-70fb2dd154b6 h1:slcJCZg0UQMHqw5JCoVmE8/IJfoNUprTmP2T3lDG9VY= -github.com/FortAwesome/Font-Awesome v0.0.0-20260625220317-70fb2dd154b6/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= github.com/cloudcannon/bookshop/hugo/v3 v3.18.5 h1:AKWzUQpWcBSbJgHQ/5cfPQtGX40bn8vbHBGk4rlHEGE= github.com/cloudcannon/bookshop/hugo/v3 v3.18.5/go.mod h1:s7mIonDhtsLcn10ZKuVXyqd6BDHI8vT1WQhZw8rPfY8= github.com/gethinode/mod-bootstrap-icons/v2 v2.0.1 h1:shq4Gb48U3h9xYUpq+FSHWz/eu1azJ5bMkja6wPmCpM= @@ -8,7 +6,5 @@ github.com/gethinode/mod-cookieyes/v2 v2.2.6 h1:/DQm8OYpms0On8wuosQER47TplVu/3z7 github.com/gethinode/mod-cookieyes/v2 v2.2.6/go.mod h1:tULb7D7CoTycGUyL7ryqHJKaX11XuL2SN+XwP7/DI0Y= github.com/gethinode/mod-docs v1.15.2 h1:ZuOO/M5KyuUNGEoId+rManHG/L3WBboXG9L/ikSPNrY= github.com/gethinode/mod-docs v1.15.2/go.mod h1:ru1w0fHqFocjDIMV0dm40OwhBw5k4UncCS8iO/1S5kI= -github.com/gethinode/mod-fontawesome/v6 v6.0.2 h1:MxaHU7MZIh4pgxtoR6C/F0qiB5eSiySmRpTw9DGIOVs= -github.com/gethinode/mod-fontawesome/v6 v6.0.2/go.mod h1:Zy+hjVhFDU52nkTIn9btbZ1PWy2n203zKHiPG9RVSL0= github.com/twbs/icons v1.13.1 h1:6bmNXvoeIbvjFWjfbjXg5JGbelLD1haIsMaEIzE9UZI= github.com/twbs/icons v1.13.1/go.mod h1:GnRlymgVWp5iVJCMa0Me5b6tFyGpVc2bSxPMRGIJmyA= diff --git a/exampleSite/hinode.work.sum b/exampleSite/hinode.work.sum index 8bc099208..769f6f2ed 100644 --- a/exampleSite/hinode.work.sum +++ b/exampleSite/hinode.work.sum @@ -17,3 +17,4 @@ github.com/gethinode/mod-fontawesome/v3 v3.1.3/go.mod h1:+E6jSVNv7h6oXw4Wm1XRq8H github.com/gethinode/mod-utils/v4 v4.12.0 h1:5sSfYIxZCeQbXLoZdS//rl6thwLwtXuvM0ujaWKyPmc= github.com/gethinode/mod-utils/v4 v4.12.0/go.mod h1:bYmvRdAo4ICy5MpSGafDvO4p5bTDpsDKFCPL3bH0mN4= github.com/gethinode/mod-utils/v6 v6.5.0/go.mod h1:E5tO9w3VKaidJpu1nI8zAKmh0bddFHOIIQnudAaXQTs= +github.com/gethinode/mod-utils/v6 v6.5.1/go.mod h1:E5tO9w3VKaidJpu1nI8zAKmh0bddFHOIIQnudAaXQTs= diff --git a/go.mod b/go.mod index 9812d4c3e..c7db3a7cc 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/gethinode/hinode/v3 go 1.19 require ( - github.com/FortAwesome/Font-Awesome v0.0.0-20260625220317-70fb2dd154b6 // indirect + github.com/FortAwesome/Font-Awesome v0.0.0-20260715180930-14c65a3747d0 // indirect github.com/airbnb/lottie-web v5.13.0+incompatible // indirect github.com/gethinode/mod-blocks/v2 v2.2.0 // indirect github.com/gethinode/mod-bootstrap v1.3.7 // indirect github.com/gethinode/mod-csp v1.0.12 // indirect github.com/gethinode/mod-flexsearch/v5 v5.0.2 // indirect - github.com/gethinode/mod-fontawesome/v6 v6.0.2 // indirect + github.com/gethinode/mod-fontawesome/v6 v6.1.1 // indirect github.com/gethinode/mod-google-analytics/v2 v2.0.4 // indirect github.com/gethinode/mod-katex v1.1.6 // indirect github.com/gethinode/mod-leaflet/v3 v3.1.1 // indirect diff --git a/go.sum b/go.sum index 1709b7e8c..5668e15ee 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/FortAwesome/Font-Awesome v0.0.0-20260625220317-70fb2dd154b6 h1:slcJCZg0UQMHqw5JCoVmE8/IJfoNUprTmP2T3lDG9VY= github.com/FortAwesome/Font-Awesome v0.0.0-20260625220317-70fb2dd154b6/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= +github.com/FortAwesome/Font-Awesome v0.0.0-20260715180930-14c65a3747d0 h1:4+bB2ojsMTsQroHtQr1FWy2gxFzpBn5hISldeRfxF+o= +github.com/FortAwesome/Font-Awesome v0.0.0-20260715180930-14c65a3747d0/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= github.com/airbnb/lottie-web v5.13.0+incompatible h1:plBV5Uq/F1kK0EC61Hr0cBGReI9OgUfd/pp0baoDX8o= github.com/airbnb/lottie-web v5.13.0+incompatible/go.mod h1:nTss557UK9FGnp8QYlCMO29tjUHwbdAHG/DprbGfHGE= github.com/gethinode/mod-blocks/v2 v2.2.0 h1:sIRH7R7MYvqVECByJEuopVgzUCOa+iOEYOFCIouo5A0= @@ -12,6 +14,8 @@ github.com/gethinode/mod-flexsearch/v5 v5.0.2 h1:VAHzYLJECrVBvzn5xvM+FoHSP2VwDDP github.com/gethinode/mod-flexsearch/v5 v5.0.2/go.mod h1:0kRR1xaAhSYVyVICV5+x5bF8OSpfre1DwLdrK3a5uAA= github.com/gethinode/mod-fontawesome/v6 v6.0.2 h1:MxaHU7MZIh4pgxtoR6C/F0qiB5eSiySmRpTw9DGIOVs= github.com/gethinode/mod-fontawesome/v6 v6.0.2/go.mod h1:Zy+hjVhFDU52nkTIn9btbZ1PWy2n203zKHiPG9RVSL0= +github.com/gethinode/mod-fontawesome/v6 v6.1.1 h1:k5Jy7nA+YfLZ9YqXH8hyaiw9wjAeOxNEUcnu6fynnJo= +github.com/gethinode/mod-fontawesome/v6 v6.1.1/go.mod h1:875OBk5te+KBJmr0PdSkFcduYnsKCuHWfcaqChh9NGo= github.com/gethinode/mod-google-analytics/v2 v2.0.4 h1:ONEUjhfVR6p+Y/XyU3BUGXZy4+HAkJvGo+mr24ugklY= github.com/gethinode/mod-google-analytics/v2 v2.0.4/go.mod h1:y4ZlacA8FSXjmvn9P8cZshOrBB5Wc+3p0DKSehkk+8E= github.com/gethinode/mod-katex v1.1.6 h1:mow61stEySb5mH5tUp1l69l2FrLWl+jh46JVT5lMOSA= diff --git a/layouts/404.html b/layouts/404.html index 9cf541bf5..b0ed731db 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -5,7 +5,7 @@
- {{ partial "assets/icon.html" (dict "icon" $notFoundPage "class" "fa-10x") }} + {{ partial "assets/icon.html" (dict "page" . "icon" $notFoundPage "class" "fa-10x") }}

404

{{ T "pageNotFoundTitle" }}

diff --git a/layouts/_markup/render-blockquote.html b/layouts/_markup/render-blockquote.html index 92f9f7da2..b24747405 100644 --- a/layouts/_markup/render-blockquote.html +++ b/layouts/_markup/render-blockquote.html @@ -17,7 +17,7 @@

{{ with $icon }} - {{ partial "assets/icon.html" (dict "icon" . "class" "fa-fw") }} + {{ partial "assets/icon.html" (dict "page" $.Page "icon" . "class" "fa-fw") }} {{ or (i18n $alert) (title $alert) }} {{ else }} {{ title $alert }} diff --git a/layouts/_markup/render-heading.html b/layouts/_markup/render-heading.html index f92a47d32..9107becce 100644 --- a/layouts/_markup/render-heading.html +++ b/layouts/_markup/render-heading.html @@ -29,7 +29,7 @@ {{- $text | safeHTML -}} - {{- partial "assets/icon.html" (dict "icon" $headingAnchor "class" "anchor") }} + {{- partial "assets/icon.html" (dict "page" .Page "icon" $headingAnchor "class" "anchor") }} {{ else }} diff --git a/layouts/_partials/assets/breadcrumb.html b/layouts/_partials/assets/breadcrumb.html index 5661bd446..d10727e78 100644 --- a/layouts/_partials/assets/breadcrumb.html +++ b/layouts/_partials/assets/breadcrumb.html @@ -54,7 +54,7 @@ {{ $item := index $items (sub $length 1) }}

{{- end -}} diff --git a/layouts/_partials/assets/button.html b/layouts/_partials/assets/button.html index 0311eb3c1..1531e54d9 100644 --- a/layouts/_partials/assets/button.html +++ b/layouts/_partials/assets/button.html @@ -68,7 +68,7 @@ {{- end -}} {{- if and $title $cue -}} - {{ $suffix := partial "assets/icon.html" (dict "icon" $externalLink "class" "fa-2xs") }} + {{ $suffix := partial "assets/icon.html" (dict "page" $args.page "icon" $externalLink "class" "fa-2xs") }} {{- $title = printf "%s %s" $title $suffix | safeHTML -}} {{- end -}} {{- end -}} @@ -105,7 +105,7 @@ {{ $title | safeHTML }} {{- with $args.icon }} - {{ partial "assets/icon.html" (dict "icon" $args.icon "class" ($args.iconClass | default "") "spacing" false) }} + {{ partial "assets/icon.html" (dict "page" $args.page "icon" $args.icon "class" ($args.iconClass | default "") "spacing" false) }} {{ end }} diff --git a/layouts/_partials/assets/card-group.html b/layouts/_partials/assets/card-group.html index ce724ea06..5e0e5df56 100644 --- a/layouts/_partials/assets/card-group.html +++ b/layouts/_partials/assets/card-group.html @@ -203,7 +203,8 @@ {{- $href = printf "%s/" $href -}} {{- end -}}
- {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" $args.page "href" $href "title" $args.hrefTitle "color" "primary" diff --git a/layouts/_partials/assets/card-icon.html b/layouts/_partials/assets/card-icon.html index 01c01f12b..10efd99a0 100644 --- a/layouts/_partials/assets/card-icon.html +++ b/layouts/_partials/assets/card-icon.html @@ -26,10 +26,10 @@ {{ $args.class }}" > {{ if $args.iconRounded }} - {{- partial "assets/icon.html" (dict "icon" "fas circle" "class" "fa-stack-2x" "spacing" false) -}} - {{- partial "assets/icon.html" (dict "icon" $args.icon "class" "fa-stack-1x fa-inverse" "spacing" false) -}} + {{- partial "assets/icon.html" (dict "page" $args.page "icon" "fas circle" "class" "fa-stack-2x" "spacing" false) -}} + {{- partial "assets/icon.html" (dict "page" $args.page "icon" $args.icon "class" "fa-stack-1x fa-inverse" "spacing" false) -}} {{ else }} - {{- partial "assets/icon.html" (dict "icon" $args.icon "class" (trim (printf "%s fa-fw" (or $args.iconStyle "")) " ") "spacing" false) -}} + {{- partial "assets/icon.html" (dict "page" $args.page "icon" $args.icon "class" (trim (printf "%s fa-fw" (or $args.iconStyle "")) " ") "spacing" false) -}} {{ end }}
{{ end }} \ No newline at end of file diff --git a/layouts/_partials/assets/card.html b/layouts/_partials/assets/card.html index 01fd7de15..5b50d9f50 100644 --- a/layouts/_partials/assets/card.html +++ b/layouts/_partials/assets/card.html @@ -8,10 +8,12 @@ {{- define "_partials/inline/card-icons.html" -}} {{ $links := .links }} - + {{ $page := .page }} + {{- range $index, $item := $links -}} - {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" $page "href" $item.url "icon" ($item.icon | default "") "icon-class" "fa-fw" @@ -26,6 +28,7 @@ {{/* Inline partial to render the card's body */}} {{- define "_partials/inline/card-body.html" -}} {{- $page := .page -}} + {{- $owner := .owner -}} {{- $title := .title -}} {{- $href := .href -}} {{- $color := .color -}} @@ -40,8 +43,8 @@ {{ if or $title $links }}

{{- with $title }}{{ . | $page.RenderString }}{{ end }} - {{ with $links }}{{ partial "inline/card-icons.html" (dict "links" .) }}{{ end -}} - {{- with $linkIcon -}}{{- partial "assets/icon.html" (dict "icon" . "spacing" false) -}}{{- end -}} + {{ with $links }}{{ partial "inline/card-icons.html" (dict "links" . "page" $owner) }}{{ end -}} + {{- with $linkIcon -}}{{- partial "assets/icon.html" (dict "page" $owner "icon" . "spacing" false) -}}{{- end -}}

{{ end -}} {{ with $description }} @@ -55,7 +58,7 @@ {{ if or $title $links }}

{{- with $title }}{{ . | $page.RenderString }}{{ end }} - {{ with $links }}{{ partial "inline/card-icons.html" (dict "links" .) }}{{ end -}} + {{ with $links }}{{ partial "inline/card-icons.html" (dict "links" . "page" $owner) }}{{ end -}}

{{ end -}} {{ with $description }}
{{ . | safeHTML }}
{{ end -}} @@ -245,6 +248,7 @@
{{ if $icon }} {{- partial "assets/card-icon.html" (dict + "page" $args.page "icon" $icon "padding" 0 "icon-rounded" $args.iconRounded @@ -263,6 +267,7 @@ {{ end }} {{- partial "inline/card-body.html" (dict "page" $renderPage + "owner" $args.page "title" (cond $minimal "" $title) "href" $href "color" $args.color @@ -285,7 +290,8 @@ {{ $buttonType := (or $args.linkType $args.buttonType) }} {{ if eq $buttonType "link" }}{{ $buttonClass = "card-button card-button-link mb-n4" }}{{ end }}
- {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" $args.page "title" $label "icon" $cardReadMore "href" $href @@ -313,6 +319,7 @@ )) -}} {{- else if $icon -}} {{- partial "assets/card-icon.html" (dict + "page" $args.page "icon" $icon "padding" 0 "icon-rounded" $args.iconRounded @@ -326,6 +333,7 @@ {{ if $page }}{{- partial "inline/card-caption.html" (dict "page" $page "keywords" $args.headerStyle "color" $args.color) -}}{{ end }} {{- partial "inline/card-body.html" (dict "page" $renderPage + "owner" $args.page "title" (cond $minimal "" $title) "href" $href "color" $args.color @@ -346,7 +354,8 @@ {{ $buttonType := (or $args.linkType $args.buttonType) }} {{ if eq $buttonType "link" }}{{ $buttonClass = "card-button card-button-link" }}{{ end }} {{ if ne $args.align "start" }}{{ $buttonClass = printf "%s m%s-auto" $buttonClass (cond (eq $args.align "center") "x" "s") }}{{ end }} - {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" $args.page "title" $label "href" $href "outline" true diff --git a/layouts/_partials/assets/download.html b/layouts/_partials/assets/download.html index d34eae9cd..466367aa2 100644 --- a/layouts/_partials/assets/download.html +++ b/layouts/_partials/assets/download.html @@ -59,7 +59,8 @@ {{ end }} {{ end }} {{ $attr := dict "download" (path.Base $download) }} - {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" $args.page "href" $download "title" $title "color" $args.color diff --git a/layouts/_partials/assets/featured-illustration.html b/layouts/_partials/assets/featured-illustration.html index a169d8bb2..9cc43ceb1 100644 --- a/layouts/_partials/assets/featured-illustration.html +++ b/layouts/_partials/assets/featured-illustration.html @@ -40,7 +40,7 @@ ) -}} {{- end -}} {{- else }} - {{ partial "assets/icon.html" (dict "icon" $icon "class" $class "wrapper" $wrapper "spacing" false) -}} + {{ partial "assets/icon.html" (dict "page" $args.page "icon" $icon "class" $class "wrapper" $wrapper "spacing" false) -}} {{- end -}} {{- else if $image -}} {{- if not (hasSuffix $image "svg") }}{{ $class = strings.TrimSpace (printf "%s rounded" (or $class "")) }}{{ end -}} diff --git a/layouts/_partials/assets/helpers/navbar-item.html b/layouts/_partials/assets/helpers/navbar-item.html index a521f4ed1..f0c79c564 100644 --- a/layouts/_partials/assets/helpers/navbar-item.html +++ b/layouts/_partials/assets/helpers/navbar-item.html @@ -61,7 +61,7 @@ {{- if $isExternal }} {{- if $tab }}{{ $externalHref = "target=\"_blank\" rel=\"noopener noreferrer nofollow\"" }}{{ end -}} - {{- if $cue }}{{ $suffix = partial "assets/icon.html" (dict "icon" $externalLink "class" "fa-2xs my-auto") }}{{ end -}} + {{- if $cue }}{{ $suffix = partial "assets/icon.html" (dict "page" $page "icon" $externalLink "class" "fa-2xs my-auto") }}{{ end -}} {{ else if $menuURL }} {{ $ref := partial "utilities/GetPage.html" (dict "url" $url.Path "page" $page) }} {{- if not $ref -}} @@ -100,6 +100,7 @@ {{ if $entry.Params.button }} {{ partial "assets/button.html" (dict + "page" $page "title" $title "icon" (string $entry.Pre) "href" $menuURL @@ -122,7 +123,7 @@ {{ if hasPrefix . " diff --git a/layouts/_partials/assets/helpers/navbar-languages.html b/layouts/_partials/assets/helpers/navbar-languages.html index 78c1a5cf1..ab751112e 100644 --- a/layouts/_partials/assets/helpers/navbar-languages.html +++ b/layouts/_partials/assets/helpers/navbar-languages.html @@ -12,11 +12,11 @@ {{ if not $inline }} {{ end }}
{{- end -}} @@ -370,7 +370,7 @@ {{- if $collapsible }} data-sidebar-label="{{ $avTitle }}"{{ end }} href="{{ $avHref }}"> {{- with .pre -}} - {{- partial "assets/icon.html" (dict "icon" (string .) "class" "fa-fw me-1" "spacing" false) -}} + {{- partial "assets/icon.html" (dict "page" $page "icon" (string .) "class" "fa-fw me-1" "spacing" false) -}} {{- end -}} {{- if $collapsible -}} {{- $avTitle -}} @@ -385,7 +385,7 @@ aria-expanded="false" aria-controls="sidebar-secondary-{{ $sidebarId }}" aria-label="{{ T "toggleSecondary" | default "Toggle more items" }}"> - {{- partial "assets/icon.html" (dict "icon" $iconSecondary "class" "sidebar-secondary-icon fa-fw" "spacing" false) -}} + {{- partial "assets/icon.html" (dict "page" $page "icon" $iconSecondary "class" "sidebar-secondary-icon fa-fw" "spacing" false) -}} {{- end -}} diff --git a/layouts/_partials/assets/testimonial.html b/layouts/_partials/assets/testimonial.html index 13f550b3a..c85cf8777 100644 --- a/layouts/_partials/assets/testimonial.html +++ b/layouts/_partials/assets/testimonial.html @@ -95,7 +95,8 @@ "class" "rounded-circle testimonial-img" )}} {{ else if .link }} - {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" .page "href" .link "title" (T "testimonialCase") "class" "btn-testimonial" @@ -198,7 +199,7 @@ {{ partial "inline/testimonial-card.html" (merge $params (dict "class" "col-8 px-0 mb-5")) }}
- {{ partial "assets/icon.html" (dict "icon" $testimonialQuote "class" "fa-2x" "spacing" false) }} + {{ partial "assets/icon.html" (dict "page" $args.page "icon" $testimonialQuote "class" "fa-2x" "spacing" false) }}
{{ else }} diff --git a/layouts/_partials/assets/timeline.html b/layouts/_partials/assets/timeline.html index 7948853f1..0eac34190 100644 --- a/layouts/_partials/assets/timeline.html +++ b/layouts/_partials/assets/timeline.html @@ -75,6 +75,7 @@ {{/* Inline partial to render icon */}} {{- define "_partials/inline/timeline-icon.html" -}} {{- $col := default 6 .col -}} + {{- $page := .page -}} {{- $icon := .icon -}} {{- $class := .class -}} {{- $direction := .direction -}} @@ -82,6 +83,7 @@
{{ partial "assets/icon.html" (dict + "page" $page "icon" $icon "class" (cond $class $class "fa-fluid") "wrapper" "fa-wrapper" @@ -190,9 +192,9 @@ }} {{ if eq (mod $index 2) 1 }} {{ partial "inline/timeline-panel.html" (merge $params (dict "direction" "start")) }} - {{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "start") }} + {{ partial "inline/timeline-icon.html" (dict "page" $args.page "icon" $item.icon "direction" "start") }} {{ else }} - {{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "end") }} + {{ partial "inline/timeline-icon.html" (dict "page" $args.page "icon" $item.icon "direction" "end") }} {{ partial "inline/timeline-panel.html" (merge $params (dict "direction" "end")) }} {{ end }}
@@ -204,7 +206,7 @@
{{ range $index, $item := $data }}
- {{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "class" "fa-2xl" "direction" "end" "col" 3) }} + {{ partial "inline/timeline-icon.html" (dict "page" $args.page "icon" $item.icon "class" "fa-2xl" "direction" "end" "col" 3) }} {{ partial "inline/timeline-panel.html" (dict "page" $args.page "content" $item.content diff --git a/layouts/_partials/assets/toc-dropdown.html b/layouts/_partials/assets/toc-dropdown.html index 8aa8d4581..9307135ed 100644 --- a/layouts/_partials/assets/toc-dropdown.html +++ b/layouts/_partials/assets/toc-dropdown.html @@ -31,8 +31,9 @@ {{- with $headings }} {{- if and (not $error) (ge (len .) $minNumHeadings) }}
- {{ partial "assets/button.html" (dict - "title" (T "toc") + {{ partial "assets/button.html" (dict + "page" $args.page + "title" (T "toc") "color" "secondary" "outline" "true" "class" "toc-button" diff --git a/layouts/_partials/assets/toc-parse-content.html b/layouts/_partials/assets/toc-parse-content.html index 027d30af5..a9ac9fd5d 100644 --- a/layouts/_partials/assets/toc-parse-content.html +++ b/layouts/_partials/assets/toc-parse-content.html @@ -76,6 +76,7 @@ {{ range $i, $v := $result }} {{ if eq $i $maxNumHeadings }} {{ partial "assets/button.html" (dict + "page" $.Page "id" "btnTOCShowMore" "collapse-id" "toc-collapse-items" "link-type" "link" @@ -91,6 +92,7 @@ {{ if gt (len $result) $maxNumHeadings }}   {{ partial "assets/button.html" (dict + "page" $.Page "id" "btnTOCShowLess" "collapse-id" "toc-collapse-items" "link-type" "link" diff --git a/layouts/_partials/footer/social.html b/layouts/_partials/footer/social.html index f976a50ac..b4ec8fe7d 100644 --- a/layouts/_partials/footer/social.html +++ b/layouts/_partials/footer/social.html @@ -20,7 +20,7 @@ {{ if hasPrefix .Pre " {{ end -}} diff --git a/layouts/_partials/page/navigation.html b/layouts/_partials/page/navigation.html index a7916a417..0625576db 100644 --- a/layouts/_partials/page/navigation.html +++ b/layouts/_partials/page/navigation.html @@ -32,7 +32,7 @@ {{- with $prevPage -}} {{- if .OutputFormats.Get "html" -}} {{- end -}} {{- end -}} @@ -41,7 +41,7 @@ {{- with $nextPage -}} {{- if .OutputFormats.Get "html" -}} {{- end -}} {{- end -}} diff --git a/layouts/_partials/page/sharing.html b/layouts/_partials/page/sharing.html index 3b29a2046..5a6f6e3be 100644 --- a/layouts/_partials/page/sharing.html +++ b/layouts/_partials/page/sharing.html @@ -34,7 +34,8 @@ {{- $url = "" -}} {{- partial "assets/toast.html" (dict "id" $target "message" (printf "%s %s" (T "link") (T "copiedToClipboard"))) -}} {{- end -}} - {{ partial "assets/button.html" (dict + {{ partial "assets/button.html" (dict + "page" $ "toast-id" $target "clipboard" $clipboard "href" $url @@ -57,6 +58,7 @@ {{- end -}} {{- $icon := partial "utilities/GetThemeIcon.html" (dict "id" "sharingWebshare" "alias" (index site.Params.sharing "webshare-icon") "default" "fas share-nodes") -}} {{ partial "assets/button.html" (dict + "page" $ "href" "" "icon" $icon "icon-class" "fa-fw" @@ -79,6 +81,7 @@ {{ $attr := dict "download" (path.Base .) }} {{- $downloadIcon := partial "utilities/GetThemeIcon.html" (dict "id" "downloadIcon" "default" "fas download") -}} {{ partial "assets/button.html" (dict + "page" $ "href" . "icon" $downloadIcon "icon-class" "fa-fw" diff --git a/layouts/_partials/page/tags.html b/layouts/_partials/page/tags.html index ba5e5ae97..1ff5a1626 100644 --- a/layouts/_partials/page/tags.html +++ b/layouts/_partials/page/tags.html @@ -4,7 +4,7 @@
{{ range (.GetTerms "tags") -}} {{- $url := .Page.RelPermalink -}} - {{ partial "assets/button.html" (dict "href" $url "title" .LinkTitle "color" "light" "button-size" "sm") }} + {{ partial "assets/button.html" (dict "page" $ "href" $url "title" .LinkTitle "color" "light" "button-size" "sm") }} {{ end -}}
@@ -13,7 +13,7 @@
{{ range (.GetTerms "tags") -}} {{- $url := .Page.RelPermalink -}} - {{ partial "assets/button.html" (dict "href" $url "title" .LinkTitle "color" "primary" "button-size" "sm" "outline" "true") }} + {{ partial "assets/button.html" (dict "page" $ "href" $url "title" .LinkTitle "color" "primary" "button-size" "sm" "outline" "true") }} {{ end -}}
diff --git a/layouts/_shortcodes/alert.html b/layouts/_shortcodes/alert.html index b8ad2b839..d05f4a77c 100644 --- a/layouts/_shortcodes/alert.html +++ b/layouts/_shortcodes/alert.html @@ -32,7 +32,7 @@ {{ $color = "info" }} {{ end }} {{ with $icon }} - {{ $icon = partial "assets/icon.html" (dict "icon" . "class" "fa-2x fa-fw") }} + {{ $icon = partial "assets/icon.html" (dict "page" $.Page "icon" . "class" "fa-2x fa-fw") }} {{ end }} {{ $body := trim .Inner " \r\n" -}} diff --git a/layouts/_shortcodes/button.html b/layouts/_shortcodes/button.html index ae61e8ed1..34c1d42bb 100644 --- a/layouts/_shortcodes/button.html +++ b/layouts/_shortcodes/button.html @@ -35,7 +35,8 @@ {{/* Main code */}} {{ if not $error }} - {{- $output := partial "assets/button.html" (dict + {{- $output := partial "assets/button.html" (dict + "page" .Page "link-type" (or $args.linkType $args.type) "title" $title "button-size" (or $args.buttonSize $args.size) diff --git a/layouts/_shortcodes/release.html b/layouts/_shortcodes/release.html index 9fed26368..2ee0ca187 100644 --- a/layouts/_shortcodes/release.html +++ b/layouts/_shortcodes/release.html @@ -57,7 +57,8 @@ {{ partial "assets/link.html" (dict "href" $href "text" $title "page" .Page) }} {{ else }} {{- if not $args.inline }}
{{ end -}} - {{- partial "assets/button.html" (dict + {{- partial "assets/button.html" (dict + "page" .Page "title" $title "href" $href "color" $color diff --git a/layouts/_shortcodes/tooltip.html b/layouts/_shortcodes/tooltip.html index 036cd6778..14f1d6a2f 100644 --- a/layouts/_shortcodes/tooltip.html +++ b/layouts/_shortcodes/tooltip.html @@ -30,7 +30,8 @@ {{/* Main code */}} {{ if not $error }}
- {{- partial "assets/button.html" (dict + {{- partial "assets/button.html" (dict + "page" .Page "link-type" "link" "title" $title "color" $args.color diff --git a/layouts/form/single.html b/layouts/form/single.html index 670c07407..fa6a7aea3 100644 --- a/layouts/form/single.html +++ b/layouts/form/single.html @@ -5,7 +5,7 @@
- {{ partial "assets/icon.html" (dict "icon" $formIcon "class" "fa-10x") }} + {{ partial "assets/icon.html" (dict "page" .Page "icon" $formIcon "class" "fa-10x") }}

{{ .Title }}

From f0c035bcbb91b52adce6733aa0e669480f1e442e Mon Sep 17 00:00:00 2001 From: Mark Dumay <61946753+markdumay@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:49:50 +0200 Subject: [PATCH 2/5] feat: emit plain-text item descriptions in RSS feeds Override Hugo's embedded RSS template (v0.164.0) with a byte-compatible copy that changes only the item description payload: the frontmatter description when set, else a plainified (entity-decoded, XML-escaped) summary. Embedding rendered HTML forced a per-output-format content render of every feed-listed page in the feed page's ambient context, making feed bytes depend on render order: three feeds differed between otherwise identical builds. With plain-text descriptions the feeds are deterministic (run-vs-run byte-identical, former allowlist included) and most RSS-triggered content variant renders disappear; only feed-listed pages without a frontmatter description still render content for their summary ('with' short-circuits the fallback). Co-Authored-By: Claude Fable 5 --- layouts/rss.xml | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 layouts/rss.xml diff --git a/layouts/rss.xml b/layouts/rss.xml new file mode 100644 index 000000000..9e8699183 --- /dev/null +++ b/layouts/rss.xml @@ -0,0 +1,80 @@ +{{/* + Copyright © 2022 - 2026 The Hinode Team / Mark Dumay. All rights reserved. + Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file. + Visit gethinode.com/license for more details. + + Override of Hugo's embedded RSS template (v0.164.0). Byte-compatible with the + embedded template except for the item : it emits plain text — the + frontmatter description when set, else a plainified summary — instead of the + page's rendered HTML. Embedding rendered HTML forces a per-output-format + content render whose ambient context is the feed page, which made feed bytes + depend on render order (non-deterministic builds). Plain text strips the + order-sensitive markup (classes, generated element ids) so feeds are stable. +*/}} +{{- $authorEmail := "" }} +{{- with site.Params.author }} + {{- if reflect.IsMap . }} + {{- with .email }} + {{- $authorEmail = . }} + {{- end }} + {{- end }} +{{- end }} + +{{- $authorName := "" }} +{{- with site.Params.author }} + {{- if reflect.IsMap . }} + {{- with .name }} + {{- $authorName = . }} + {{- end }} + {{- else }} + {{- $authorName = . }} + {{- end }} +{{- end }} + +{{- $pctx := . }} +{{- if .IsHome }}{{ $pctx = .Site }}{{ end }} +{{- $pages := slice }} +{{- if or $.IsHome $.IsSection }} + {{- $pages = $pctx.RegularPages }} +{{- else }} + {{- $pages = $pctx.Pages }} +{{- end }} +{{- $limit := .Site.Config.Services.RSS.Limit }} +{{- if ge $limit 1 }} + {{- $pages = $pages | first $limit }} +{{- end }} +{{- printf "" | safeHTML }} + + + {{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }} + {{ .Permalink }} + Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{ . }} {{ end }}{{ end }}on {{ .Site.Title }} + Hugo + {{ site.Language.Locale }} + {{ with $authorEmail }} + {{ . }}{{ with $authorName }} ({{ . }}){{ end }} + {{ end }} + {{ with $authorEmail }} + {{ . }}{{ with $authorName }} ({{ . }}){{ end }} + {{ end }} + {{ with .Site.Copyright }} + {{ . }} + {{ end }} + {{ if not .Date.IsZero }} + {{ (index $pages.ByLastmod.Reverse 0).Lastmod.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} + {{ end }} + {{- with .OutputFormats.Get "RSS" }} + {{ printf "" .Permalink .MediaType | safeHTML }} + {{- end }} + {{- range $pages }} + + {{ .Title }} + {{ .Permalink }} + {{ .PublishDate.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} + {{- with $authorEmail }}{{ . }}{{ with $authorName }} ({{ . }}){{ end }}{{ end }} + {{ .Permalink }} + {{ with .Description }}{{ . | transform.XMLEscape | safeHTML }}{{ else }}{{ .Summary | plainify | htmlUnescape | transform.XMLEscape | safeHTML }}{{ end }} + + {{- end }} + + From ef0545b8bea0fc015e1ddb9c1ed327988ba6aea9 Mon Sep 17 00:00:00 2001 From: Mark Dumay <61946753+markdumay@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:42:04 +0200 Subject: [PATCH 3/5] fix: thread the owning page into shortcode UniqueID calls Threads 'page' into the 9 hinode shortcode UniqueID call sites that omitted it (table.html already threads it). Anchors id counters to the owning page regardless of which rendering context materializes the content, so body ids stay page-local (1..n) under render-once. Folded into the flip slice: the one-time UID renumbering relative to the double-render baseline is this PR's expected diff (see the D8 evidence file). Co-Authored-By: Claude Fable 5 --- exampleSite/hugo_stats.json | 100 +++++++++++++----------- layouts/_shortcodes/accordion-item.html | 2 +- layouts/_shortcodes/accordion.html | 2 +- layouts/_shortcodes/carousel.html | 2 +- layouts/_shortcodes/docs.html | 2 +- layouts/_shortcodes/file.html | 2 +- layouts/_shortcodes/nav-item.html | 2 +- layouts/_shortcodes/nav.html | 2 +- layouts/_shortcodes/navbar.html | 2 +- layouts/_shortcodes/toast.html | 2 +- 10 files changed, 65 insertions(+), 53 deletions(-) diff --git a/exampleSite/hugo_stats.json b/exampleSite/hugo_stats.json index 7d5631a8e..e86b1ea8c 100644 --- a/exampleSite/hugo_stats.json +++ b/exampleSite/hugo_stats.json @@ -560,10 +560,12 @@ "multi-file-collapse-2", "multi-file-collapse-4", "multi-file-collapse-5", - "multi-file-collapse-UID-1", + "multi-file-collapse-UID-10", "multi-file-collapse-UID-2", "multi-file-collapse-UID-3", - "multi-file-collapse-UID-5", + "multi-file-collapse-UID-4", + "multi-file-collapse-UID-6", + "multi-file-collapse-UID-8", "mx-auto", "mx-md-2", "my-4", @@ -830,14 +832,14 @@ "about", "absolute-sizing", "accordion", - "accordion-UID-1", - "accordion-UID-1-heading-0", - "accordion-UID-1-heading-1", - "accordion-UID-1-item-0", - "accordion-UID-1-item-1", - "accordion-UID-2", - "accordion-UID-2-heading-0", - "accordion-UID-2-item-0", + "accordion-UID-3", + "accordion-UID-3-heading-0", + "accordion-UID-3-heading-1", + "accordion-UID-3-item-0", + "accordion-UID-3-item-1", + "accordion-UID-4", + "accordion-UID-4-heading-0", + "accordion-UID-4-item-0", "accordion-always-open", "accordion-always-open-heading-0", "accordion-always-open-heading-1", @@ -941,10 +943,12 @@ "body-file-collapse-2", "body-file-collapse-4", "body-file-collapse-5", - "body-file-collapse-UID-1", + "body-file-collapse-UID-10", "body-file-collapse-UID-2", "body-file-collapse-UID-3", - "body-file-collapse-UID-5", + "body-file-collapse-UID-4", + "body-file-collapse-UID-6", + "body-file-collapse-UID-8", "bordered-and-pulled-icons", "brand-logo", "brand-text", @@ -982,8 +986,8 @@ "carousel-3x1", "carousel-3x2", "carousel-4x3", - "carousel-UID-1", - "carousel-UID-2", + "carousel-UID-3", + "carousel-UID-4", "carousel-original", "carousel-portrait-3x2", "category-filter", @@ -1058,10 +1062,11 @@ "dropdown-align-center-1", "dropdown-align-end-1", "dropdown-callout-1", - "dropdown-nav-UID-1", - "dropdown-nav-UID-2", - "dropdown-nav-UID-3", "dropdown-nav-UID-4", + "dropdown-nav-UID-5", + "dropdown-nav-UID-6", + "dropdown-nav-UID-7", + "dropdown-nav-UID-8", "dropdown-panel-UID-1", "dropdown-panel-UID-2", "dropdown-panel-UID-3", @@ -1162,10 +1167,12 @@ "footer-file-collapse-2", "footer-file-collapse-4", "footer-file-collapse-5", - "footer-file-collapse-UID-1", + "footer-file-collapse-UID-10", "footer-file-collapse-UID-2", "footer-file-collapse-UID-3", - "footer-file-collapse-UID-5", + "footer-file-collapse-UID-4", + "footer-file-collapse-UID-6", + "footer-file-collapse-UID-8", "fourth-post", "frontmatter-configuration", "full-width-preview", @@ -1261,37 +1268,42 @@ "more-type", "named-link", "nav", - "nav-UID-1-0", - "nav-UID-1-1", - "nav-UID-1-2", - "nav-UID-1-btn-0", - "nav-UID-1-btn-1", - "nav-UID-1-btn-2", - "nav-UID-2-0", - "nav-UID-2-1", - "nav-UID-2-2", - "nav-UID-2-btn-0", - "nav-UID-2-btn-1", - "nav-UID-2-btn-2", - "nav-UID-3-0", - "nav-UID-3-1", - "nav-UID-3-2", - "nav-UID-3-btn-0", - "nav-UID-3-btn-1", - "nav-UID-3-btn-2", "nav-UID-4-0", "nav-UID-4-1", - "nav-UID-4-2", "nav-UID-4-btn-0", "nav-UID-4-btn-1", - "nav-UID-4-btn-2", + "nav-UID-5-0", + "nav-UID-5-1", + "nav-UID-5-2", + "nav-UID-5-btn-0", + "nav-UID-5-btn-1", + "nav-UID-5-btn-2", + "nav-UID-6-0", + "nav-UID-6-1", + "nav-UID-6-2", + "nav-UID-6-btn-0", + "nav-UID-6-btn-1", + "nav-UID-6-btn-2", + "nav-UID-7-0", + "nav-UID-7-1", + "nav-UID-7-2", + "nav-UID-7-btn-0", + "nav-UID-7-btn-1", + "nav-UID-7-btn-2", + "nav-UID-8-0", + "nav-UID-8-1", + "nav-UID-8-2", + "nav-UID-8-btn-0", + "nav-UID-8-btn-1", + "nav-UID-8-btn-2", "nav-align-center-1", "nav-align-end-1", "nav-callout-1", - "nav-nav-UID-1", - "nav-nav-UID-2", - "nav-nav-UID-3", "nav-nav-UID-4", + "nav-nav-UID-5", + "nav-nav-UID-6", + "nav-nav-UID-7", + "nav-nav-UID-8", "nav-panel-UID-1", "nav-panel-UID-2", "nav-panel-UID-3", @@ -1519,8 +1531,8 @@ "toast-copied-code-message", "toast-example-1", "toast-example-2", - "toast-message-UID-1", - "toast-message-UID-2", + "toast-message-UID-3", + "toast-message-UID-4", "toast-message-email-4", "toc-collapse", "toc-collapse-items", diff --git a/layouts/_shortcodes/accordion-item.html b/layouts/_shortcodes/accordion-item.html index 75b785df4..bfa781a5f 100644 --- a/layouts/_shortcodes/accordion-item.html +++ b/layouts/_shortcodes/accordion-item.html @@ -33,7 +33,7 @@ {{- if not $parent -}} {{- $parent = .Parent.Scratch.Get "resolved-id" -}} {{- if not $parent -}} - {{- $parent = partial "utilities/UniqueID.html" (dict "prefix" "accordion") -}} + {{- $parent = partial "utilities/UniqueID.html" (dict "prefix" "accordion" "page" $.Page) -}} {{- .Parent.Scratch.Set "resolved-id" $parent -}} {{- end -}} {{- end -}} diff --git a/layouts/_shortcodes/accordion.html b/layouts/_shortcodes/accordion.html index 36b663d00..42eb3bb3e 100644 --- a/layouts/_shortcodes/accordion.html +++ b/layouts/_shortcodes/accordion.html @@ -22,7 +22,7 @@ {{- if not $id -}} {{- $id = .Scratch.Get "resolved-id" -}} {{- if not $id -}} - {{- $id = partial "utilities/UniqueID.html" (dict "prefix" "accordion") -}} + {{- $id = partial "utilities/UniqueID.html" (dict "prefix" "accordion" "page" $.Page) -}} {{- .Scratch.Set "resolved-id" $id -}} {{- end -}} {{- end -}} diff --git a/layouts/_shortcodes/carousel.html b/layouts/_shortcodes/carousel.html index 3eeb0ec2e..7ed6c1f0b 100644 --- a/layouts/_shortcodes/carousel.html +++ b/layouts/_shortcodes/carousel.html @@ -18,7 +18,7 @@ {{- end -}} {{/* Initialize local arguments */}} -{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "carousel")) -}} +{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "carousel" "page" .Page)) -}} {{ $inner := .Scratch.Get "inner" }} {{ $input := trim .Inner " \r\n" }} {{ if $input }} diff --git a/layouts/_shortcodes/docs.html b/layouts/_shortcodes/docs.html index 7fbe155e2..cd5c6f8c7 100644 --- a/layouts/_shortcodes/docs.html +++ b/layouts/_shortcodes/docs.html @@ -30,7 +30,7 @@ {{- end -}} {{/* Initialize local arguments */}} -{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "docs-collapse")) -}} +{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "docs-collapse" "page" .Page)) -}} {{- $basePath := .Site.Params.docs.basePath -}} {{- $file := $args.file -}} {{- if hasPrefix $file "./" -}} diff --git a/layouts/_shortcodes/file.html b/layouts/_shortcodes/file.html index 7ba1a063f..a5c45c94a 100644 --- a/layouts/_shortcodes/file.html +++ b/layouts/_shortcodes/file.html @@ -50,7 +50,7 @@ {{- $extension := strings.TrimLeft "." (path.Ext $file) }} {{- $lang := $args.lang | default $extension -}} -{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "file-collapse")) -}} +{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "file-collapse" "page" .Page)) -}} {{/* Main code */}} {{- if not $error -}} diff --git a/layouts/_shortcodes/nav-item.html b/layouts/_shortcodes/nav-item.html index 60aaabc3c..0b22623fb 100644 --- a/layouts/_shortcodes/nav-item.html +++ b/layouts/_shortcodes/nav-item.html @@ -26,7 +26,7 @@ {{- if not $parent -}} {{- $parent = .Parent.Scratch.Get "resolved-id" -}} {{- if not $parent -}} - {{- $parent = partial "utilities/UniqueID.html" (dict "prefix" "nav") -}} + {{- $parent = partial "utilities/UniqueID.html" (dict "prefix" "nav" "page" $.Page) -}} {{- .Parent.Scratch.Set "resolved-id" $parent -}} {{- end -}} {{- end -}} diff --git a/layouts/_shortcodes/nav.html b/layouts/_shortcodes/nav.html index 06f863d68..19afbbf4e 100644 --- a/layouts/_shortcodes/nav.html +++ b/layouts/_shortcodes/nav.html @@ -35,7 +35,7 @@ {{- if not $navID -}} {{- $navID = .Scratch.Get "resolved-id" -}} {{- if not $navID -}} - {{- $navID = partial "utilities/UniqueID.html" (dict "prefix" "nav") -}} + {{- $navID = partial "utilities/UniqueID.html" (dict "prefix" "nav" "page" $.Page) -}} {{- .Scratch.Set "resolved-id" $navID -}} {{- end -}} {{- end -}} diff --git a/layouts/_shortcodes/navbar.html b/layouts/_shortcodes/navbar.html index 8f4af6071..0bee522ea 100644 --- a/layouts/_shortcodes/navbar.html +++ b/layouts/_shortcodes/navbar.html @@ -21,7 +21,7 @@ {{- end -}} {{/* Initialize arguments */}} -{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "navbar-collapse")) -}} +{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "navbar-collapse" "page" .Page)) -}} {{ $page := .Page }} {{ if $args.path }}{{ $page = .Site.GetPage $args.path }}{{ end }} {{ if and $args.path (not $page) }} diff --git a/layouts/_shortcodes/toast.html b/layouts/_shortcodes/toast.html index 02e0b7a56..8ea37840b 100644 --- a/layouts/_shortcodes/toast.html +++ b/layouts/_shortcodes/toast.html @@ -21,7 +21,7 @@ {{ end }} {{/* Initialize local arguments */}} -{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "toast-message")) -}} +{{- $id := $args.id | default (partial "utilities/UniqueID.html" (dict "prefix" "toast-message" "page" .Page)) -}} {{ $message := trim .Inner " \r\n" | .Page.RenderString -}} {{ if not $message -}} From 78d00c5a847850381c19f591f28ee53bb3da4e95 Mon Sep 17 00:00:00 2001 From: Mark Dumay <61946753+markdumay@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:57:40 +0200 Subject: [PATCH 4/5] feat: serve page bodies from cached content Body layouts (body, docs/body, minimal/body, list) render .Content instead of re-rendering .RawContent through utilities/ProcessContent, removing one full shortcode/Goldmark pass per page; form/single.html keeps ProcessContent as it renders a fragment. The head stylesheet consumer materializes .Content explicitly and reads the module dependencies from the page Scratch and Store, mirroring footer/scripts.html. The exampleSite drops the deprecated purgeHTMLComments parameter in favour of Hugo's ignoreLogs, and the determinism script no longer tolerates any diff between two builds. Co-Authored-By: Claude Fable 5 --- exampleSite/config/_default/hugo.toml | 9 +- exampleSite/config/_default/params.toml | 1 - exampleSite/hugo_stats.json | 108 ++++++++++-------------- layouts/_partials/head/head.html | 7 ++ layouts/body.html | 2 +- layouts/docs/body.html | 2 +- layouts/list.html | 2 +- layouts/minimal/body.html | 2 +- scripts/check-build-determinism.sh | 42 ++------- 9 files changed, 70 insertions(+), 105 deletions(-) diff --git a/exampleSite/config/_default/hugo.toml b/exampleSite/config/_default/hugo.toml index dc48a643b..e3fe4a5b8 100644 --- a/exampleSite/config/_default/hugo.toml +++ b/exampleSite/config/_default/hugo.toml @@ -13,9 +13,14 @@ enableInlineShortcodes = true # prevent build failures when using Hugo's Instagram shortcode due to deprecated Instagram API. # See https://github.com/gohugoio/hugo/issues/7228#issuecomment-714490456 # the transitional 'warn-missing-page-argument' entry suppresses the fallback warning raised by -# mod-blocks <= v2.1.4, which calls the section-title / image partials without a page argument; -# remove it once the exampleSite picks up the mod-blocks release that threads the page explicitly. +# mod-blocks <= v2.2.0, which still calls the section-title / image partials without a page +# argument in several components (hero, faq, testimonials, preview, and others); remove it once +# the exampleSite picks up a mod-blocks release that threads the page into every call. ignoreErrors = ["error-remote-getjson", "warn-preview-restricted", "warn-missing-page-argument"] +# the site's content uses HTML comments (markdownlint directives); with Goldmark's unsafe +# rendering disabled these trigger 'warning-goldmark-raw-html' and render as harmless +# '' placeholders, which the minifier strips from production output. +ignoreLogs = ['warning-goldmark-raw-html'] timeout = "180s" languageCode = "en-us" diff --git a/exampleSite/config/_default/params.toml b/exampleSite/config/_default/params.toml index 951d88f84..d877a6cb6 100644 --- a/exampleSite/config/_default/params.toml +++ b/exampleSite/config/_default/params.toml @@ -79,7 +79,6 @@ [debugging] showJS = false showSCSS = false - purgeHTMLComments = true # prevents a Goldmark warning when processing HTML comments (as used by markdownlint) includeSVGOrigin = true [docs] diff --git a/exampleSite/hugo_stats.json b/exampleSite/hugo_stats.json index e86b1ea8c..cffc4eba2 100644 --- a/exampleSite/hugo_stats.json +++ b/exampleSite/hugo_stats.json @@ -560,12 +560,10 @@ "multi-file-collapse-2", "multi-file-collapse-4", "multi-file-collapse-5", - "multi-file-collapse-UID-10", + "multi-file-collapse-UID-1", "multi-file-collapse-UID-2", "multi-file-collapse-UID-3", - "multi-file-collapse-UID-4", - "multi-file-collapse-UID-6", - "multi-file-collapse-UID-8", + "multi-file-collapse-UID-5", "mx-auto", "mx-md-2", "my-4", @@ -832,14 +830,14 @@ "about", "absolute-sizing", "accordion", - "accordion-UID-3", - "accordion-UID-3-heading-0", - "accordion-UID-3-heading-1", - "accordion-UID-3-item-0", - "accordion-UID-3-item-1", - "accordion-UID-4", - "accordion-UID-4-heading-0", - "accordion-UID-4-item-0", + "accordion-UID-1", + "accordion-UID-1-heading-0", + "accordion-UID-1-heading-1", + "accordion-UID-1-item-0", + "accordion-UID-1-item-1", + "accordion-UID-2", + "accordion-UID-2-heading-0", + "accordion-UID-2-item-0", "accordion-always-open", "accordion-always-open-heading-0", "accordion-always-open-heading-1", @@ -903,8 +901,6 @@ "bi-box-arrow-up-right", "bi-chevron-left", "bi-chevron-right", - "bi-display", - "bi-download", "bi-exclamation", "bi-exclamation-triangle", "bi-facebook", @@ -920,7 +916,6 @@ "bi-linkedin", "bi-list-ul", "bi-moon-stars", - "bi-phone", "bi-pinterest", "bi-quote", "bi-rocket", @@ -928,7 +923,6 @@ "bi-share", "bi-sort-down", "bi-sun", - "bi-tablet", "bi-three-dots", "bi-trash", "bienvenue-sur-hinode", @@ -943,12 +937,10 @@ "body-file-collapse-2", "body-file-collapse-4", "body-file-collapse-5", - "body-file-collapse-UID-10", + "body-file-collapse-UID-1", "body-file-collapse-UID-2", "body-file-collapse-UID-3", - "body-file-collapse-UID-4", - "body-file-collapse-UID-6", - "body-file-collapse-UID-8", + "body-file-collapse-UID-5", "bordered-and-pulled-icons", "brand-logo", "brand-text", @@ -986,8 +978,8 @@ "carousel-3x1", "carousel-3x2", "carousel-4x3", - "carousel-UID-3", - "carousel-UID-4", + "carousel-UID-1", + "carousel-UID-2", "carousel-original", "carousel-portrait-3x2", "category-filter", @@ -1062,11 +1054,10 @@ "dropdown-align-center-1", "dropdown-align-end-1", "dropdown-callout-1", + "dropdown-nav-UID-1", + "dropdown-nav-UID-2", + "dropdown-nav-UID-3", "dropdown-nav-UID-4", - "dropdown-nav-UID-5", - "dropdown-nav-UID-6", - "dropdown-nav-UID-7", - "dropdown-nav-UID-8", "dropdown-panel-UID-1", "dropdown-panel-UID-2", "dropdown-panel-UID-3", @@ -1085,7 +1076,6 @@ "examples", "external-link", "fa-address-card", - "fa-paper-plane", "fab-bootstrap", "fab-facebook", "fab-github", @@ -1110,7 +1100,6 @@ "fas-6", "fas-arrow-right", "fas-arrows-rotate", - "fas-arrows-to-dot", "fas-ban", "fas-basketball", "fas-bell", @@ -1126,8 +1115,6 @@ "fas-heart", "fas-link", "fas-magnifying-glass", - "fas-magnifying-glass-minus", - "fas-magnifying-glass-plus", "fas-mug-saucer", "fas-person-skating", "fas-person-skiing", @@ -1167,12 +1154,10 @@ "footer-file-collapse-2", "footer-file-collapse-4", "footer-file-collapse-5", - "footer-file-collapse-UID-10", + "footer-file-collapse-UID-1", "footer-file-collapse-UID-2", "footer-file-collapse-UID-3", - "footer-file-collapse-UID-4", - "footer-file-collapse-UID-6", - "footer-file-collapse-UID-8", + "footer-file-collapse-UID-5", "fourth-post", "frontmatter-configuration", "full-width-preview", @@ -1268,42 +1253,37 @@ "more-type", "named-link", "nav", + "nav-UID-1-0", + "nav-UID-1-1", + "nav-UID-1-2", + "nav-UID-1-btn-0", + "nav-UID-1-btn-1", + "nav-UID-1-btn-2", + "nav-UID-2-0", + "nav-UID-2-1", + "nav-UID-2-2", + "nav-UID-2-btn-0", + "nav-UID-2-btn-1", + "nav-UID-2-btn-2", + "nav-UID-3-0", + "nav-UID-3-1", + "nav-UID-3-2", + "nav-UID-3-btn-0", + "nav-UID-3-btn-1", + "nav-UID-3-btn-2", "nav-UID-4-0", "nav-UID-4-1", + "nav-UID-4-2", "nav-UID-4-btn-0", "nav-UID-4-btn-1", - "nav-UID-5-0", - "nav-UID-5-1", - "nav-UID-5-2", - "nav-UID-5-btn-0", - "nav-UID-5-btn-1", - "nav-UID-5-btn-2", - "nav-UID-6-0", - "nav-UID-6-1", - "nav-UID-6-2", - "nav-UID-6-btn-0", - "nav-UID-6-btn-1", - "nav-UID-6-btn-2", - "nav-UID-7-0", - "nav-UID-7-1", - "nav-UID-7-2", - "nav-UID-7-btn-0", - "nav-UID-7-btn-1", - "nav-UID-7-btn-2", - "nav-UID-8-0", - "nav-UID-8-1", - "nav-UID-8-2", - "nav-UID-8-btn-0", - "nav-UID-8-btn-1", - "nav-UID-8-btn-2", + "nav-UID-4-btn-2", "nav-align-center-1", "nav-align-end-1", "nav-callout-1", + "nav-nav-UID-1", + "nav-nav-UID-2", + "nav-nav-UID-3", "nav-nav-UID-4", - "nav-nav-UID-5", - "nav-nav-UID-6", - "nav-nav-UID-7", - "nav-nav-UID-8", "nav-panel-UID-1", "nav-panel-UID-2", "nav-panel-UID-3", @@ -1531,8 +1511,8 @@ "toast-copied-code-message", "toast-example-1", "toast-example-2", - "toast-message-UID-3", - "toast-message-UID-4", + "toast-message-UID-1", + "toast-message-UID-2", "toast-message-email-4", "toc-collapse", "toc-collapse-items", diff --git a/layouts/_partials/head/head.html b/layouts/_partials/head/head.html index 2202c41c2..d1079a4bd 100644 --- a/layouts/_partials/head/head.html +++ b/layouts/_partials/head/head.html @@ -19,7 +19,14 @@ {{ end }} {{ $page_modules := slice | append .Page.Params.modules }} + {{/* Module dependencies are registered in the page's Scratch and Store as a side effect of + content rendering (utilities/AddModule.html). The head renders before the body, so + materialize the content explicitly to make the read below contract-based rather than + an ordering accident. .Content is cached, so this is cheap: under render-once it is + the page's only body render. */}} + {{ $_ := .Page.Content }} {{ with .Scratch.Get "dependencies" }}{{ $page_modules = append $page_modules . | uniq }}{{ end }} + {{ with .Page.Store.Get "dependencies" }}{{ $page_modules = append $page_modules . | uniq }}{{ end }} {{- $modules := $config.optional | intersect $page_modules -}} {{- range $index, $mod := $modules -}} {{- $source := printf "scss/%s.scss" $mod -}} diff --git a/layouts/body.html b/layouts/body.html index 3d32f9c04..79b63255a 100644 --- a/layouts/body.html +++ b/layouts/body.html @@ -1,3 +1,3 @@ {{- partial "page/thumbnail.html" (dict "page" . "wrapper" "mb-5") -}} -{{ partial "utilities/ProcessContent" (dict "page" .Page "raw" .RawContent) }} +{{ .Content }} diff --git a/layouts/docs/body.html b/layouts/docs/body.html index db2bf07ff..68a09ae66 100644 --- a/layouts/docs/body.html +++ b/layouts/docs/body.html @@ -1 +1 @@ -{{ partial "utilities/ProcessContent" (dict "page" .Page "raw" .RawContent) }} +{{ .Content }} diff --git a/layouts/list.html b/layouts/list.html index 710804070..da0088008 100644 --- a/layouts/list.html +++ b/layouts/list.html @@ -1,7 +1,7 @@ {{ define "main" -}} {{- $breakpoint := partialCached "utilities/GetBreakpoint.html" site -}} {{- $padding := partial "utilities/GetPadding.html" -}} - {{- $content := partial "utilities/ProcessContent" (dict "page" .Page "raw" .RawContent) }} + {{- $content := .Content }} {{ if .Params.content_blocks }} diff --git a/layouts/minimal/body.html b/layouts/minimal/body.html index db2bf07ff..68a09ae66 100644 --- a/layouts/minimal/body.html +++ b/layouts/minimal/body.html @@ -1 +1 @@ -{{ partial "utilities/ProcessContent" (dict "page" .Page "raw" .RawContent) }} +{{ .Content }} diff --git a/scripts/check-build-determinism.sh b/scripts/check-build-determinism.sh index 34a181e95..9d3f50bac 100755 --- a/scripts/check-build-determinism.sh +++ b/scripts/check-build-determinism.sh @@ -14,14 +14,10 @@ # masquerade as a fast one, so page counts are checked explicitly. # 3. Compares both output trees with `diff -rq`. # -# Tolerated diffs (allowlist): a pre-existing intermittent `.Content` race in -# RSS-embedded HTML (accepted by the maintainer on 2026-07-15) may cause the -# following files to differ between otherwise identical builds: -# - en/index.xml -# - en/docs/blocks/index.xml -# - en/tags/block/index.xml -# Any other diff — or a missing/extra file, an ERROR line, or an unexpected -# page count — makes the script exit non-zero. +# Any diff — or a missing/extra file, an ERROR line, or an unexpected page +# count — makes the script exit non-zero. Since the render-once flip, page +# bodies, RSS feeds, and the search index all derive from the same single +# content render, so two builds must be fully byte-identical (no allowlist). # # Usage (from the repository root, after `pnpm install` and `pnpm mod:vendor`): # scripts/check-build-determinism.sh @@ -36,11 +32,6 @@ cd "$ROOT" export PATH="$ROOT/node_modules/.bin:$PATH" EXPECTED_PAGES="98 26 24" # EN FR NL -ALLOWLIST=( - "en/index.xml" - "en/docs/blocks/index.xml" - "en/tags/block/index.xml" -) WORKDIR="$(mktemp -d)" trap 'rm -rf "$WORKDIR"' EXIT @@ -96,29 +87,12 @@ fi unexpected=0 while IFS= read -r line; do [ -z "$line" ] && continue - allowed="" - case "$line" in - Files\ *\ differ) - for entry in "${ALLOWLIST[@]}"; do - case "$line" in - "Files $WORKDIR/snapshot-1/$entry and $WORKDIR/snapshot-2/$entry differ") - allowed="yes" - break - ;; - esac - done - ;; - esac - if [ -n "$allowed" ]; then - echo " tolerated (RSS .Content race allowlist): $line" - else - echo " UNEXPECTED: $line" - unexpected=1 - fi + echo " UNEXPECTED: $line" + unexpected=1 done <"$WORKDIR/diff.txt" if [ "$unexpected" -ne 0 ]; then - echo "FAIL: builds are not byte-identical outside the allowlist" + echo "FAIL: builds are not byte-identical" fail=1 fi @@ -127,4 +101,4 @@ if [ "$fail" -ne 0 ]; then exit 1 fi -echo "RESULT: PASS — two consecutive builds are byte-identical (allowlist excepted)" +echo "RESULT: PASS — two consecutive builds are byte-identical" From f272b8906643795dbcead8c288df77f38240ffbb Mon Sep 17 00:00:00 2001 From: Mark Dumay <61946753+markdumay@users.noreply.github.com> Date: Thu, 16 Jul 2026 16:02:28 +0200 Subject: [PATCH 5/5] fix: update mod-blocks and mod-mermaid to page-threaded releases mod-blocks v2.2.2 and mod-mermaid v5.0.2 register icons and UIDs on the owning page; required for sprite integrity under render-once bodies. Co-Authored-By: Claude Fable 5 --- exampleSite/hugo_stats.json | 6 ++++++ go.mod | 4 ++-- go.sum | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/exampleSite/hugo_stats.json b/exampleSite/hugo_stats.json index cffc4eba2..ba4481331 100644 --- a/exampleSite/hugo_stats.json +++ b/exampleSite/hugo_stats.json @@ -901,6 +901,7 @@ "bi-box-arrow-up-right", "bi-chevron-left", "bi-chevron-right", + "bi-display", "bi-exclamation", "bi-exclamation-triangle", "bi-facebook", @@ -916,6 +917,7 @@ "bi-linkedin", "bi-list-ul", "bi-moon-stars", + "bi-phone", "bi-pinterest", "bi-quote", "bi-rocket", @@ -923,6 +925,7 @@ "bi-share", "bi-sort-down", "bi-sun", + "bi-tablet", "bi-three-dots", "bi-trash", "bienvenue-sur-hinode", @@ -1100,6 +1103,7 @@ "fas-6", "fas-arrow-right", "fas-arrows-rotate", + "fas-arrows-to-dot", "fas-ban", "fas-basketball", "fas-bell", @@ -1115,6 +1119,8 @@ "fas-heart", "fas-link", "fas-magnifying-glass", + "fas-magnifying-glass-minus", + "fas-magnifying-glass-plus", "fas-mug-saucer", "fas-person-skating", "fas-person-skiing", diff --git a/go.mod b/go.mod index c7db3a7cc..944e9e0d6 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/FortAwesome/Font-Awesome v0.0.0-20260715180930-14c65a3747d0 // indirect github.com/airbnb/lottie-web v5.13.0+incompatible // indirect - github.com/gethinode/mod-blocks/v2 v2.2.0 // indirect + github.com/gethinode/mod-blocks/v2 v2.2.2 // indirect github.com/gethinode/mod-bootstrap v1.3.7 // indirect github.com/gethinode/mod-csp v1.0.12 // indirect github.com/gethinode/mod-flexsearch/v5 v5.0.2 // indirect @@ -14,7 +14,7 @@ require ( github.com/gethinode/mod-katex v1.1.6 // indirect github.com/gethinode/mod-leaflet/v3 v3.1.1 // indirect github.com/gethinode/mod-lottie/v3 v3.0.2 // indirect - github.com/gethinode/mod-mermaid/v5 v5.0.1 // indirect + github.com/gethinode/mod-mermaid/v5 v5.0.2 // indirect github.com/gethinode/mod-simple-datatables/v4 v4.1.0 // indirect github.com/gethinode/mod-utils/v6 v6.6.0 // indirect github.com/nextapps-de/flexsearch v0.0.0-20260529083235-f7ed963096a0 // indirect diff --git a/go.sum b/go.sum index 5668e15ee..a6b7b4f45 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/airbnb/lottie-web v5.13.0+incompatible h1:plBV5Uq/F1kK0EC61Hr0cBGReI9 github.com/airbnb/lottie-web v5.13.0+incompatible/go.mod h1:nTss557UK9FGnp8QYlCMO29tjUHwbdAHG/DprbGfHGE= github.com/gethinode/mod-blocks/v2 v2.2.0 h1:sIRH7R7MYvqVECByJEuopVgzUCOa+iOEYOFCIouo5A0= github.com/gethinode/mod-blocks/v2 v2.2.0/go.mod h1:z+0Rg+I0naJf7VOy9dDuo8FX1dB5bPuMmbWT1QmBFhg= +github.com/gethinode/mod-blocks/v2 v2.2.2 h1:8CZkdenBGUQ2O6zMdlD+UHG5cjCOVxIG0UfBagSFWog= +github.com/gethinode/mod-blocks/v2 v2.2.2/go.mod h1:Kt8QjKpgozmxGj0dX20f0i8ZdBVaO1jw+tbZwJUl7yE= github.com/gethinode/mod-bootstrap v1.3.7 h1:rbjOg//q7dbsM+TkDQLsyk9LKv93D1RUjtcSkvV55UU= github.com/gethinode/mod-bootstrap v1.3.7/go.mod h1:CxrYCFzKtBMz3YWG5i/d5jHKCgvUo60NFcCmz2mxCjQ= github.com/gethinode/mod-csp v1.0.12 h1:6CaIH3IBn92lcwMFdYPmmWsPKq+VZ6n9Po8FI26jLJc= @@ -26,6 +28,8 @@ github.com/gethinode/mod-lottie/v3 v3.0.2 h1:PJ9BB5s+oli2D5i9apcWu8AowtfyNVb7VAc github.com/gethinode/mod-lottie/v3 v3.0.2/go.mod h1:QnNRtZPSwl6x7acJbR4jHNhNNRxbwVv0XsnD1hFcsro= github.com/gethinode/mod-mermaid/v5 v5.0.1 h1:heGJ9i3rDXAh+qU8N0jSEPhVGOsQwxLpNmB+h1FhTg8= github.com/gethinode/mod-mermaid/v5 v5.0.1/go.mod h1:3M0XrI6Ginj5EIbXy1xOymv3KsfPuBhD07FEPz1SikI= +github.com/gethinode/mod-mermaid/v5 v5.0.2 h1:OmpgjPcSlm7lXpcRDKkZbzklG/3a9QurrqsdkGMDdGQ= +github.com/gethinode/mod-mermaid/v5 v5.0.2/go.mod h1:rrCnPe+gLH83GpMm5uA/SeapZcNBj65jcJVLyXtsXPU= github.com/gethinode/mod-simple-datatables/v4 v4.1.0 h1:AtEtLH9RoAEIpElg0k6UkVlHmiBc4Df3NCCUfBtmktU= github.com/gethinode/mod-simple-datatables/v4 v4.1.0/go.mod h1:jRHoX20bUiaVg7UtKzMjfHQjd5M6WZ8hAeVqA3TKwTA= github.com/gethinode/mod-utils/v6 v6.6.0 h1:b+xpvPUqDKcQr1LUU4YKqtr7zIpzZ7zxCrlpLtlyr5Y=