mirror of
https://github.com/tiennm99/tsuki.git
synced 2026-08-18 02:24:10 +00:00
Three independent CI failures from run 25916500415:
1. Smoke test [linkToSection aria-label] fail on Hugo 0.146 leg.
The assertion pinned to $post selected via `find ... | head -1`,
which on 0.146 picked `doc-sach-quan-sat/index.html` — a post with
zero h2/h3/h4 headings, so zero heading-anchor markup. Rewrite the
check to scan all built post HTML (same pattern already in use for
render-link rel). Now reports 13 matches on the demo build.
2. htmltest URLSwap silently never matched. The prior
`^/tsuki/: /` config (added in d30f50f) used a regex anchor that
doesn't match htmltest's substring evaluation against minified
`href=/tsuki/...` attributes. Switch to the unanchored
`"/tsuki/": /` form. CI has been failing on this since v0.2.0
despite the "fix" commit; this is the real fix.
3. head.html referenced `/favicon.ico` and `/favicon.svg` but neither
asset existed in exampleSite/static/. Add a minimal SVG favicon,
drop the legacy .ico reference (modern browsers fall back to a
site-rooted /favicon.ico by convention; sites needing one can
override head.html). Switch the SVG link to `relURL` so the
`/tsuki/` baseURL prefix is honoured under GitHub Pages subpath
deploy.
Local validation: all 32 smoke checks green; favicon resolves to
`/tsuki/favicon.svg` and ships in the build artifact.
103 lines
4.2 KiB
HTML
103 lines
4.2 KiB
HTML
{{- $title := cond .IsHome site.Title (printf "%s · %s" .Title site.Title) -}}
|
|
{{- $description := .Description | default .Summary | default site.Params.description | default site.Title | plainify -}}
|
|
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="generator" content="tsuki">
|
|
<meta name="theme-color" content="#fbfaf7" media="(prefers-color-scheme: light)">
|
|
<meta name="theme-color" content="#14151a" media="(prefers-color-scheme: dark)">
|
|
|
|
<title>{{ $title }}</title>
|
|
<meta name="description" content="{{ $description }}">
|
|
<link rel="canonical" href="{{ .Permalink }}">
|
|
|
|
{{/* Theme flash prevention — must run before <body> */}}
|
|
<script>
|
|
(function () {
|
|
try {
|
|
var stored = localStorage.getItem('tsuki-theme');
|
|
if (stored === 'dark' || stored === 'light') {
|
|
document.documentElement.setAttribute('data-theme', stored);
|
|
}
|
|
} catch (e) {}
|
|
})();
|
|
</script>
|
|
|
|
{{/* SEO: OpenGraph + Twitter Cards + JSON-LD Article */}}
|
|
{{ partial "head/seo.html" . }}
|
|
|
|
{{/* RSS autodiscovery */}}
|
|
{{- with .OutputFormats.Get "RSS" }}
|
|
<link rel="alternate" type="application/rss+xml" title="{{ site.Title }}" href="{{ .Permalink }}">
|
|
{{- end }}
|
|
|
|
{{/* hreflang alternates — emit only on multilingual sites */}}
|
|
{{- if hugo.IsMultilingual }}
|
|
{{- range .AllTranslations }}
|
|
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}">
|
|
{{- end }}
|
|
{{- with site.Home }}<link rel="alternate" hreflang="x-default" href="{{ .Permalink }}">{{- end }}
|
|
{{- end }}
|
|
|
|
{{/* Pagination prev/next for SEO — only on paginated kinds with >1 page */}}
|
|
{{- if or (eq .Kind "section") (eq .Kind "taxonomy") (eq .Kind "term") }}
|
|
{{- with .Paginator }}
|
|
{{- if gt .TotalPages 1 }}
|
|
{{- if .HasPrev }}<link rel="prev" href="{{ .Prev.URL }}">{{ end }}
|
|
{{- if .HasNext }}<link rel="next" href="{{ .Next.URL }}">{{ end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
|
|
{{/* Favicon — SVG only; sites can override head.html to add an .ico fallback */}}
|
|
<link rel="icon" href="{{ "favicon.svg" | relURL }}" type="image/svg+xml">
|
|
|
|
{{/* Speculation Rules — Chromium prefetch hints; gated, off by default */}}
|
|
{{- $prefetch := site.Params.prefetch -}}
|
|
{{- if and $prefetch $prefetch.enable }}
|
|
<script type="speculationrules">
|
|
{{- with $prefetch.rules -}}{{ . | safeJS }}{{- else -}}
|
|
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":"/search/*"}}]},"eagerness":"moderate"}]}
|
|
{{- end -}}
|
|
</script>
|
|
{{- end }}
|
|
|
|
{{/* Preconnect to Giscus on comment-enabled posts to shave third-party DNS+TLS handshake */}}
|
|
{{- $giscusCfg := site.Params.comments.giscus -}}
|
|
{{- if and (eq .Kind "page") $giscusCfg $giscusCfg.enable $giscusCfg.repo $giscusCfg.repoId $giscusCfg.categoryId (ne .Params.comments false) }}
|
|
<link rel="preconnect" href="https://giscus.app" crossorigin>
|
|
{{- end }}
|
|
|
|
{{/* Theme CSS — per-page-kind bundles. Core loads everywhere; kind-specific bundles add only when needed. */}}
|
|
{{- $coreFiles := slice
|
|
(resources.Get "css/tokens.css")
|
|
(resources.Get "css/reset.css")
|
|
(resources.Get "css/typography.css")
|
|
(resources.Get "css/layout.css")
|
|
(resources.Get "css/components.css")
|
|
(resources.Get "css/view-transitions.css")
|
|
-}}
|
|
{{- $core := $coreFiles | resources.Concat "css/tsuki.core.css" | minify | fingerprint -}}
|
|
<link rel="stylesheet" href="{{ $core.RelPermalink }}" integrity="{{ $core.Data.Integrity }}" crossorigin="anonymous">
|
|
|
|
{{- if .IsHome }}
|
|
{{- $home := resources.Get "css/home.css" | minify | fingerprint -}}
|
|
<link rel="stylesheet" href="{{ $home.RelPermalink }}" integrity="{{ $home.Data.Integrity }}" crossorigin="anonymous">
|
|
{{- end }}
|
|
|
|
{{- if eq .Kind "page" }}
|
|
{{- $singleFiles := slice
|
|
(resources.Get "css/toc.css")
|
|
(resources.Get "css/callouts.css")
|
|
(resources.Get "css/comments.css")
|
|
(resources.Get "css/single-extras.css")
|
|
-}}
|
|
{{- $single := $singleFiles | resources.Concat "css/tsuki.single.css" | minify | fingerprint -}}
|
|
<link rel="stylesheet" href="{{ $single.RelPermalink }}" integrity="{{ $single.Data.Integrity }}" crossorigin="anonymous">
|
|
{{- end }}
|
|
|
|
{{- if eq .Section "archives" }}
|
|
{{- $archive := resources.Get "css/archive.css" | minify | fingerprint -}}
|
|
<link rel="stylesheet" href="{{ $archive.RelPermalink }}" integrity="{{ $archive.Data.Integrity }}" crossorigin="anonymous">
|
|
{{- end }}
|