Compare commits

...

3 Commits

Author SHA1 Message Date
0d1e2e80eb Add fingerprinting and integrity checks to generated HTML
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2026-05-18 21:28:38 -07:00
19550ef1b2 Use Hugo's partial-returning where possible
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2026-05-18 21:15:19 -07:00
2032e1cdc2 Update theme with .Scratch -> .Store deprecation
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
2026-05-18 21:05:45 -07:00
20 changed files with 82 additions and 88 deletions

View File

@@ -1,4 +1,4 @@
{{- .Page.Scratch.SetInMap "definedSections" (printf "#%s" .Anchor) true -}} {{- .Page.Store.SetInMap "definedSections" (printf "#%s" .Anchor) true -}}
<a href="#{{ .Anchor }}"> <a href="#{{ .Anchor }}">
<h{{ .Level }} id="{{ .Anchor }}"> <h{{ .Level }} id="{{ .Anchor }}">
{{- .Text | safeHTML -}} {{- .Text | safeHTML -}}

View File

@@ -7,7 +7,7 @@
{{- if $isSamePage -}} {{- if $isSamePage -}}
{{- $class = "same-page-link" -}} {{- $class = "same-page-link" -}}
{{- if index (.Page.Scratch.Get "definedSections") .Destination -}} {{- if index (.Page.Store.Get "definedSections") .Destination -}}
{{- $icon = "arrow-up" -}} {{- $icon = "arrow-up" -}}
{{- else -}} {{- else -}}
{{- /* Do not render "down" links because don't know how to distinguish unseen titles from paragraph links. */ -}} {{- /* Do not render "down" links because don't know how to distinguish unseen titles from paragraph links. */ -}}

View File

@@ -1,2 +1,2 @@
<link rel="preload" href="{{ .url }}" as="style" onload="this.onload=null;this.rel='stylesheet'" {{ .extra | safeHTMLAttr }}> <link rel="preload" href="{{ .url }}" as="style" onload="this.onload=null;this.rel='stylesheet'"{{ with .integrity }} integrity="{{ . }}"{{ end }}{{ with .extra }} {{ . | safeHTMLAttr }}{{ end }}>
<noscript><link rel="stylesheet" href="{{ .url }}"></noscript> <noscript><link rel="stylesheet" href="{{ .url }}"{{ with .integrity }} integrity="{{ . }}"{{ end }}></noscript>

View File

@@ -1,27 +1,26 @@
{{- $siteSourceUrl := site.Params.siteSourceUrl -}} {{- $siteSourceUrl := site.Params.siteSourceUrl -}}
{{- $submoduleLinks := site.Data.submodules -}} {{- $submoduleLinks := hugo.Data.submodules -}}
{{- $hostData := site.Data.hosts -}} {{- $hostData := hugo.Data.hosts -}}
{{- $scratch := .scratch -}}
{{- $lines := .lines -}} {{- $lines := .lines -}}
{{- $scratch.Set "bestLength" -1 -}} {{- $bestLength := -1 -}}
{{- $scratch.Set "bestUrl" (printf "%s/code/%s" $siteSourceUrl .path) -}} {{- $bestUrl := printf "%s/code/%s" $siteSourceUrl .path -}}
{{- $scratch.Set "bestPath" "" -}} {{- $bestPath := "" -}}
{{- $filePath := .path -}} {{- $filePath := .path -}}
{{- range $path, $url := $submoduleLinks -}} {{- range $path, $url := $submoduleLinks -}}
{{- $bestLength := $scratch.Get "bestLength" -}}
{{- if and (le $bestLength (len $path)) (hasPrefix $filePath $path) -}} {{- if and (le $bestLength (len $path)) (hasPrefix $filePath $path) -}}
{{- $scratch.Set "bestLength" (len $path) -}} {{- $bestLength = len $path -}}
{{- $scratch.Set "bestPath" $path -}} {{- $bestPath = $path -}}
{{- $scratch.Set "bestUrl" (printf "%s%s" $url (strings.TrimPrefix $path $filePath)) -}} {{- $bestUrl = printf "%s%s" $url (strings.TrimPrefix $path $filePath) -}}
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
{{- if .lines -}} {{- if .lines -}}
{{- /* If the user provided a line range, see if we can tack it on to the end of the link. */ -}} {{- /* If the user provided a line range, see if we can tack it on to the end of the link. */ -}}
{{- range $host, $data := $hostData -}} {{- range $host, $data := $hostData -}}
{{- if hasPrefix ($scratch.Get "bestUrl") $host -}} {{- if hasPrefix $bestUrl $host -}}
{{- with $data.linesSuffix -}} {{- with $data.linesSuffix -}}
{{- $scratch.Add "bestUrl" (printf . (index $lines 0) (index $lines 1)) -}} {{- $bestUrl = add $bestUrl (printf . (index $lines 0) (index $lines 1)) -}}
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
{{- return (dict "url" $bestUrl "basePath" $bestPath) -}}

