diff --git a/assets/js/code-copy.js b/assets/js/code-copy.js index 792a50e..9c7d20b 100644 --- a/assets/js/code-copy.js +++ b/assets/js/code-copy.js @@ -2,22 +2,24 @@ const COPY = "Sao chép"; const COPIED = "Đã chép"; const FAILED = "Lỗi"; -for (const pre of document.querySelectorAll("pre")) { - const code = pre.querySelector("code"); - if (!code) continue; - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "code-copy"; - btn.setAttribute("aria-label", COPY); - btn.textContent = COPY; - pre.appendChild(btn); - btn.addEventListener("click", async () => { - try { - await navigator.clipboard.writeText(code.innerText); - btn.textContent = COPIED; - } catch { - btn.textContent = FAILED; - } - setTimeout(() => { btn.textContent = COPY; }, 1500); - }); +if (navigator.clipboard) { + for (const pre of document.querySelectorAll("pre")) { + const code = pre.querySelector("code"); + if (!code) continue; + const btn = document.createElement("button"); + btn.type = "button"; + btn.className = "code-copy"; + btn.setAttribute("aria-label", COPY); + btn.textContent = COPY; + pre.appendChild(btn); + btn.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText(code.innerText); + btn.textContent = COPIED; + } catch { + btn.textContent = FAILED; + } + setTimeout(() => { btn.textContent = COPY; }, 1500); + }); + } } diff --git a/docs/data-schemas.md b/docs/data-schemas.md index e88a4bb..0d95ed0 100644 --- a/docs/data-schemas.md +++ b/docs/data-schemas.md @@ -34,11 +34,13 @@ Field reference: | handle | string | no | reserved | | tagline | string | no | rendered as `
` under name |
| avatar | string | no | resolved with `relURL`; show `` if set |
-| bio | string | no | markdown; `markdownify` filter applied |
+| bio | string | no | markdown; `markdownify` filter applied — see security note below |
| links | array | no | empty list = no links section |
Built-in icons under `assets/icons/`: `github`, `mail`, `rss`, `search`. Add your own SVGs there with `currentColor` fill.
+> **Security note — `bio` rendering.** The theme requires `markup.goldmark.renderer.unsafe: true` (see [`docs/config.md`](config.md)) and pipes `bio` through `markdownify`. Any raw HTML in `bio` — including `
-{{- if and (eq .Kind "page") (gt .WordCount 400) (ne .Params.toc false) }}
+{{- $tocCfg := site.Params.toc | default dict -}}
+{{- $tocEnabled := $tocCfg.enable | default true -}}
+{{- $tocMin := $tocCfg.minWordCount | default 400 -}}
+{{- if and (eq .Kind "page") $tocEnabled (gt .WordCount $tocMin) (ne .Params.toc false) }}
{{- $tocJs := resources.Get "js/toc-active.js" | js.Build (dict "minify" true) | fingerprint -}}
{{- end }}
diff --git a/layouts/_partials/head.html b/layouts/_partials/head.html
index e092a7e..7a56f2f 100644
--- a/layouts/_partials/head.html
+++ b/layouts/_partials/head.html
@@ -1,10 +1,9 @@
{{- $title := cond .IsHome site.Title (printf "%s · %s" .Title site.Title) -}}
-{{- $description := .Description | default .Summary | default site.Params.description | default site.Title -}}
-{{- $ogImage := .Params.image | default site.Params.profile.avatar -}}
+{{- $description := .Description | default .Summary | default site.Params.description | default site.Title | plainify -}}
-
+
{{ i18n "viewAll" | default "View all" }} →
diff --git a/layouts/_partials/meta.html b/layouts/_partials/meta.html index 8ad2c80..fb7e999 100644 --- a/layouts/_partials/meta.html +++ b/layouts/_partials/meta.html @@ -4,16 +4,28 @@ {{ . | time.Format ":date_long" }} {{- end }} + {{- if and .Lastmod (gt (.Lastmod.Sub .Date).Hours 24.0) }} + + {{ i18n "updatedOn" }} + + {{- end }} {{- if gt .ReadingTime 0 }} {{ i18n "readingTime" (dict "Count" .ReadingTime) | default (printf "%d min" .ReadingTime) }} {{- end }} - {{- with .Params.tags }} + {{- if and (site.Params.showWordCount | default false) (gt .WordCount 0) }} + + {{ i18n "wordCount" (dict "Count" .WordCount) | default (printf "%d words" .WordCount) }} + + {{- end }} + {{/* Categories are deliberately not surfaced here; the `categories` taxonomy is routing-only. */}} + {{/* Tag plural is part of the theme contract — see docs/config.md. */}} + {{- with .GetTerms "tags" }} {{- end }} diff --git a/layouts/search/list.html b/layouts/search/list.html index 1ceca25..2128dfc 100644 --- a/layouts/search/list.html +++ b/layouts/search/list.html @@ -1,7 +1,9 @@ {{ define "body_class" }}search{{ end }} {{ define "head_extra" }} +{{- if site.Params.search.enable | default true }} +{{- end }} {{ end }} {{ define "main" }} @@ -10,14 +12,19 @@ {{- with .Description }}{{ . }}
{{ end }} +{{- if site.Params.search.enable | default true }} +{{- else }} +{{ i18n "searchDisabled" | default "Tìm kiếm hiện không khả dụng trên trang này." }}
+{{- end }} {{ end }} {{ define "scripts" }} +{{- if site.Params.search.enable | default true }} +{{- end }} {{ end }} diff --git a/layouts/single.html b/layouts/single.html index 985cf49..d7565ac 100644 --- a/layouts/single.html +++ b/layouts/single.html @@ -15,19 +15,24 @@ -{{- if and (gt .WordCount 400) (ne .Params.toc false) }} +{{- $tocCfg := site.Params.toc | default dict -}} +{{- $tocEnabled := $tocCfg.enable | default true -}} +{{- $tocMin := $tocCfg.minWordCount | default 400 -}} +{{- if and $tocEnabled (gt .WordCount $tocMin) (ne .Params.toc false) }} {{ partial "toc.html" . }} {{- end }} +{{ partial "related-posts.html" . }} + {{ partial "comments.html" . }} {{ end }}