@heroiclands/package-build 23.13.0 → 24.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +2 -1
- package/assets/preview/gitea.ini +12 -7
- package/assets/styles/content-base.css +150 -1
- package/bin/content-commands.mjs +356 -210
- package/bin/package-build.mjs +3 -2
- package/ci/check-banners.mjs +7 -7
- package/config.mjs +21 -6
- package/content-config.mjs +199 -80
- package/docs/api.md +93 -72
- package/docs/authoring/links-and-markup.md +316 -78
- package/docs/commands.md +248 -80
- package/docs/configuration.md +210 -102
- package/docs/content-format.md +2 -2
- package/docs/diagnostics.md +2 -2
- package/docs/getting-started.md +1 -1
- package/docs/guides/icons.md +1 -1
- package/docs/guides/module-project.md +5 -8
- package/docs/guides/release-and-deploy.md +2 -2
- package/docs/guides/site.md +155 -23
- package/docs/guides/system-project.md +1 -1
- package/docs/guides/writing-in-invented-scripts.md +1247 -0
- package/docs/index.md +1 -0
- package/docs/project-setup.md +28 -30
- package/docs/reference/format-details.md +589 -308
- package/docs/reference/note-types.md +40 -10
- package/docs/reference/theme-pages.md +127 -108
- package/docs/source-preview.md +15 -1
- package/engine/asset-shipping.mjs +22 -10
- package/engine/base-compiler.mjs +62 -104
- package/engine/changelog-lint.mjs +1 -1
- package/engine/content-address.mjs +1 -1
- package/engine/content-alerts.mjs +8 -4
- package/engine/content-blocks.mjs +26 -11
- package/engine/content-embeds.mjs +1 -1
- package/engine/content-expand.mjs +376 -0
- package/engine/content-figures.mjs +13 -6
- package/engine/content-format.yaml +8 -0
- package/engine/content-glyphs.mjs +213 -0
- package/engine/content-images.mjs +6 -7
- package/engine/content-links.mjs +3 -3
- package/engine/content-lint.mjs +1 -1
- package/engine/content-render.mjs +453 -0
- package/engine/content-scripts.mjs +326 -27
- package/engine/content-spans.mjs +4 -1
- package/engine/content-styles.mjs +91 -0
- package/engine/content-symbols.mjs +186 -0
- package/engine/content-verse.mjs +6 -18
- package/engine/core-report.mjs +169 -0
- package/engine/core-vocabulary.mjs +208 -0
- package/engine/dictionary-html.mjs +119 -0
- package/engine/field-reference.mjs +1 -1
- package/engine/frontmatter-lint.mjs +1 -1
- package/engine/heading-attributes.mjs +89 -0
- package/engine/helpers.mjs +61 -101
- package/engine/homepage.mjs +17 -29
- package/engine/html-minify.mjs +70 -0
- package/engine/index.mjs +8 -5
- package/engine/language-rows.mjs +8 -2
- package/engine/language-terms.mjs +115 -14
- package/engine/language-words.mjs +12 -0
- package/engine/logographic.mjs +255 -0
- package/engine/map-lexicon.mjs +221 -25
- package/engine/map-places.mjs +5 -4
- package/engine/markdown-expressions.mjs +0 -2
- package/engine/markdownlint-run.mjs +9 -3
- package/engine/markup-validation.mjs +21 -0
- package/engine/metre-declaration.mjs +134 -0
- package/engine/note-matter.mjs +2 -2
- package/engine/note-vocabulary.mjs +187 -3
- package/engine/pdf-build.mjs +68 -133
- package/engine/pdf-render.mjs +102 -44
- package/engine/post-fields.mjs +157 -0
- package/engine/preview-index.mjs +130 -0
- package/engine/preview-source.mjs +450 -0
- package/engine/project-init.mjs +5 -12
- package/engine/prose-config.mjs +3 -3
- package/engine/run-words.mjs +3 -2
- package/engine/script-emphasis-terms.mjs +38 -0
- package/engine/script-emphasis.mjs +295 -0
- package/engine/script-font-delivery.mjs +4 -4
- package/engine/site-build.mjs +265 -313
- package/engine/site-config.mjs +26 -238
- package/engine/site-files.mjs +175 -0
- package/engine/site-index.mjs +9 -4
- package/engine/site-preview.mjs +50 -523
- package/engine/site-reach.mjs +213 -0
- package/engine/site-render.mjs +668 -0
- package/engine/site-root.mjs +90 -39
- package/engine/site-search.mjs +161 -0
- package/engine/site-serve.mjs +274 -0
- package/engine/site-theme-banner.mjs +154 -0
- package/engine/site-theme-urls.mjs +125 -0
- package/engine/site-theme.mjs +939 -0
- package/engine/sql-tables.mjs +9 -6
- package/engine/text-maps.mjs +57 -10
- package/engine/typographer.mjs +248 -0
- package/engine/verse-metre.mjs +357 -0
- package/engine/wikilink-syntax.mjs +29 -47
- package/engine/wikilinks.mjs +758 -279
- package/engine/word-forms.mjs +39 -24
- package/engine/word-rows.mjs +12 -2
- package/engine/word-terms.mjs +29 -4
- package/manifest.mjs +3 -4
- package/package.json +10 -7
- package/{hugo-theme → site-theme}/data/banners.yaml +6 -10
- package/site-theme/layouts/base.hbs +31 -0
- package/site-theme/layouts/blog-list.hbs +30 -0
- package/site-theme/layouts/blog-post.hbs +40 -0
- package/site-theme/layouts/home.hbs +35 -0
- package/site-theme/layouts/list.hbs +20 -0
- package/site-theme/layouts/not-found.hbs +31 -0
- package/site-theme/layouts/page.hbs +7 -0
- package/site-theme/partials/copy-buttons.hbs +37 -0
- package/site-theme/partials/draft-notice.hbs +5 -0
- package/site-theme/partials/exturl.hbs +2 -0
- package/{hugo-theme/layouts/partials/footer.html → site-theme/partials/footer.hbs} +10 -7
- package/site-theme/partials/header.hbs +44 -0
- package/site-theme/partials/hero-banner.hbs +11 -0
- package/site-theme/partials/infobox-entry.hbs +2 -0
- package/site-theme/partials/infobox-section.hbs +31 -0
- package/site-theme/partials/infobox-value.hbs +2 -0
- package/site-theme/partials/infobox.hbs +18 -0
- package/site-theme/partials/list-members.hbs +9 -0
- package/site-theme/partials/nav-links.hbs +5 -0
- package/site-theme/partials/page-body.hbs +48 -0
- package/site-theme/partials/page-list.hbs +14 -0
- package/site-theme/partials/related.hbs +24 -0
- package/site-theme/partials/search-meta.hbs +6 -0
- package/site-theme/partials/search-names.hbs +2 -0
- package/site-theme/partials/search.hbs +52 -0
- package/site-theme/partials/tags.hbs +4 -0
- package/site-theme/partials/toc.hbs +7 -0
- package/{hugo-theme → site-theme}/static/css/style.css +14 -0
- package/stage.mjs +1 -2
- package/types/config.d.mts +8 -4
- package/types/content-config.d.mts +15 -15
- package/types/engine/asset-shipping.d.mts +5 -2
- package/types/engine/base-compiler.d.mts +20 -2
- package/types/engine/content-address.d.mts +1 -1
- package/types/engine/content-alerts.d.mts +8 -2
- package/types/engine/content-blocks.d.mts +11 -4
- package/types/engine/content-expand.d.mts +288 -0
- package/types/engine/content-figures.d.mts +11 -3
- package/types/engine/content-glyphs.d.mts +85 -0
- package/types/engine/content-images.d.mts +6 -7
- package/types/engine/content-links.d.mts +1 -1
- package/types/engine/content-render.d.mts +199 -0
- package/types/engine/content-scripts.d.mts +62 -0
- package/types/engine/content-spans.d.mts +1 -1
- package/types/engine/content-styles.d.mts +33 -0
- package/types/engine/content-symbols.d.mts +35 -0
- package/types/engine/core-report.d.mts +45 -0
- package/types/engine/core-vocabulary.d.mts +53 -0
- package/types/engine/dictionary-html.d.mts +8 -0
- package/types/engine/field-reference.d.mts +1 -1
- package/types/engine/heading-attributes.d.mts +20 -0
- package/types/engine/helpers.d.mts +3 -10
- package/types/engine/homepage.d.mts +11 -24
- package/types/engine/html-minify.d.mts +9 -0
- package/types/engine/index.d.mts +2 -1
- package/types/engine/language-terms.d.mts +24 -2
- package/types/engine/logographic.d.mts +45 -0
- package/types/engine/map-lexicon.d.mts +48 -8
- package/types/engine/map-places.d.mts +8 -0
- package/types/engine/markdown-expressions.d.mts +0 -2
- package/types/engine/metre-declaration.d.mts +39 -0
- package/types/engine/pdf-render.d.mts +6 -2
- package/types/engine/post-fields.d.mts +44 -0
- package/types/engine/preview-index.d.mts +72 -0
- package/types/engine/preview-source.d.mts +51 -0
- package/types/engine/script-emphasis-terms.d.mts +21 -0
- package/types/engine/script-emphasis.d.mts +84 -0
- package/types/engine/script-font-delivery.d.mts +4 -4
- package/types/engine/site-build.d.mts +71 -113
- package/types/engine/site-config.d.mts +14 -134
- package/types/engine/site-files.d.mts +73 -0
- package/types/engine/site-index.d.mts +11 -3
- package/types/engine/site-preview.d.mts +15 -19
- package/types/engine/site-reach.d.mts +76 -0
- package/types/engine/site-render.d.mts +173 -0
- package/types/engine/site-root.d.mts +14 -4
- package/types/engine/site-search.d.mts +54 -0
- package/types/engine/site-serve.d.mts +44 -0
- package/types/engine/site-theme-banner.d.mts +51 -0
- package/types/engine/site-theme-urls.d.mts +60 -0
- package/types/engine/site-theme.d.mts +127 -0
- package/types/engine/text-maps.d.mts +17 -3
- package/types/engine/typographer.d.mts +11 -0
- package/types/engine/verse-metre.d.mts +131 -0
- package/types/engine/wikilink-syntax.d.mts +30 -48
- package/types/engine/wikilinks.d.mts +330 -14
- package/types/engine/word-forms.d.mts +3 -2
- package/types/manifest.d.mts +3 -4
- package/types/stage.d.mts +1 -2
- package/types/vendor/markdownlint.d.mts +8 -0
- package/vendor/markdownlint.mjs +20388 -0
- package/engine/web-wikilinks.mjs +0 -594
- package/hugo-theme/layouts/404.html +0 -85
- package/hugo-theme/layouts/_default/baseof.html +0 -67
- package/hugo-theme/layouts/_default/list.html +0 -139
- package/hugo-theme/layouts/_default/single.html +0 -4
- package/hugo-theme/layouts/blog/list.html +0 -54
- package/hugo-theme/layouts/blog-post/single.html +0 -36
- package/hugo-theme/layouts/index.html +0 -75
- package/hugo-theme/layouts/partials/banner-url.html +0 -141
- package/hugo-theme/layouts/partials/cdn-url.html +0 -36
- package/hugo-theme/layouts/partials/dictionary-lists.html +0 -58
- package/hugo-theme/layouts/partials/draft-notice.html +0 -41
- package/hugo-theme/layouts/partials/draft-state.html +0 -26
- package/hugo-theme/layouts/partials/header.html +0 -35
- package/hugo-theme/layouts/partials/hero-banner.html +0 -85
- package/hugo-theme/layouts/partials/infobox/entry.html +0 -18
- package/hugo-theme/layouts/partials/infobox/items.html +0 -26
- package/hugo-theme/layouts/partials/infobox/section.html +0 -56
- package/hugo-theme/layouts/partials/infobox/value.html +0 -43
- package/hugo-theme/layouts/partials/infobox.html +0 -57
- package/hugo-theme/layouts/partials/page-body.html +0 -152
- package/hugo-theme/layouts/partials/related.html +0 -138
- package/hugo-theme/layouts/partials/search.html +0 -84
- package/hugo-theme/layouts/partials/site-url.html +0 -32
- package/hugo-theme/layouts/partials/tags.html +0 -30
- package/hugo-theme/layouts/partials/toc.html +0 -28
- package/hugo-theme/layouts/partials/warn-missing-banner.html +0 -3
- package/hugo-theme/layouts/shortcodes/cartouche.html +0 -64
- package/hugo-theme/layouts/shortcodes/exturl.html +0 -12
- package/hugo-theme/layouts/shortcodes/glyph.html +0 -43
- package/hugo-theme/layouts/shortcodes/pagelist.html +0 -63
- package/hugo-theme/theme.toml +0 -11
- package/types/engine/web-wikilinks.d.mts +0 -107
- /package/{hugo-theme → site-theme}/data/banner-kinds.yaml +0 -0
- /package/{hugo-theme → site-theme}/static/css/sohl-icons.css +0 -0
- /package/{hugo-theme → site-theme}/static/fonts/game-icons-kb.woff2 +0 -0
- /package/{hugo-theme → site-theme}/static/img/banners/takheperu-hieroglyphs.svg +0 -0
- /package/{hugo-theme → site-theme}/static/img/cartouches/takheperu.svg +0 -0
- /package/{hugo-theme → site-theme}/static/js/inline-spoilers.js +0 -0
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
Whether a page's note is an unfinished draft.
|
|
3
|
-
|
|
4
|
-
The `draft` tag is the authored signal, and it is the only one either side
|
|
5
|
-
can read: the content build asks it through its own single reader
|
|
6
|
-
(package-build/engine/note-vocabulary.mjs, `DRAFT_TAG`) and a theme cannot
|
|
7
|
-
import that, so the shared fact is the tag itself. It reaches the page
|
|
8
|
-
because the build copies a note's own front matter onto it.
|
|
9
|
-
|
|
10
|
-
It is spelled once, here. Two partials act on the state — the tag row leaves
|
|
11
|
-
it out of a page's subjects, and the notice states it — and a second literal
|
|
12
|
-
is how the two come apart.
|
|
13
|
-
|
|
14
|
-
Hugo's own reserved `draft: true` is a different thing entirely and is never
|
|
15
|
-
written by the build: a page carrying it is not rendered at all.
|
|
16
|
-
|
|
17
|
-
Context: the page. Returns "true" for a draft and "" for anything else, which
|
|
18
|
-
is what `if` reads.
|
|
19
|
-
*/ -}}
|
|
20
|
-
{{- $draft := false -}}
|
|
21
|
-
{{- range .Params.tags -}}
|
|
22
|
-
{{- if eq (lower .) "draft" -}}
|
|
23
|
-
{{- $draft = true -}}
|
|
24
|
-
{{- end -}}
|
|
25
|
-
{{- end -}}
|
|
26
|
-
{{- return $draft -}}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<header class="site-header" data-pagefind-ignore>
|
|
2
|
-
<div class="header-inner">
|
|
3
|
-
<a href="{{ .Site.Home.RelPermalink }}" class="site-title">
|
|
4
|
-
{{- with .Site.Params.brand }}{{ with .logo }}
|
|
5
|
-
<img src="{{ partial "cdn-url.html" (dict "site" $.Site "path" .) }}" alt="Heroic Lands" class="site-logo">
|
|
6
|
-
{{- end }}{{ end }}
|
|
7
|
-
<span class="title-main">Heroic Lands</span>
|
|
8
|
-
</a>
|
|
9
|
-
<div class="header-actions">
|
|
10
|
-
<nav class="site-nav">
|
|
11
|
-
{{ range .Site.Menus.main }}
|
|
12
|
-
{{ if .HasChildren }}
|
|
13
|
-
<div class="nav-dropdown">
|
|
14
|
-
<a href="{{ .URL }}" class="nav-link{{ if $.IsMenuCurrent "main" . }} active{{ end }}">
|
|
15
|
-
{{ .Name }}
|
|
16
|
-
<svg class="dropdown-arrow" width="10" height="6" viewBox="0 0 10 6" fill="currentColor"><path d="M1 1l4 4 4-4"/></svg>
|
|
17
|
-
</a>
|
|
18
|
-
<div class="dropdown-menu">
|
|
19
|
-
{{ range .Children }}
|
|
20
|
-
<a href="{{ .URL }}" class="dropdown-item">{{ .Name }}</a>
|
|
21
|
-
{{ end }}
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
{{ else }}
|
|
25
|
-
<a href="{{ .URL }}" class="nav-link{{ if $.IsMenuCurrent "main" . }} active{{ end }}">{{ .Name }}</a>
|
|
26
|
-
{{ end }}
|
|
27
|
-
{{ end }}
|
|
28
|
-
</nav>
|
|
29
|
-
{{ partial "search.html" . }}
|
|
30
|
-
<button class="nav-toggle" aria-label="Toggle navigation">
|
|
31
|
-
<span></span><span></span><span></span>
|
|
32
|
-
</button>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</header>
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
Hero banner partial.
|
|
3
|
-
|
|
4
|
-
Displays a full-width banner band (using the same .hero.hero-with-image
|
|
5
|
-
classes as the homepage) with a centered page title and description
|
|
6
|
-
above the content.
|
|
7
|
-
|
|
8
|
-
Every path below resolves through cdn-url.html against the consuming
|
|
9
|
-
site's `params.cdnBaseURL`; the theme names no host of its own.
|
|
10
|
-
|
|
11
|
-
The resolution itself lives in `banner-url.html`, which a derived landing card
|
|
12
|
-
calls too. The order is documented in both places because this is where a
|
|
13
|
-
reader looking at a banner starts; that partial is where it happens.
|
|
14
|
-
|
|
15
|
-
Banner image resolution order:
|
|
16
|
-
1. .Params.data.banner — a note's own hero image, which the content
|
|
17
|
-
build resolved from an asset Address into
|
|
18
|
-
the address its asset host serves. Used
|
|
19
|
-
exactly as given. A blank declines a hero
|
|
20
|
-
image; unset or `null` carries on.
|
|
21
|
-
2. .Params.banner — a hand-authored page's value. `none` (or
|
|
22
|
-
`false`) declines a hero image entirely —
|
|
23
|
-
see "Declining" below. A full URL is used
|
|
24
|
-
as-is; anything else is treated as a
|
|
25
|
-
fragment under images/.
|
|
26
|
-
3. images/banners/{name}.webp — the default for the page's kind: the
|
|
27
|
-
banner data/banner-kinds.yaml maps its
|
|
28
|
-
type and subType to, or its category for
|
|
29
|
-
type=doc pages
|
|
30
|
-
4. images/banners/default.webp — used when the page has no type, *and*
|
|
31
|
-
whenever the name picked by 2 or 3 is not
|
|
32
|
-
in the declared inventory (see below).
|
|
33
|
-
|
|
34
|
-
Existence, and why step 4 is a declaration rather than a test.
|
|
35
|
-
The image is served from the consumer's asset host, and Hugo cannot ask a
|
|
36
|
-
remote host whether a URL exists — so a name that was never drawn would be
|
|
37
|
-
emitted unchecked and 404 in silence, the band rendering with its title,
|
|
38
|
-
palette and gradient intact behind a dead URL. `data/banners.yaml`
|
|
39
|
-
is the declaration that stands in for the test it cannot make: a resolved name
|
|
40
|
-
absent from `available` falls back to `fallback` and warns once. That file
|
|
41
|
-
documents how the list is kept honest (`npm run lint:banners` fetches every
|
|
42
|
-
name and fails on a non-200), and a consumer publishing its own artwork set
|
|
43
|
-
overrides the whole list by shipping its own `data/banners.yaml`.
|
|
44
|
-
|
|
45
|
-
The check applies only to a *relative* path resolving directly inside the
|
|
46
|
-
declared banner directory. An absolute URL, and a fragment pointing anywhere
|
|
47
|
-
else under images/, pass through untouched: the theme has no inventory for
|
|
48
|
-
either and must not second-guess an address it cannot know about. A step 1
|
|
49
|
-
address is not checked either — the build resolved it against a real asset
|
|
50
|
-
record, so the question has already been answered.
|
|
51
|
-
|
|
52
|
-
Declining a hero image.
|
|
53
|
-
`banner: none` on a hand-authored page, and a blank `data.banner` on a note,
|
|
54
|
-
render the band with no image at all — the title, the palette
|
|
55
|
-
and the .hero-with-image gradient, which is what gives the band its presence.
|
|
56
|
-
This is not the same as having no banner yet: a package may have a standing
|
|
57
|
-
editorial reason to publish no imagery, and the fan-material carve-outs do.
|
|
58
|
-
Falling back to a default for them would substitute artwork where the
|
|
59
|
-
considered answer was "none", so declining has to be sayable.
|
|
60
|
-
*/ -}}
|
|
61
|
-
|
|
62
|
-
{{- /* The order above, the `none` decision, the type-to-banner mapping in
|
|
63
|
-
`data/banner-kinds.yaml` and the declared-existence check all live in
|
|
64
|
-
`banner-url.html`, which a derived landing card calls too. A hero band
|
|
65
|
-
always wants the default for its page's kind; a card never does. A page
|
|
66
|
-
with no type gets `default`. */ -}}
|
|
67
|
-
{{- $type := .Params.type | default "" -}}
|
|
68
|
-
{{- $bannerURL := partial "banner-url.html" (dict
|
|
69
|
-
"site" .Site
|
|
70
|
-
"data" .Params.data
|
|
71
|
-
"banner" .Params.banner
|
|
72
|
-
"type" $type
|
|
73
|
-
"subType" .Params.subType
|
|
74
|
-
"category" .Params.category
|
|
75
|
-
"subtype" (cond (eq $type "") "default" "")
|
|
76
|
-
"context" .RelPermalink) -}}
|
|
77
|
-
|
|
78
|
-
<section class="hero hero-with-image"{{ with $bannerURL }} style="background-image: url('{{ . }}');"{{ end }}>
|
|
79
|
-
<div class="hero-inner" data-pagefind-ignore>
|
|
80
|
-
<h1>{{ .Title }}</h1>
|
|
81
|
-
{{- with .Params.description }}
|
|
82
|
-
<p class="hero-tagline">{{ . }}</p>
|
|
83
|
-
{{- end }}
|
|
84
|
-
</div>
|
|
85
|
-
</section>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
One entry of a `runin` group or a `list` section.
|
|
3
|
-
|
|
4
|
-
An entry is `{lead, text, url}`. It links when the build reached the page it
|
|
5
|
-
names, and keeps its words when it did not — a panel naming something this
|
|
6
|
-
site does not publish is better than a panel silently one entry short.
|
|
7
|
-
`lead`, where present, is plain text set before the link, so a line such as
|
|
8
|
-
a membership links the body's name and nothing else.
|
|
9
|
-
|
|
10
|
-
Takes `entry` and the `class` its medium gives it.
|
|
11
|
-
*/ -}}
|
|
12
|
-
{{- $entry := .entry -}}
|
|
13
|
-
{{- with $entry.lead }}{{ . }}{{ end -}}
|
|
14
|
-
{{- with $entry.url -}}
|
|
15
|
-
<a class="{{ $.class }}" href="{{ . }}">{{ $entry.text }}</a>
|
|
16
|
-
{{- else -}}
|
|
17
|
-
<span class="{{ $.class }}">{{ $entry.text }}</span>
|
|
18
|
-
{{- end -}}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
What one infobox section holds, whatever its layout.
|
|
3
|
-
|
|
4
|
-
A section carries its content under the key its layout names — `rows`,
|
|
5
|
-
`cells`, `groups` or `entries` — so one lookup answers "is there anything to
|
|
6
|
-
draw?" for every layout there is. Returns a slice, empty when there is
|
|
7
|
-
nothing.
|
|
8
|
-
|
|
9
|
-
Takes the section. Returns the items.
|
|
10
|
-
|
|
11
|
-
An unrecognised layout returns nothing and says so once: the four layouts
|
|
12
|
-
are a closed set, so a fifth means this theme is older than the content it
|
|
13
|
-
is drawing, and a silently dropped section is the expensive way to find out.
|
|
14
|
-
*/ -}}
|
|
15
|
-
{{- $section := . -}}
|
|
16
|
-
{{- $layout := $section.layout | default "" -}}
|
|
17
|
-
{{- $key := index (dict "rows" "rows" "grid" "cells" "runin" "groups" "list" "entries") $layout -}}
|
|
18
|
-
{{- $items := slice -}}
|
|
19
|
-
{{- with $key -}}
|
|
20
|
-
{{- with index $section . -}}
|
|
21
|
-
{{- $items = . -}}
|
|
22
|
-
{{- end -}}
|
|
23
|
-
{{- else -}}
|
|
24
|
-
{{- warnidf "infobox-unknown-layout" "infobox: section layout %q is not one of rows, grid, runin or list, so the section is not drawn. Upgrade @heroiclands/hugo-theme to a version that draws it." $layout -}}
|
|
25
|
-
{{- end -}}
|
|
26
|
-
{{- return $items -}}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
One infobox section, arranged the way its `layout` says.
|
|
3
|
-
|
|
4
|
-
Four layouts, a closed set, and the key a section carries its content under
|
|
5
|
-
is what names it:
|
|
6
|
-
|
|
7
|
-
rows — label/value pairs, one per line `rows`
|
|
8
|
-
grid — short label/value cells packed together `cells`
|
|
9
|
-
runin — groups of comma-joined entries `groups`
|
|
10
|
-
list — one entry per line `entries`
|
|
11
|
-
|
|
12
|
-
Takes the section.
|
|
13
|
-
|
|
14
|
-
**A value of `0` is a value.** Armour that stops nothing edged is a fact
|
|
15
|
-
about the armour, so a cell is printed as it comes rather than guarded with
|
|
16
|
-
`with`, which would drop a zero along with an absence.
|
|
17
|
-
*/ -}}
|
|
18
|
-
{{- $section := . -}}
|
|
19
|
-
{{- $layout := $section.layout | default "" -}}
|
|
20
|
-
{{- if eq $layout "rows" -}}
|
|
21
|
-
<dl class="info-profile-grid">
|
|
22
|
-
{{- range $section.rows }}
|
|
23
|
-
<dt>{{ .label }}</dt>
|
|
24
|
-
<dd>{{ partial "infobox/value.html" . }}</dd>
|
|
25
|
-
{{- end }}
|
|
26
|
-
</dl>
|
|
27
|
-
{{- else if eq $layout "grid" -}}
|
|
28
|
-
<div class="info-attrs-grid">
|
|
29
|
-
{{- range $section.cells }}
|
|
30
|
-
<div class="info-attr">
|
|
31
|
-
<span class="attr-label">{{ .label }}</span>
|
|
32
|
-
<span class="attr-value">{{ .value }}</span>
|
|
33
|
-
</div>
|
|
34
|
-
{{- end }}
|
|
35
|
-
</div>
|
|
36
|
-
{{- else if eq $layout "runin" -}}
|
|
37
|
-
{{- range $section.groups }}
|
|
38
|
-
<p class="info-skill-line">
|
|
39
|
-
{{- with .label }}<span class="skill-cat">{{ . }}:</span>{{ end }}
|
|
40
|
-
<span class="skill-entries">
|
|
41
|
-
{{- range $i, $entry := .entries -}}
|
|
42
|
-
{{- if $i }}, {{ end -}}
|
|
43
|
-
{{- partial "infobox/entry.html" (dict "entry" $entry "class" "skill-entry") -}}
|
|
44
|
-
{{- end -}}
|
|
45
|
-
</span>
|
|
46
|
-
</p>
|
|
47
|
-
{{- end }}
|
|
48
|
-
{{- else if eq $layout "list" -}}
|
|
49
|
-
<ul class="info-mystical-list">
|
|
50
|
-
{{- range $section.entries }}
|
|
51
|
-
<li class="info-mystical-item">
|
|
52
|
-
{{- partial "infobox/entry.html" (dict "entry" . "class" "mystical-name") -}}
|
|
53
|
-
</li>
|
|
54
|
-
{{- end }}
|
|
55
|
-
</ul>
|
|
56
|
-
{{- end -}}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
One row's value, drawn by its `kind`.
|
|
3
|
-
|
|
4
|
-
Five kinds, a closed set:
|
|
5
|
-
|
|
6
|
-
text — a string
|
|
7
|
-
number — a number
|
|
8
|
-
link — `{text, url}`
|
|
9
|
-
links — a list of those, comma-joined
|
|
10
|
-
list — a list of strings, comma-joined
|
|
11
|
-
|
|
12
|
-
Takes the row.
|
|
13
|
-
|
|
14
|
-
**A value of `0` is a value**, so a number is printed as it comes rather
|
|
15
|
-
than guarded with `with`, which would drop a zero along with an absence.
|
|
16
|
-
Anything the build did not classify is set as text, which is what an
|
|
17
|
-
unlabelled scalar is.
|
|
18
|
-
*/ -}}
|
|
19
|
-
{{- $kind := .kind | default "text" -}}
|
|
20
|
-
{{- if eq $kind "link" -}}
|
|
21
|
-
{{- partial "infobox/entry.html" (dict "entry" .value "class" "info-link") -}}
|
|
22
|
-
{{- else if eq $kind "links" -}}
|
|
23
|
-
{{- range $i, $entry := .value -}}
|
|
24
|
-
{{- if $i }}, {{ end -}}
|
|
25
|
-
{{- partial "infobox/entry.html" (dict "entry" $entry "class" "info-link") -}}
|
|
26
|
-
{{- end -}}
|
|
27
|
-
{{- else if eq $kind "list" -}}
|
|
28
|
-
{{- delimit .value ", " -}}
|
|
29
|
-
{{- else if eq $kind "number" -}}
|
|
30
|
-
{{- /* A whole number is grouped, so a population reads as 500,000 rather
|
|
31
|
-
than as a run of digits a reader has to count. Grouping is
|
|
32
|
-
typography and belongs to the medium; the number itself is the
|
|
33
|
-
build's. Anything that is not a plain integer — a measurement, or a
|
|
34
|
-
value the build did not classify — is set as written. */ -}}
|
|
35
|
-
{{- $digits := printf "%v" .value -}}
|
|
36
|
-
{{- if findRE `^-?[0-9]+$` $digits -}}
|
|
37
|
-
{{- lang.FormatNumberCustom 0 (int $digits) -}}
|
|
38
|
-
{{- else -}}
|
|
39
|
-
{{- .value -}}
|
|
40
|
-
{{- end -}}
|
|
41
|
-
{{- else -}}
|
|
42
|
-
{{- .value -}}
|
|
43
|
-
{{- end -}}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
The infobox rail — every box a page declares, drawn in the order declared.
|
|
3
|
-
|
|
4
|
-
**The content is not decided here.** A page's `infoboxes:` front matter
|
|
5
|
-
carries an ordered list of boxes, each holding ordered sections, each holding
|
|
6
|
-
ordered rows, cells, groups or entries, already labelled. This partial and
|
|
7
|
-
the three under `infobox/` switch on a section's `layout` and a value's
|
|
8
|
-
`kind` and on nothing else — never on a note type, never on a field name.
|
|
9
|
-
That is what lets a field added to a type appear here with no edit.
|
|
10
|
-
|
|
11
|
-
A box is a `<details>` disclosure, open by default: native, accessible, and
|
|
12
|
-
no JavaScript. It is what lets several boxes stack for nothing — a note box
|
|
13
|
-
and one box per system are three summary lines when closed, rather than
|
|
14
|
-
three panels burying the prose.
|
|
15
|
-
|
|
16
|
-
Two kinds of box, and they answer emptiness differently:
|
|
17
|
-
|
|
18
|
-
- A **note box** with no section holding anything is not drawn. A heading
|
|
19
|
-
over nothing asserts a fact that is not there.
|
|
20
|
-
- A **system box** carries a `statement` where it has nothing to show, and
|
|
21
|
-
the statement is drawn in place of the sections. Which silence this is —
|
|
22
|
-
the system compiled no document, or it compiled one holding nothing the
|
|
23
|
-
profile has not already said — is decided by the build, because a reader
|
|
24
|
-
meeting one page cannot tell the two apart and neither can a template. A
|
|
25
|
-
system that does not map the note's type at all sends no box, and nothing
|
|
26
|
-
is drawn.
|
|
27
|
-
|
|
28
|
-
Returns an empty string when the page declares no box, so a caller can test
|
|
29
|
-
what comes back rather than reaching into the data itself.
|
|
30
|
-
*/ -}}
|
|
31
|
-
{{- range .Params.infoboxes -}}
|
|
32
|
-
{{- $box := . -}}
|
|
33
|
-
{{- $sections := slice -}}
|
|
34
|
-
{{- range $box.sections -}}
|
|
35
|
-
{{- if gt (len (partial "infobox/items.html" .)) 0 -}}
|
|
36
|
-
{{- $sections = $sections | append . -}}
|
|
37
|
-
{{- end -}}
|
|
38
|
-
{{- end -}}
|
|
39
|
-
{{- $system := eq ($box.kind | default "") "system" -}}
|
|
40
|
-
{{- if or $system (gt (len $sections) 0) }}
|
|
41
|
-
<details class="info-sidebar info-box{{ with $box.id }} info-box-{{ . }}{{ end }}" open data-pagefind-ignore>
|
|
42
|
-
<summary class="info-sidebar-title"><h2>{{ $box.title }}</h2></summary>
|
|
43
|
-
{{- with $box.statement }}
|
|
44
|
-
<p class="info-statement">{{ . }}</p>
|
|
45
|
-
{{- else }}
|
|
46
|
-
{{- range $sections }}
|
|
47
|
-
<section class="info-section{{ with .id }} info-section-{{ . }}{{ end }}">
|
|
48
|
-
{{- with .label }}
|
|
49
|
-
<h3 class="info-section-title">{{ . }}</h3>
|
|
50
|
-
{{- end }}
|
|
51
|
-
{{ partial "infobox/section.html" . }}
|
|
52
|
-
</section>
|
|
53
|
-
{{- end }}
|
|
54
|
-
{{- end }}
|
|
55
|
-
</details>
|
|
56
|
-
{{- end -}}
|
|
57
|
-
{{- end -}}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
A note's body — the infobox rail, the content, and prev/next through its
|
|
3
|
-
catalog. Shared by `_default/single.html`, for a page, and `index.html`,
|
|
4
|
-
for the homepage note rendered as a page: the two are the same family, and
|
|
5
|
-
this is the shape they share. The caller renders the hero; this partial
|
|
6
|
-
starts at the article.
|
|
7
|
-
|
|
8
|
-
Context: the page.
|
|
9
|
-
*/ -}}
|
|
10
|
-
{{- /* The boxes a page declares, drawn by one generic renderer. What each box
|
|
11
|
-
holds is decided by the build and carried in `infoboxes:` front matter;
|
|
12
|
-
this file decides only where the rail goes. A page declaring none gets
|
|
13
|
-
back an empty string and no rail. */ -}}
|
|
14
|
-
{{- $infobox := partial "infobox.html" . -}}
|
|
15
|
-
{{- $hasSidebar := ne (trim $infobox " \r\n\t") "" -}}
|
|
16
|
-
|
|
17
|
-
{{- /* The TOC partial only emits markup when the page has more than
|
|
18
|
-
3 H2 headings. To avoid laying the page out as a two-column
|
|
19
|
-
grid for nothing, detect the same condition here so we can
|
|
20
|
-
apply the `.single-with-toc` class conditionally. A page that
|
|
21
|
-
already has a rail gets its contents list at the foot of that
|
|
22
|
-
rail rather than a second column. */ -}}
|
|
23
|
-
{{- $h2Count := len (findRE `(?m)^##\s+\S` (.RawContent | default "")) -}}
|
|
24
|
-
{{- $hasToc := gt $h2Count 3 -}}
|
|
25
|
-
|
|
26
|
-
{{- /* A draft page states it, which also decides the article's first grid
|
|
27
|
-
row — see the notice partial and `.single-with-notice`. */ -}}
|
|
28
|
-
{{- $isDraft := partial "draft-state.html" . -}}
|
|
29
|
-
|
|
30
|
-
<article class="single{{ if $hasSidebar }} single-with-sidebar{{ else if $hasToc }} single-with-toc{{ end }}{{ if $isDraft }} single-with-notice{{ end }}">
|
|
31
|
-
{{- /* A statement about the page rather than about its subject, so it leads
|
|
32
|
-
the article: above the rail and above the prose, at every width. It
|
|
33
|
-
spans the grid for that reason — inside `.single-content` it would sit
|
|
34
|
-
beside the boxes on a wide screen and below them on a narrow one,
|
|
35
|
-
where the rail comes first. */ -}}
|
|
36
|
-
{{ partial "draft-notice.html" . }}
|
|
37
|
-
{{- /* Filter values a search can narrow on, invisible and excluded from
|
|
38
|
-
indexing themselves — `data-pagefind-filter` is read wherever it
|
|
39
|
-
sits, `data-pagefind-body`/`data-pagefind-ignore` scoping included
|
|
40
|
-
(see the README's "Search" section). */ -}}
|
|
41
|
-
{{- with .Params.type }}<span data-pagefind-filter="type" hidden>{{ . }}</span>{{ end -}}
|
|
42
|
-
{{- with .Params.package }}<span data-pagefind-filter="package" hidden>{{ . }}</span>{{ end -}}
|
|
43
|
-
{{- if $hasSidebar }}
|
|
44
|
-
{{- /* The rail comes first in document order, because the infobox is
|
|
45
|
-
generated content prepended before the prose: on a narrow screen the
|
|
46
|
-
grid collapses and the boxes land where they were written, above the
|
|
47
|
-
text they summarise. */ -}}
|
|
48
|
-
<aside class="info-rail">
|
|
49
|
-
{{ $infobox }}
|
|
50
|
-
{{ if $hasToc }}{{ partial "toc.html" . }}{{ end }}
|
|
51
|
-
</aside>
|
|
52
|
-
{{- end }}
|
|
53
|
-
<div class="single-content">
|
|
54
|
-
{{- $tagChips := partial "tags.html" . -}}
|
|
55
|
-
{{- $beingSubtype := "" -}}
|
|
56
|
-
{{- if and (eq .Params.type "being") .Params.subType -}}
|
|
57
|
-
{{- $beingSubtype = cond (eq .Params.subType "npc") "NPC" (humanize .Params.subType) -}}
|
|
58
|
-
{{- end -}}
|
|
59
|
-
{{ if or .Params.date (ne (trim $tagChips " \r\n\t") "") $beingSubtype }}
|
|
60
|
-
<div class="single-meta">
|
|
61
|
-
{{ if .Params.date }}
|
|
62
|
-
<time class="single-date" datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "January 2, 2006" }}</time>
|
|
63
|
-
{{ end }}
|
|
64
|
-
{{- with $beingSubtype }}<span class="single-subtype">{{ . }}</span>{{ end }}
|
|
65
|
-
{{ $tagChips }}
|
|
66
|
-
</div>
|
|
67
|
-
{{ end }}
|
|
68
|
-
|
|
69
|
-
<div class="single-body" data-pagefind-body>
|
|
70
|
-
{{ partial "dictionary-lists.html" .Content }}
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
{{ partial "related.html" . }}
|
|
74
|
-
|
|
75
|
-
{{- /*
|
|
76
|
-
Prev/next walk the page's own catalog, not its Hugo section (issue #48).
|
|
77
|
-
`.PrevInSection` / `.NextInSection` mean "the neighbouring page in this
|
|
78
|
-
directory", which was the same thing only while a page lived in a
|
|
79
|
-
directory named for its catalog. `@heroiclands/package-build`
|
|
80
|
-
(package-build#204) emits every content page flat under the content
|
|
81
|
-
mount, so a consumer's whole catalog is one section and these two links
|
|
82
|
-
would walk every page of every type — reading through the afflictions
|
|
83
|
-
silently left them.
|
|
84
|
-
|
|
85
|
-
So where a section holds more than one catalog, the sibling set is
|
|
86
|
-
narrowed to the pages sharing this page's catalog key. A section holding
|
|
87
|
-
a single catalog is left alone, because `.PrevInSection` already walks
|
|
88
|
-
exactly that catalog there — which is what makes this a no-op for a site
|
|
89
|
-
whose pages still sit in catalog-named directories. A page declaring no
|
|
90
|
-
catalog keeps the section-scoped result. The home page declares no
|
|
91
|
-
catalog and has no section siblings either way.
|
|
92
|
-
|
|
93
|
-
The catalog key: `type` for structured content, whose type *is* its
|
|
94
|
-
catalog (`affliction`, `skill`, `weapongear`, …); for `type: doc`, which
|
|
95
|
-
is prose rather than a catalog of its own, `subType` (what package-build
|
|
96
|
-
compiles from a note's classification) or, failing that, `category`
|
|
97
|
-
(what a documentation tree mounted from a repository directory
|
|
98
|
-
carries); "" for a page with no `type`, which has no catalog.
|
|
99
|
-
|
|
100
|
-
Ordering follows Hugo's: in a page collection `.PrevInSection` is the
|
|
101
|
-
*following* entry and `.NextInSection` the preceding one, so the
|
|
102
|
-
neighbours are taken at index+1 and index-1 respectively.
|
|
103
|
-
*/ -}}
|
|
104
|
-
{{- $prev := .PrevInSection -}}
|
|
105
|
-
{{- $next := .NextInSection -}}
|
|
106
|
-
{{- $type := .Params.type | default "" -}}
|
|
107
|
-
{{- $key := $type -}}
|
|
108
|
-
{{- if eq $type "doc" -}}
|
|
109
|
-
{{- $key = .Params.subType | default (.Params.category | default "") -}}
|
|
110
|
-
{{- end -}}
|
|
111
|
-
{{- $siblings := slice -}}
|
|
112
|
-
{{- with .CurrentSection -}}
|
|
113
|
-
{{- if $key -}}
|
|
114
|
-
{{- $mixed := false -}}
|
|
115
|
-
{{- $matching := slice -}}
|
|
116
|
-
{{- range .RegularPages -}}
|
|
117
|
-
{{- $pageType := .Params.type | default "" -}}
|
|
118
|
-
{{- $pageKey := $pageType -}}
|
|
119
|
-
{{- if eq $pageType "doc" -}}
|
|
120
|
-
{{- $pageKey = .Params.subType | default (.Params.category | default "") -}}
|
|
121
|
-
{{- end -}}
|
|
122
|
-
{{- if eq $pageKey $key -}}
|
|
123
|
-
{{- $matching = $matching | append . -}}
|
|
124
|
-
{{- else if ne $pageKey "" -}}
|
|
125
|
-
{{- $mixed = true -}}
|
|
126
|
-
{{- end -}}
|
|
127
|
-
{{- end -}}
|
|
128
|
-
{{- if $mixed -}}{{- $siblings = $matching -}}{{- end -}}
|
|
129
|
-
{{- end -}}
|
|
130
|
-
{{- end -}}
|
|
131
|
-
{{- if $siblings -}}
|
|
132
|
-
{{- $index := -1 -}}
|
|
133
|
-
{{- range $i, $p := $siblings -}}
|
|
134
|
-
{{- if eq $p.Path $.Path -}}{{- $index = $i -}}{{- end -}}
|
|
135
|
-
{{- end -}}
|
|
136
|
-
{{- if ge $index 0 -}}
|
|
137
|
-
{{- $prev = "" -}}
|
|
138
|
-
{{- $next = "" -}}
|
|
139
|
-
{{- if lt (add $index 1) (len $siblings) -}}{{- $prev = index $siblings (add $index 1) -}}{{- end -}}
|
|
140
|
-
{{- if gt $index 0 -}}{{- $next = index $siblings (sub $index 1) -}}{{- end -}}
|
|
141
|
-
{{- end -}}
|
|
142
|
-
{{- end -}}
|
|
143
|
-
<nav class="single-nav">
|
|
144
|
-
{{ with $prev }}<a href="{{ .Permalink }}" class="nav-prev">← {{ .Title }}</a>{{ end }}
|
|
145
|
-
{{ with $next }}<a href="{{ .Permalink }}" class="nav-next">{{ .Title }} →</a>{{ end }}
|
|
146
|
-
</nav>
|
|
147
|
-
</div>
|
|
148
|
-
|
|
149
|
-
{{ if and (not $hasSidebar) $hasToc }}
|
|
150
|
-
{{ partial "toc.html" . }}
|
|
151
|
-
{{ end }}
|
|
152
|
-
</article>
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
{{- /*
|
|
2
|
-
Related partial.
|
|
3
|
-
|
|
4
|
-
Renders a compact "Related" block at the bottom of a single page from the
|
|
5
|
-
page's `related` front matter, if it carries any.
|
|
6
|
-
|
|
7
|
-
Structure in front matter:
|
|
8
|
-
related:
|
|
9
|
-
seeAlso: [{ title, url, type, gloss? }, ...] # deliberate references
|
|
10
|
-
backlinks: [{ title, url, type }, ...] # pages that link here
|
|
11
|
-
mentions: [{ title, url, type }, ...] # pages this page links to
|
|
12
|
-
|
|
13
|
-
Rendering strategy:
|
|
14
|
-
- Render deliberate references in authored order, with their glosses.
|
|
15
|
-
- Merge both inferred directions into a single deduped pool (direction
|
|
16
|
-
doesn't matter to a reader — a connection is a connection).
|
|
17
|
-
- Group by the referenced page's `type`.
|
|
18
|
-
- Emit one labelled group per type, its entries laid out as a
|
|
19
|
-
CSS grid (`repeat(auto-fill, minmax(14em, 1fr))`) so a wide
|
|
20
|
-
screen shows two or three columns and a narrow one falls back
|
|
21
|
-
to a single column with no media query.
|
|
22
|
-
- The whole block is wrapped in a bordered, tinted card so it
|
|
23
|
-
visually sets off the end of the article.
|
|
24
|
-
|
|
25
|
-
Silent disappear: a page with no `related`, or whose lists are all
|
|
26
|
-
empty, emits nothing at all rather than an empty heading. The rows are
|
|
27
|
-
computed first and the <section> is rendered only when there is something
|
|
28
|
-
to put in it.
|
|
29
|
-
|
|
30
|
-
`return` cannot bail out early here. It sets the partial's
|
|
31
|
-
return value; it does not discard template text the partial has already
|
|
32
|
-
emitted, so a guard written that way still prints the empty shell. Hence
|
|
33
|
-
the emptiness test wraps the markup instead of preceding it.
|
|
34
|
-
*/ -}}
|
|
35
|
-
|
|
36
|
-
{{- /* `default dict` keeps the lookups below safe on a page with no
|
|
37
|
-
`related` at all, so the whole computation stays flat. */ -}}
|
|
38
|
-
{{- $rel := .Params.related | default dict -}}
|
|
39
|
-
{{- $seeAlso := or $rel.seealso slice -}}
|
|
40
|
-
{{- $backlinks := or $rel.backlinks slice -}}
|
|
41
|
-
{{- $mentions := or $rel.mentions slice -}}
|
|
42
|
-
|
|
43
|
-
{{- /* Merge both directions, deduped by URL. `union` can't hash
|
|
44
|
-
slices of maps, so we walk the two lists in order and dedupe
|
|
45
|
-
by URL manually. Deliberate references take priority; mentions
|
|
46
|
-
precede backlinks among inferred connections. */ -}}
|
|
47
|
-
{{- $seen := slice -}}
|
|
48
|
-
{{- $merged := slice -}}
|
|
49
|
-
{{- $deliberate := slice -}}
|
|
50
|
-
{{- range $seeAlso -}}
|
|
51
|
-
{{- if not (in $seen .url) -}}
|
|
52
|
-
{{- $seen = $seen | append .url -}}
|
|
53
|
-
{{- $deliberate = $deliberate | append . -}}
|
|
54
|
-
{{- end -}}
|
|
55
|
-
{{- end -}}
|
|
56
|
-
{{- range $mentions -}}
|
|
57
|
-
{{- if not (in $seen .url) -}}
|
|
58
|
-
{{- $seen = $seen | append .url -}}
|
|
59
|
-
{{- $merged = $merged | append . -}}
|
|
60
|
-
{{- end -}}
|
|
61
|
-
{{- end -}}
|
|
62
|
-
{{- range $backlinks -}}
|
|
63
|
-
{{- if not (in $seen .url) -}}
|
|
64
|
-
{{- $seen = $seen | append .url -}}
|
|
65
|
-
{{- $merged = $merged | append . -}}
|
|
66
|
-
{{- end -}}
|
|
67
|
-
{{- end -}}
|
|
68
|
-
|
|
69
|
-
{{- /* Plural, human-readable label for each type. Falls back to
|
|
70
|
-
`humanize` for any type not listed here. */ -}}
|
|
71
|
-
{{- $labels := dict
|
|
72
|
-
"affiliation" "Affiliations"
|
|
73
|
-
"being" "Beings"
|
|
74
|
-
"blog-post" "Posts"
|
|
75
|
-
"character" "People"
|
|
76
|
-
"continent" "Continents"
|
|
77
|
-
"creature" "Creatures"
|
|
78
|
-
"faith" "Faiths"
|
|
79
|
-
"language" "Languages"
|
|
80
|
-
"lore" "Lore"
|
|
81
|
-
"organization" "Organizations"
|
|
82
|
-
"page" "Pages"
|
|
83
|
-
"pantheon" "Pantheons"
|
|
84
|
-
"people" "Peoples"
|
|
85
|
-
"polity" "Polities"
|
|
86
|
-
"project-page" "Projects"
|
|
87
|
-
"region" "Regions"
|
|
88
|
-
"religion" "Religions"
|
|
89
|
-
"settlement" "Settlements"
|
|
90
|
-
"site" "Places"
|
|
91
|
-
"world" "Worlds"
|
|
92
|
-
-}}
|
|
93
|
-
|
|
94
|
-
{{- /* Group refs by type, preserving alphabetical order within a
|
|
95
|
-
group (the input lists arrive already sorted). */ -}}
|
|
96
|
-
{{- $groups := dict -}}
|
|
97
|
-
{{- range $merged -}}
|
|
98
|
-
{{- $t := .type | default "page" -}}
|
|
99
|
-
{{- $existing := index $groups $t | default slice -}}
|
|
100
|
-
{{- $groups = merge $groups (dict $t ($existing | append .)) -}}
|
|
101
|
-
{{- end -}}
|
|
102
|
-
|
|
103
|
-
{{- /* Sort the group keys alphabetically by their rendered label
|
|
104
|
-
so the list reads A → Z regardless of insertion order. */ -}}
|
|
105
|
-
{{- $rows := slice -}}
|
|
106
|
-
{{- range $type, $refs := $groups -}}
|
|
107
|
-
{{- $label := index $labels $type | default (humanize $type) -}}
|
|
108
|
-
{{- $rows = $rows | append (dict "label" $label "type" $type "refs" $refs) -}}
|
|
109
|
-
{{- end -}}
|
|
110
|
-
{{- if $rows -}}
|
|
111
|
-
{{- $rows = sort $rows "label" "asc" -}}
|
|
112
|
-
{{- end -}}
|
|
113
|
-
|
|
114
|
-
{{- if or $rows $deliberate -}}
|
|
115
|
-
<section class="related" aria-labelledby="related-heading" data-pagefind-ignore>
|
|
116
|
-
<h2 id="related-heading" class="related-heading">Related</h2>
|
|
117
|
-
{{- with $deliberate }}
|
|
118
|
-
<div class="related-group">
|
|
119
|
-
<h3 class="related-group-label">See also</h3>
|
|
120
|
-
<ul class="related-group-grid">
|
|
121
|
-
{{- range . }}
|
|
122
|
-
<li><a href="{{ .url }}">{{ .title }}</a>{{ with .gloss }} — {{ . }}{{ end }}</li>
|
|
123
|
-
{{- end }}
|
|
124
|
-
</ul>
|
|
125
|
-
</div>
|
|
126
|
-
{{- end }}
|
|
127
|
-
{{- range $rows }}
|
|
128
|
-
<div class="related-group">
|
|
129
|
-
<h3 class="related-group-label">{{ .label }}</h3>
|
|
130
|
-
<ul class="related-group-grid">
|
|
131
|
-
{{- range .refs }}
|
|
132
|
-
<li><a href="{{ .url }}">{{ .title }}</a></li>
|
|
133
|
-
{{- end }}
|
|
134
|
-
</ul>
|
|
135
|
-
</div>
|
|
136
|
-
{{- end }}
|
|
137
|
-
</section>
|
|
138
|
-
{{ end -}}
|