View File

@@ -14,8 +14,8 @@
<!-- Fonts --> <!-- Fonts -->
{{ if not (.Site.Params.noCss) }} {{ if not (.Site.Params.noCss) }}
{{ $fonts := resources.Get "scss/fonts.scss" | css.Sass | resources.Minify }} {{ $fonts := resources.Get "scss/fonts.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $fonts.Permalink }}" media="screen"> <link rel="stylesheet" href="{{ $fonts.Permalink }}" integrity="{{ $fonts.Data.Integrity }}" media="screen">
{{ end }} {{ end }}
<!-- External CSS (normalize and KaTeX --> <!-- External CSS (normalize and KaTeX -->
@@ -30,22 +30,25 @@
{{ end -}} {{ end -}}
<!-- In-house CSS --> <!-- In-house CSS -->
{{ $style := resources.Get "scss/style.scss" | css.Sass | resources.Minify }} {{ $style := resources.Get "scss/style.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
{{ $sidenotes := resources.Get "scss/sidenotes.scss" | css.Sass | resources.Minify }} {{ $sidenotes := resources.Get "scss/sidenotes.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
{{ $code := resources.Get "scss/code.scss" | css.Sass | resources.Minify }} {{ $code := resources.Get "scss/code.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
{{ $icon := resources.Get "img/favicon.png" }} {{ $icon := resources.Get "img/favicon.png" | resources.Fingerprint }}
<style>.feather { display: inline !important; width: 10px; height: 10px; }</style> <style>.feather { display: inline !important; width: 10px; height: 10px; }</style>
<style>img { max-width: 70%; }</style> <style>img { max-width: 70%; }</style>
{{ if not (.Site.Params.noCss) }} {{ if not (.Site.Params.noCss) }}
<link rel="stylesheet" href="{{ $style.Permalink }}"> <link rel="stylesheet" href="{{ $style.Permalink }}" integrity="{{ $style.Data.Integrity }}">
{{ partial "defercss.html" (dict "url" $sidenotes.Permalink "extra" "") }} {{ partial "defercss.html" (dict "url" $sidenotes.Permalink "integrity" $sidenotes.Data.Integrity "extra" "") }}
{{ partial "defercss.html" (dict "url" $code.Permalink "extra" "") }} {{ partial "defercss.html" (dict "url" $code.Permalink "integrity" $code.Data.Integrity "extra" "") }}
{{ end }} {{ end }}
<link rel="icon" type="image/png" href="{{ $icon.Permalink }}"> <link rel="icon" type="image/png" href="{{ $icon.Permalink }}" integrity="{{ $icon.Data.Integrity }}">
{{ if .Params.custom_js }} {{ if .Params.custom_js }}
{{ range $customJs := .Params.custom_js }} {{ range $customJs := .Params.custom_js }}
<script src="{{ page.Resources.Get $customJs }}"></script> {{ with page.Resources.Get $customJs }}
{{ $customJsResource := . | resources.Fingerprint }}
<script src="{{ $customJsResource.Permalink }}" integrity="{{ $customJsResource.Data.Integrity }}"></script>
{{ end }}
{{ end }} {{ end }}
{{ end }} {{ end }}
@@ -66,14 +69,14 @@
<meta name="needs-latex"> <meta name="needs-latex">
<!-- Code to support the Bergamot JS widget --> <!-- Code to support the Bergamot JS widget -->
<script defer src="{{ .Site.Params.katexJsUrl }}" crossorigin="anonymous"></script> <script defer src="{{ .Site.Params.katexJsUrl }}" crossorigin="anonymous"></script>
{{ $katexComponentJs := resources.Get "js/katex-component.js" | resources.Minify }} {{ $katexComponentJs := resources.Get "js/katex-component.js" | resources.Minify | resources.Fingerprint }}
<script defer src="{{ $katexComponentJs.Permalink }}"></script> <script defer src="{{ $katexComponentJs.Permalink }}" integrity="{{ $katexComponentJs.Data.Integrity }}"></script>
<script defer src="{{ .Site.Params.bergamotJsUrl }}"></script> <script defer src="{{ .Site.Params.bergamotJsUrl }}"></script>
<script defer src="{{ .Site.Params.bergamotObjectLanguageJsUrl }}"></script> <script defer src="{{ .Site.Params.bergamotObjectLanguageJsUrl }}"></script>
{{ $bergamotHelpers := resources.Get "js/bergamot-helpers.js" | resources.Minify }} {{ $bergamotHelpers := resources.Get "js/bergamot-helpers.js" | resources.Minify | resources.Fingerprint }}
<script defer src="{{ $bergamotHelpers.Permalink }}"></script> <script defer src="{{ $bergamotHelpers.Permalink }}" integrity="{{ $bergamotHelpers.Data.Integrity }}"></script>
{{ $bergamotStyle := resources.Get "scss/bergamot.scss" | css.Sass | resources.Minify }} {{ $bergamotStyle := resources.Get "scss/bergamot.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
{{ partial "defercss.html" (dict "url" $bergamotStyle.Permalink "extra" "") }} {{ partial "defercss.html" (dict "url" $bergamotStyle.Permalink "integrity" $bergamotStyle.Data.Integrity "extra" "") }}
{{ if .Params.bergamot.render_presets }} {{ if .Params.bergamot.render_presets }}
{{ range $name, $rulefile := .Params.bergamot.render_presets }} {{ range $name, $rulefile := .Params.bergamot.render_presets }}
{{ $file := default (resources.Get $rulefile) (page.Resources.Get $rulefile) }} {{ $file := default (resources.Get $rulefile) (page.Resources.Get $rulefile) }}

View File

@@ -1,9 +1,9 @@
{{ if eq .from .to }} {{- $comment := "" -}}
{{ .scratch.Set "comment" (printf ", line %d" .from) }} {{- if eq .from .to -}}
{{ else }} {{- $comment = printf ", line %d" .from -}}
{{ if eq .from 0 }} {{- else if eq .from 0 -}}
{{ .scratch.Set "comment" (printf ", around line %d" .to) }} {{- $comment = printf ", around line %d" .to -}}
{{ else }} {{- else -}}
{{ .scratch.Set "comment" (printf ", lines %d through %d" .from .to) }} {{- $comment = printf ", lines %d through %d" .from .to -}}
{{ end }} {{- end -}}
{{ end }} {{- return $comment -}}

View File

@@ -1,8 +1,8 @@
{{- $term := index (.page.GetTerms "series") 0 -}} {{- $term := index (.page.GetTerms "series") 0 -}}
{{- $divider := $term.Params.divider -}} {{- $divider := $term.Params.divider -}}
{{- $name := .page.Title -}}
{{- if (and $divider (strings.Contains .page.Title $divider)) -}} {{- if (and $divider (strings.Contains .page.Title $divider)) -}}
{{- $rest := after 1 (split .page.Title $divider) -}} {{- $rest := after 1 (split .page.Title $divider) -}}
{{- .scratch.Set "name" (delimit $rest $divider) -}} {{- $name = delimit $rest $divider -}}
{{- else -}}
{{- .scratch.Set "name" .page.Title -}}
{{- end -}} {{- end -}}
{{- return $name -}}

View File

@@ -1,11 +1,9 @@
<li> <li>
{{- $scratch := newScratch -}} {{- $name := .page.Title -}}
{{- if .seriesName -}} {{- if .seriesName -}}
{{- partial "nameinseries" (dict "page" .page "scratch" $scratch) -}} {{- $name = partial "nameinseries" (dict "page" .page) -}}
{{- else -}}
{{- $scratch.Set "name" (.page.Title) -}}
{{- end -}} {{- end -}}
<a href="{{ .page.Permalink }}" class="post-title">{{ if .page.Params.favorite }}{{ partial "icon.html" "star" }}{{ end }} {{ $scratch.Get "name" }}</a> <a href="{{ .page.Permalink }}" class="post-title">{{ if .page.Params.favorite }}{{ partial "icon.html" "star" }}{{ end }} {{ $name }}</a>
{{ if (not (eq .page.WordCount 0)) }} {{ if (not (eq .page.WordCount 0)) }}
<p class="post-wordcount">{{ i18n "nWords" .page.WordCount }}, {{ i18n "nMinutesToRead" .page.ReadingTime }}.</p> <p class="post-wordcount">{{ i18n "nWords" .page.WordCount }}, {{ i18n "nMinutesToRead" .page.ReadingTime }}.</p>
{{ end }} {{ end }}

View File

@@ -3,9 +3,7 @@
{{ if eq .direction "previous" }}{{ partial "icon.html" "chevrons-left" }}{{ end }} {{ if eq .direction "previous" }}{{ partial "icon.html" "chevrons-left" }}{{ end }}
<div class="title-subtitle"> <div class="title-subtitle">
{{ title .direction }} in Series {{ title .direction }} in Series
{{ $scratch := newScratch -}} <div class="title">{{ partial "nameinseries.html" (dict "page" .page) }}</div>
{{- partial "nameinseries.html" (dict "page" .page "scratch" $scratch) -}}
<div class="title">{{ $scratch.Get "name" }}</div>
</div> </div>
{{ if eq .direction "next" }}{{ partial "icon.html" "chevrons-right" }}{{ end }} {{ if eq .direction "next" }}{{ partial "icon.html" "chevrons-right" }}{{ end }}
</a> </a>

View File

@@ -1,14 +1,14 @@
{{- $scratch := .scratch -}} {{- $pages := slice -}}
{{- $scratch.Set "pages" slice -}}
{{- $tmpScratch := newScratch -}} {{- $tmpScratch := newScratch -}}
{{- range $post := (where (where site.Pages.ByDate.Reverse "Section" "blog") ".Kind" "!=" "section") -}} {{- range $post := (where (where site.Pages.ByDate.Reverse "Section" "blog") ".Kind" "!=" "section") -}}
{{- $term := index ($post.GetTerms "series") 0 -}} {{- $term := index ($post.GetTerms "series") 0 -}}
{{- if (and $term (not ($term.Param "donotunique"))) -}} {{- if (and $term (not ($term.Param "donotunique"))) -}}
{{- if not ($tmpScratch.Get $term.Permalink) -}} {{- if not ($tmpScratch.Get $term.Permalink) -}}
{{- $tmpScratch.Set $term.Permalink true -}} {{- $tmpScratch.Set $term.Permalink true -}}
{{- $scratch.Add "pages" $post -}} {{- $pages = $pages | append $post -}}
{{- end -}} {{- end -}}
{{- else -}} {{- else -}}
{{- $scratch.Add "pages" $post -}} {{- $pages = $pages | append $post -}}
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
{{- return $pages -}}

View File

@@ -1,8 +1,7 @@
{{- $scratch := newScratch -}} {{- $url := partial "geturl.html" (dict "path" (.Get 1)) -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 1)) -}}
{{- $groupconfig := dict {{- $groupconfig := dict
"url" ($scratch.Get "bestUrl") "url" $url.url
"basePath" ($scratch.Get "bestPath") "basePath" $url.basePath
"path" (.Get 1) "path" (.Get 1)
"comment" ", entire file" "comment" ", entire file"
"code" (readFile (printf "code/%s" (.Get 1))) "code" (readFile (printf "code/%s" (.Get 1)))

View File

@@ -35,17 +35,17 @@
{{- $joinedLines = delimit $lines "\n" -}} {{- $joinedLines = delimit $lines "\n" -}}
{{- end -}} {{- end -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 1) "lines" (slice (.Get 2) (.Get 3))) -}} {{- $url := partial "geturl.html" (dict "path" (.Get 1) "lines" (slice (.Get 2) (.Get 3))) -}}
{{- partial "linerangestr.html" (dict "scratch" $scratch "from" (.Get 2) "to" (.Get 3)) -}} {{- $comment := partial "linerangestr.html" (dict "from" (.Get 2) "to" (.Get 3)) -}}
{{- with ($scratch.Get "hidden") -}} {{- with ($scratch.Get "hidden") -}}
<details><summary>{{- . | markdownify -}}</summary> <details><summary>{{- . | markdownify -}}</summary>
{{- end -}} {{- end -}}
{{- $groupconfig := dict {{- $groupconfig := dict
"url" ($scratch.Get "bestUrl") "url" $url.url
"basePath" ($scratch.Get "bestPath") "basePath" $url.basePath
"path" (.Get 1) "path" (.Get 1)
"comment" ($scratch.Get "comment") "comment" $comment
"code" $joinedLines "code" $joinedLines
"firstLine" (int (.Get 2)) "firstLine" (int (.Get 2))
"lastLine" (int (.Get 3)) "lastLine" (int (.Get 3))

View File

@@ -1,3 +1,2 @@
{{- $scratch := newScratch -}} {{- $url := partial "geturl.html" (dict "path" (.Get 0)) -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 0)) -}} {{- $url.url -}}
{{- $scratch.Get "bestUrl" -}}

View File

@@ -5,7 +5,6 @@
{{- $line := .Get 4 -}} {{- $line := .Get 4 -}}
{{- $lines := split (trim .Inner "\n") "\n" -}} {{- $lines := split (trim .Inner "\n") "\n" -}}
{{- $scratch := newScratch -}}
{{- $url := printf "https://github.com/%s/blob/%s/%s#L%d" $repo $commit $file $line -}} {{- $url := printf "https://github.com/%s/blob/%s/%s#L%d" $repo $commit $file $line -}}
{{- partial "linerangestr.html" (dict "scratch" $scratch "from" 0 "to" $line) -}} {{- $comment := partial "linerangestr.html" (dict "from" 0 "to" $line) -}}
{{- partial "highlightgroup.html" (dict "url" $url "path" $file "comment" ($scratch.Get "comment") "code" (trim .Inner "\n") "language" $lang) -}} {{- partial "highlightgroup.html" (dict "url" $url "path" $file "comment" $comment "code" (trim .Inner "\n") "language" $lang) -}}

View File

@@ -1,10 +1,10 @@
{{- $name := .Get 0 -}} {{- $name := .Get 0 -}}
{{- $number := 1 -}} {{- $number := 1 -}}
{{- with .Page.Scratch.Get "internal-ref-counter" -}} {{- with .Page.Store.Get "internal-ref-counter" -}}
{{- $number = add . 1 }} {{- $number = add . 1 }}
{{- end -}} {{- end -}}
{{- .Page.Scratch.Set "internal-ref-counter" $number -}} {{- .Page.Store.Set "internal-ref-counter" $number -}}
{{- .Page.Scratch.SetInMap "internal-ref" $name $number -}} {{- .Page.Store.SetInMap "internal-ref" $name $number -}}
<span class="internal-ref" id="internal-ref-{{ $name }}"> <span class="internal-ref" id="internal-ref-{{ $name }}">
{{ .Inner }} {{ .Inner }}

View File

@@ -1,5 +1,5 @@
{{- $name := .Get 0 -}} {{- $name := .Get 0 -}}
{{- $number := index (.Page.Scratch.Get "internal-ref") $name -}} {{- $number := index (.Page.Store.Get "internal-ref") $name -}}
<a href="#internal-ref-{{ $name }}"> <a href="#internal-ref-{{ $name }}">
{{ .Inner }} {{ .Inner }}

View File

@@ -1,8 +1,7 @@
{{- $scratch := newScratch -}} {{- $url := partial "geturl.html" (dict "path" (.Get 0)) -}}
{{- partial "geturl.html" (dict "scratch" $scratch "path" (.Get 0) "siteSourceUrl" .Site.Params.siteSourceUrl "submoduleLinks" hugo.Data.submodules) -}}
{{- $groupconfig := dict {{- $groupconfig := dict
"url" ($scratch.Get "bestUrl") "url" $url.url
"basePath" ($scratch.Get "bestPath") "basePath" $url.basePath
"path" (.Get 0) "path" (.Get 0)
"comment" ", entire file" "comment" ", entire file"
"content" (safeHTML (printf "<pre><code>%s</code></pre>" (htmlEscape (readFile (printf "code/%s" (.Get 0)))))) "content" (safeHTML (printf "<pre><code>%s</code></pre>" (htmlEscape (readFile (printf "code/%s" (.Get 0))))))

View File

@@ -2,9 +2,9 @@
{{ .Content }} {{ .Content }}
{{ i18n "recentPosts" }}: {{ i18n "recentPosts" }}:
{{ partial "uniquebyseries.html" (dict "scratch" .Scratch) }} {{ $pages := partial "uniquebyseries.html" . }}
<ul class="post-list"> <ul class="post-list">
{{ range first 10 (.Scratch.Get "pages") }} {{ range first 10 $pages }}
{{ partial "post.html" (dict "page" . "linkSeries" true) }} {{ partial "post.html" (dict "page" . "linkSeries" true) }}
{{ end }} {{ end }}
</ul> </ul>

View File

@@ -2,8 +2,8 @@
<h2>{{ .Title }} </h2> <h2>{{ .Title }} </h2>
{{ .Content }} {{ .Content }}
{{ $search := resources.Get "scss/search.scss" | css.Sass | resources.Minify }} {{ $search := resources.Get "scss/search.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $search.Permalink }}" media="screen"> <link rel="stylesheet" href="{{ $search.Permalink }}" integrity="{{ $search.Data.Integrity }}" media="screen">
<div class="stork-wrapper"> <div class="stork-wrapper">
<div class="stork-input-wrapper"> <div class="stork-input-wrapper">

View File

@@ -4,13 +4,13 @@
<head> <head>
{{- partial "head.html" . -}} {{- partial "head.html" . -}}
{{ $writingcss := resources.Get "scss/writing.scss" | css.Sass | resources.Minify }} {{ $writingcss := resources.Get "scss/writing.scss" | css.Sass | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $writingcss.Permalink }}"> <link rel="stylesheet" href="{{ $writingcss.Permalink }}" integrity="{{ $writingcss.Data.Integrity }}">
{{ if .Params.custom_css }} {{ if .Params.custom_css }}
{{ range $customCss := .Params.custom_css }} {{ range $customCss := .Params.custom_css }}
{{ $renderedCustomCss := page.Resources.Get $customCss | css.Sass (dict "includePaths" (slice "themes/vanilla/assets/scss")) | resources.Minify }} {{ $renderedCustomCss := page.Resources.Get $customCss | css.Sass (dict "includePaths" (slice "themes/vanilla/assets/scss")) | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $renderedCustomCss.Permalink }}"> <link rel="stylesheet" href="{{ $renderedCustomCss.Permalink }}" integrity="{{ $renderedCustomCss.Data.Integrity }}">
{{ end }} {{ end }}
{{ end }} {{ end }}
</head> </head>