diff --git a/apps/test/content/posts/color-preview-test.md b/apps/test/content/posts/color-preview-test.md
index c1734d1e..e70550e8 100644
--- a/apps/test/content/posts/color-preview-test.md
+++ b/apps/test/content/posts/color-preview-test.md
@@ -12,6 +12,7 @@ tags:
This post is a test post to preview the color syntax in Markdown.
+
## 📝 Syntax
@@ -20,6 +21,7 @@ This post is a test post to preview the color syntax in Markdown.
| HEX | `` `#RRGGBB` `` | `` `#0969DA` `` | `#0969DA` |
| RGB | `` `rgb(R,G,B)` `` | `` `rgb(9, 105, 218)` `` | `rgb(9, 105, 218)` |
| HSL | `` `hsl(H,S,L)` `` | `` `hsl(212, 92%, 45%)` `` | `hsl(212, 92%, 45%)` |
+{caption="Color syntax in Markdown"}
e.g. The background color is `#ffffff` for light mode and `#000000` for dark mode.
diff --git a/assets/js/lib/table-sort.ts b/assets/js/lib/table-sort.ts
new file mode 100644
index 00000000..12664efd
--- /dev/null
+++ b/assets/js/lib/table-sort.ts
@@ -0,0 +1,154 @@
+/**
+ * Table sort module for FixIt content blocks.
+ *
+ * Responsibilities:
+ * - Initialize sortable tables (marked with `data-sortable` attribute).
+ * - Add click handlers to `
` elements for ascending/descending/no-sort toggle.
+ * - Support numeric, date, and string sorting.
+ * - Re-initialize after content decryption events.
+ */
+import { eventBus } from '../core/event-bus'
+
+type SortDirection = 'asc' | 'desc' | null
+
+function detectValueType(value: string): 'number' | 'date' | 'string' {
+ const stripped = value.replace(/[\s,%$€£¥]/g, '')
+ if (stripped !== '' && !Number.isNaN(Number(stripped)))
+ return 'number'
+ if (/\d{4}[-/]\d{1,2}[-/]\d{1,2}/.test(value) && !Number.isNaN(Date.parse(value)))
+ return 'date'
+ return 'string'
+}
+
+function compareValues(a: string, b: string, direction: SortDirection): number {
+ if (!direction)
+ return 0
+ const type = detectValueType(a)
+ let result = 0
+
+ switch (type) {
+ case 'number':
+ result = Number(a.replace(/[\s,%$€£¥]/g, '')) - Number(b.replace(/[\s,%$€£¥]/g, ''))
+ break
+ case 'date':
+ result = new Date(a).getTime() - new Date(b).getTime()
+ break
+ default:
+ result = a.localeCompare(b)
+ }
+
+ return direction === 'asc' ? result : -result
+}
+
+function nextDirection(current: SortDirection): SortDirection {
+ if (current === null)
+ return 'asc'
+ if (current === 'asc')
+ return 'desc'
+ return null
+}
+
+function sortTable(table: HTMLTableElement, colIndex: number, direction: SortDirection) {
+ const tbody = table.querySelector('tbody')
+ if (!tbody)
+ return
+
+ const rows = Array.from(tbody.querySelectorAll('tr'))
+
+ if (!direction) {
+ rows.sort((a, b) => {
+ const orderA = parseInt(a.dataset.order || '0', 10)
+ const orderB = parseInt(b.dataset.order || '0', 10)
+ return orderA - orderB
+ })
+ }
+ else {
+ rows.sort((a, b) => {
+ const cellA = a.children[colIndex]?.textContent?.trim() || ''
+ const cellB = b.children[colIndex]?.textContent?.trim() || ''
+ return compareValues(cellA, cellB, direction)
+ })
+ }
+
+ rows.forEach(row => tbody.appendChild(row))
+}
+
+function updateSortIndicators(table: HTMLTableElement, colIndex: number, direction: SortDirection) {
+ table.querySelectorAll('th').forEach((th, i) => {
+ th.classList.remove('sort-asc', 'sort-desc')
+ if (i === colIndex && direction) {
+ th.classList.add(direction === 'asc' ? 'sort-asc' : 'sort-desc')
+ }
+ })
+}
+
+function initSortableTable(table: HTMLTableElement) {
+ if (table.dataset.sortInit)
+ return
+ table.dataset.sortInit = 'true'
+
+ const tbody = table.querySelector('tbody')
+ if (tbody) {
+ Array.from(tbody.querySelectorAll('tr')).forEach((row, i) => {
+ row.dataset.order = String(i)
+ })
+ }
+
+ table.classList.add('is-sortable')
+
+ const headers = table.querySelectorAll('thead th')
+ headers.forEach((th, index) => {
+ th.classList.add('sort-header')
+ th.setAttribute('role', 'button')
+ th.setAttribute('tabindex', '0')
+ th.setAttribute('aria-sort', 'none')
+
+ const handleClick = () => {
+ const currentDir = (table.dataset.sortDir === 'asc' && table.dataset.sortCol === String(index))
+ ? 'asc'
+ : (table.dataset.sortDir === 'desc' && table.dataset.sortCol === String(index))
+ ? 'desc'
+ : null
+
+ const newDir = nextDirection(currentDir)
+
+ if (newDir) {
+ table.dataset.sortCol = String(index)
+ table.dataset.sortDir = newDir
+ th.setAttribute('aria-sort', newDir === 'asc' ? 'ascending' : 'descending')
+ }
+ else {
+ delete table.dataset.sortCol
+ delete table.dataset.sortDir
+ th.setAttribute('aria-sort', 'none')
+ }
+
+ sortTable(table, index, newDir)
+ updateSortIndicators(table, index, newDir)
+ }
+
+ th.addEventListener('click', handleClick, false)
+ th.addEventListener('keydown', (e) => {
+ if ((e as KeyboardEvent).key === 'Enter' || (e as KeyboardEvent).key === ' ') {
+ e.preventDefault()
+ handleClick()
+ }
+ }, false)
+ })
+}
+
+function initTableSort(target: Element | Document = document) {
+ target.querySelectorAll('table[data-sortable]:not([data-sort-init])')
+ .forEach(initSortableTable)
+}
+
+function bindEvents() {
+ eventBus.on('fixit:content-decrypted', ({ detail }) => {
+ initTableSort(detail.target)
+ })
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ initTableSort()
+ bindEvents()
+}, false)
diff --git a/assets/js/types/config.ts b/assets/js/types/config.ts
index 059a3ed9..ae7e1813 100644
--- a/assets/js/types/config.ts
+++ b/assets/js/types/config.ts
@@ -32,6 +32,7 @@ export interface FixItConfig {
encryption?: EncryptionConfig
print?: PrintConfig
postChat?: boolean
+ table?: TableConfig
}
export interface EchartsConfig {
@@ -121,3 +122,8 @@ export interface PrintConfig {
expandDetails?: boolean
expandFileTree?: boolean
}
+
+export interface TableConfig {
+ number?: boolean
+ sort?: boolean
+}
diff --git a/assets/scss/content/_content.scss b/assets/scss/content/_content.scss
index 10c397df..d1e00e34 100644
--- a/assets/scss/content/_content.scss
+++ b/assets/scss/content/_content.scss
@@ -141,7 +141,7 @@
.content {
margin-block: 1rem;
- counter-reset: h2 h3 h4 h5 h6;
+ counter-reset: h2 h3 h4 h5 h6 table-counter;
> h2.heading-element {
counter-increment: h2;
@@ -167,6 +167,10 @@
counter-increment: h6;
}
+ > .table-wrapper table[data-table-numbered] {
+ counter-increment: table-counter;
+ }
+
> h2.heading-element .heading-numbered::before {
content: counter(h2) ". ";
}
@@ -358,53 +362,8 @@
}
}
- .table-wrapper {
- position: relative;
- overflow-x: auto;
- overflow-y: hidden;
- margin: 0.5rem 0;
- background: fi-var(table-background-color);
- border: 1px solid fi-var(table-border-color);
- @include border-radius;
- @include set-fi-var(scrollbar-thumb-color, fi-var(table-background-color));
-
- > table {
- width: 100%;
- max-width: 100%;
- margin: 0;
- border-spacing: 0;
- background: fi-var(table-background-color);
- border-collapse: separate;
-
- thead {
- background: fi-var(table-thead-color);
- }
-
- &:not([class]) tbody {
- & tr:nth-child(odd) {
- background: light-dark(color.adjust($table-background-color, $lightness: -2.25%), color.adjust($table-background-color-dark, $lightness: 2.75%));
- }
-
- & tr:hover {
- background: light-dark(color.adjust($table-background-color, $lightness: -4.5%), color.adjust($table-background-color-dark, $lightness: 5.5%));
- }
- }
-
- th,
- td {
- padding: 0.3rem 1rem;
- border-inline-end: 1px solid fi-var(table-border-color);
- border-bottom: 1px solid fi-var(table-border-color);
- }
-
- tr > :last-child {
- border-inline-end: none;
- }
-
- > :last-child > tr:last-child > * {
- border-bottom: none;
- }
- }
+ > .table-wrapper table[data-table-numbered] {
+ counter-increment: table-counter;
}
img {
diff --git a/assets/scss/content/_index.scss b/assets/scss/content/_index.scss
index 24bd91b3..57d27d3c 100644
--- a/assets/scss/content/_index.scss
+++ b/assets/scss/content/_index.scss
@@ -2,5 +2,6 @@
@forward "shortcodes";
@forward "alert";
@forward "code";
+@forward "table";
@forward "fixit-decryptor";
@forward "patch";
diff --git a/assets/scss/content/_table.scss b/assets/scss/content/_table.scss
new file mode 100644
index 00000000..8c54bff4
--- /dev/null
+++ b/assets/scss/content/_table.scss
@@ -0,0 +1,114 @@
+@use "sass:color";
+@use "core/functions" as *;
+@use "core/mixins" as *;
+@use "variables" as *;
+
+.table-wrapper {
+ position: relative;
+ overflow-x: auto;
+ overflow-y: hidden;
+ margin: 0.5rem 0;
+ background: fi-var(table-background-color);
+ border: 1px solid fi-var(table-border-color);
+ @include border-radius;
+ @include set-fi-var(scrollbar-thumb-color, fi-var(table-background-color));
+
+ > table {
+ width: 100%;
+ max-width: 100%;
+ margin: 0;
+ border-spacing: 0;
+ background: fi-var(table-background-color);
+ border-collapse: separate;
+
+ thead {
+ background: fi-var(table-thead-color);
+ }
+
+ tbody {
+ tr:nth-child(odd) {
+ background: light-dark(color.adjust($table-background-color, $lightness: -2.25%), color.adjust($table-background-color-dark, $lightness: 2.75%));
+ }
+ tr:hover {
+ background: light-dark(color.adjust($table-background-color, $lightness: -4.5%), color.adjust($table-background-color-dark, $lightness: 5.5%));
+ }
+ }
+
+ th,
+ td {
+ padding: 0.3rem 1rem;
+ border-inline-end: 1px solid fi-var(table-border-color);
+ border-bottom: 1px solid fi-var(table-border-color);
+ }
+
+ tr > :last-child {
+ border-inline-end: none;
+ }
+
+ > :last-child > tr:last-child > * {
+ border-bottom: none;
+ }
+
+ > caption {
+ caption-side: top;
+ padding: 0.5rem 1rem;
+ text-align: center;
+ font-weight: 600;
+ font-size: 0.875em;
+ border-bottom: 1px solid fi-var(table-border-color);
+ border-radius: fi-var(global-border-radius) fi-var(global-border-radius) 0 0;
+
+ .table-number {
+ &::before {
+ content: attr(data-i18n-table) " " counter(table-counter);
+ }
+
+ & + .table-caption {
+ font-weight: normal;
+
+ &::before {
+ content: "-";
+ margin-inline: 0.25em;
+ }
+ }
+ }
+ }
+
+ // Sortable table styles
+ &.is-sortable thead th.sort-header {
+ cursor: pointer;
+ user-select: none;
+ position: relative;
+ padding-inline-end: 1.5rem;
+
+ &::after {
+ content: "";
+ position: absolute;
+ inset-inline-end: 0.5rem;
+ top: 50%;
+ translate: 0 -50%;
+ width: 0;
+ height: 0;
+ border-inline: 4px solid transparent;
+ border-block: 4px solid transparent;
+ opacity: 0.3;
+ transition: all 0.2s, translate 0.2s;
+ }
+
+ &:hover::after {
+ opacity: 0.6;
+ }
+
+ &.sort-asc::after,
+ &.sort-desc::after {
+ opacity: 1;
+ border-block-end: 5px solid fi-var(global-font-color);
+ border-block-start: 0;
+ }
+
+ &.sort-desc::after {
+ rotate: 180deg;
+ }
+ }
+ }
+}
diff --git a/hugo.toml b/hugo.toml
index 4d8d00a8..c4882639 100644
--- a/hugo.toml
+++ b/hugo.toml
@@ -735,7 +735,7 @@ enable = false
# Disclaimer type.
# available values: ["ai", "repost", "original", "custom"]
type = "ai"
-# Custom disclaimer content (optional, uses i18n default if empty).
+# Custom disclaimer content (optional, uses I18n default if empty).
content = ""
# Display a message at the beginning of an article to warn the reader that its content might be expired.
@@ -760,6 +760,13 @@ enable = false
# Only enable in main section pages (default is posts).
only_main_section = true
+# {{< version 1.0.0 >}} Table configuration.
+[params.table]
+# Whether to enable auto table numbering.
+number = false
+# Whether to enable table sorting.
+sort = true
+
# Mathematical formulas configuration.
# See: [Formula](https://fixit.lruihao.cn/docs/content-management/markdown-syntax/extended/#formula)
[params.math]
diff --git a/i18n/ar.toml b/i18n/ar.toml
index 555ea025..3e710043 100644
--- a/i18n/ar.toml
+++ b/i18n/ar.toml
@@ -89,6 +89,7 @@ valinePlaceholder = "تعليقك ..."
# === Assets ===
[assets]
+table = "جدول"
search = "بحث"
searchPlaceholder = "ابحث في العناوين أو المحتوى ..."
searchIn = "ابحث في {{ . }}"
diff --git a/i18n/de.toml b/i18n/de.toml
index 42774802..6812dec0 100644
--- a/i18n/de.toml
+++ b/i18n/de.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Ihr Kommentar ..."
# === Assets ===
[assets]
+table = "Tabelle"
search = "Suche"
searchPlaceholder = "Suche nach Titel und Inhalt..."
searchIn = "Suche in {{ . }}"
diff --git a/i18n/en.toml b/i18n/en.toml
index d4d3a260..fe460da7 100644
--- a/i18n/en.toml
+++ b/i18n/en.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Your comment ..."
# === Assets ===
[assets]
+table = "Table"
search = "Search"
searchPlaceholder = "Search titles or contents ..."
searchIn = "Search in {{ . }}"
diff --git a/i18n/es.toml b/i18n/es.toml
index 1c99fcf8..35599760 100644
--- a/i18n/es.toml
+++ b/i18n/es.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Tu comentario ..."
# === Assets ===
[assets]
+table = "Tabla"
search = "Buscar"
searchPlaceholder = "Busca títulos o contenido..."
searchIn = "Buscar en {{ . }}"
diff --git a/i18n/fa.toml b/i18n/fa.toml
index 10668117..1375349f 100644
--- a/i18n/fa.toml
+++ b/i18n/fa.toml
@@ -89,6 +89,7 @@ valinePlaceholder = "نظر شما ..."
# === Assets ===
[assets]
+table = "جدول"
search = "جستجو"
searchPlaceholder = "جستجوی عناوین یا محتوا ..."
searchIn = "جستجو در {{ . }}"
diff --git a/i18n/fr.toml b/i18n/fr.toml
index 4f874300..a0c14317 100644
--- a/i18n/fr.toml
+++ b/i18n/fr.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Votre commentaire ..."
# === Assets ===
[assets]
+table = "Tableau"
search = "Chercher"
searchPlaceholder = "Rechercher des titres, des contenus..."
searchIn = "Rechercher dans {{ . }}"
diff --git a/i18n/hi.toml b/i18n/hi.toml
index f06b3df5..d78d40bc 100644
--- a/i18n/hi.toml
+++ b/i18n/hi.toml
@@ -89,6 +89,7 @@ valinePlaceholder = "आपकी टिप्पणी ..."
# === Assets ===
[assets]
+table = "तालिका"
search = "खोज"
searchPlaceholder = "शीर्षक या सामग्री खोजें ..."
searchIn = "{{ . }} में खोजें"
diff --git a/i18n/it.toml b/i18n/it.toml
index 2c5eb275..cabaa963 100644
--- a/i18n/it.toml
+++ b/i18n/it.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Il tuo commento ..."
# === Assets ===
[assets]
+table = "Tabella"
search = "Cerca"
searchPlaceholder = "Cerca il titolo o il contenuto dell'articolo ..."
searchIn = "Cerca in"
diff --git a/i18n/ja.toml b/i18n/ja.toml
index 685f5e15..72492c2d 100644
--- a/i18n/ja.toml
+++ b/i18n/ja.toml
@@ -86,6 +86,7 @@ valinePlaceholder = "あなたのコメント……"
# === Assets ===
[assets]
+table = "テーブル"
search = "検索"
searchPlaceholder = "タイトルまたは内容を検索..."
searchIn = "{{ . }} で検索"
diff --git a/i18n/ko.toml b/i18n/ko.toml
index f56fff90..30ddb4d3 100644
--- a/i18n/ko.toml
+++ b/i18n/ko.toml
@@ -86,6 +86,7 @@ valinePlaceholder = "당신의 댓글……"
# === Assets ===
[assets]
+table = "표"
search = "검색"
searchPlaceholder = "제목 또는 내용을 검색하세요..."
searchIn = "{{ . }}에서 검색"
diff --git a/i18n/pl.toml b/i18n/pl.toml
index 76a8c627..6ff4b067 100644
--- a/i18n/pl.toml
+++ b/i18n/pl.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Twój komentarz ..."
# === Assets ===
[assets]
+table = "Tabela"
search = "Szukaj"
searchPlaceholder = "Wyszukaj tytuł lub treść artykułu ..."
searchIn = "Szukaj w {{ . }}"
diff --git a/i18n/pt-BR.toml b/i18n/pt-BR.toml
index d9bdab55..7db543a6 100644
--- a/i18n/pt-BR.toml
+++ b/i18n/pt-BR.toml
@@ -89,6 +89,7 @@ valinePlaceholder = "O seu comentário..."
# === Assets ===
[assets]
+table = "Tabela"
search = "Pesquisa"
searchPlaceholder = "Pesquisar títulos ou conteúdos..."
searchIn = "Pesquisar em {{ . }}"
diff --git a/i18n/ro.toml b/i18n/ro.toml
index 356dd13a..05c528f3 100644
--- a/i18n/ro.toml
+++ b/i18n/ro.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Comentariul dvs ..."
# === Assets ===
[assets]
+table = "Tabelă"
search = "Căutare"
searchPlaceholder = "Căutarea titlului sau conținutului articolului ..."
searchIn = "Căutare în {{ . }}"
diff --git a/i18n/ru.toml b/i18n/ru.toml
index 1c5ec8c2..21102e52 100644
--- a/i18n/ru.toml
+++ b/i18n/ru.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Ваш комментарий ..."
# === Assets ===
[assets]
+table = "Таблица"
search = "Поиск"
searchPlaceholder = "Поиск заголовков или содержимого ..."
searchIn = "Поиск в {{ . }}"
diff --git a/i18n/sr.toml b/i18n/sr.toml
index dd26c300..8b265804 100644
--- a/i18n/sr.toml
+++ b/i18n/sr.toml
@@ -88,6 +88,7 @@ valinePlaceholder = "Ваш коментар ..."
# === Assets ===
[assets]
+table = "Табела"
search = "Претрага"
searchPlaceholder = "Претражи наслове или садржај..."
searchIn = "Претражи у {{ . }}"
diff --git a/i18n/ur.toml b/i18n/ur.toml
index 92e21313..695db332 100644
--- a/i18n/ur.toml
+++ b/i18n/ur.toml
@@ -89,6 +89,7 @@ valinePlaceholder = "آپ کا تبصرہ ..."
# === Assets ===
[assets]
+table = "جدول"
search = "تلاش"
searchPlaceholder = "عنوان یا مواد میں تلاش کریں ..."
searchIn = "{{ . }} میں تلاش کریں"
diff --git a/i18n/vi.toml b/i18n/vi.toml
index c7800d1c..0d157c2f 100644
--- a/i18n/vi.toml
+++ b/i18n/vi.toml
@@ -87,6 +87,7 @@ valinePlaceholder = "Bình luận của bạn ..."
# === Assets ===
[assets]
+table = "Bảng"
search = "Tìm kiếm"
searchPlaceholder = "Tìm tiêu đề hoặc nội dung..."
searchIn = "Tìm kiếm trong {{ . }}"
diff --git a/i18n/zh-CN.toml b/i18n/zh-CN.toml
index 3bf00c53..c9b52c97 100644
--- a/i18n/zh-CN.toml
+++ b/i18n/zh-CN.toml
@@ -86,6 +86,7 @@ valinePlaceholder = "你的评论……"
# === Assets ===
[assets]
+table = "表"
search = "搜索"
searchPlaceholder = "搜索文章标题或内容……"
searchIn = "在 {{ . }} 中搜索"
diff --git a/i18n/zh-TW.toml b/i18n/zh-TW.toml
index cd08eeba..ba01ef9c 100644
--- a/i18n/zh-TW.toml
+++ b/i18n/zh-TW.toml
@@ -86,6 +86,7 @@ valinePlaceholder = "你的評論……"
# === Assets ===
[assets]
+table = "表"
search = "搜尋"
searchPlaceholder = "搜尋文章標題或內容……"
searchIn = "在 {{ . }} 中搜尋"
diff --git a/layouts/_markup/render-table.html b/layouts/_markup/render-table.html
index ca1d4c00..5f25da4b 100644
--- a/layouts/_markup/render-table.html
+++ b/layouts/_markup/render-table.html
@@ -1,15 +1,40 @@
{{- /*
- Add a table wrapper to better style overflow tables
- The reset of the template is the same as the default render-table.html
+ Custom table render hook for FixIt theme.
+ - Wraps tables in a scrollable container
+ - Supports auto-numbering via CSS counters (config: params.table.number)
+ - Supports client-side sorting (config: params.table.sort)
+ - Supports table captions via Markdown attribute {caption="..."}
+ - Per-table override via Markdown attributes (e.g., {number=false, sort=false})
+
See https://gohugo.io/render-hooks/tables/
*/ -}}
+{{- $pageConfig := dict "Page" .Page "Key" "table" | partial "function/param.html" | merge .Attributes -}}
+{{- $config := .Attributes | merge $pageConfig -}}
+{{- $caption := .Attributes.caption -}}
+
+{{- $attrs := "" -}}
+{{- if $config.number }}
+ {{- $attrs = printf "%s data-table-numbered" $attrs }}
+{{- end -}}
+{{- if $config.sort }}
+ {{- $attrs = printf "%s data-sortable" $attrs }}
+ {{- .Page.Store.Set "hasTableSort" true }}
+{{- end -}}
+{{- range $k, $v := .Attributes }}
+ {{- if and $v (ne $k "number") (ne $k "caption") (ne $k "sort") }}
+ {{- $attrs = printf "%s %s=%q" $attrs $k $v }}
+ {{- end }}
+{{- end -}}
+{{- $attrs = partial "function/trim.html" $attrs -}}
+
-
+
+ {{- if or $config.number $caption }}
+
+ {{- if $config.number }}{{ end -}}
+ {{- with $caption }}{{ . }}{{ end -}}
+
+ {{- end -}}
{{- range .THead }}
diff --git a/layouts/_partials/base/assets.html b/layouts/_partials/base/assets.html
index fa1e5f8b..8e24de2d 100644
--- a/layouts/_partials/base/assets.html
+++ b/layouts/_partials/base/assets.html
@@ -267,6 +267,11 @@
{{- dict "Source" "js/lib/watermark.ts" "Build" true "Fingerprint" $fingerprint "Defer" true | dict "Page" . "Data" | partial "store/script.html" -}}
{{- end -}}
+{{- /* Table Sort */ -}}
+{{- if .Store.Get "hasTableSort" -}}
+ {{- dict "Source" "js/lib/table-sort.ts" "Build" true "Fingerprint" $fingerprint "Defer" true | dict "Page" . "Data" | partial "store/script.html" -}}
+{{- end -}}
+
{{- /* Content Decryption */ -}}
{{- $encryptPartial := .Store.Get "hasEncryptor" -}}
{{- if .Params.password | or $encryptPartial -}}
|