@heroiclands/package-build 23.12.8 → 24.0.0
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 +84 -0
- package/README.md +3 -2
- package/assets/preview/gitea.ini +12 -7
- package/assets/styles/content-base.css +293 -24
- package/bin/content-commands.mjs +370 -213
- package/bin/package-build-preview.mjs +2 -2
- 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 +110 -89
- package/docs/authoring/links-and-markup.md +469 -97
- package/docs/commands.md +259 -78
- package/docs/configuration.md +211 -103
- package/docs/content-format.md +4 -4
- package/docs/diagnostics.md +44 -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 +112 -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 +677 -319
- package/docs/reference/note-types.md +47 -10
- package/docs/reference/theme-pages.md +178 -108
- package/docs/source-preview.md +16 -2
- package/engine/anchors.mjs +2 -2
- package/engine/asset-shipping.mjs +22 -10
- package/engine/base-compiler.mjs +62 -104
- package/engine/changelog-lint.mjs +1 -1
- package/engine/code-fences.mjs +3 -3
- package/engine/content-address.mjs +1 -1
- package/engine/content-alerts.mjs +8 -4
- package/engine/content-blocks.mjs +29 -14
- package/engine/content-embeds.mjs +1 -1
- package/engine/content-expand.mjs +376 -0
- package/engine/content-figures.mjs +18 -11
- package/engine/content-format.yaml +8 -0
- package/engine/content-glyphs.mjs +213 -0
- package/engine/content-images.mjs +6 -7
- package/engine/content-index.mjs +1 -1
- 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 +376 -43
- package/engine/content-spans.mjs +6 -3
- package/engine/content-styles.mjs +91 -0
- package/engine/content-symbols.mjs +186 -0
- package/engine/content-verse.mjs +738 -0
- package/engine/core-report.mjs +169 -0
- package/engine/core-vocabulary.mjs +208 -0
- package/engine/dictionary-html.mjs +119 -0
- package/engine/dictionary-rows.mjs +15 -4
- package/engine/field-reference.mjs +5 -5
- package/engine/first-use.mjs +17 -27
- 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/key-case-collisions.mjs +136 -0
- package/engine/language-data.mjs +203 -6
- package/engine/language-rows.mjs +8 -2
- package/engine/language-terms.mjs +186 -16
- package/engine/language-words.mjs +12 -0
- package/engine/logographic.mjs +255 -0
- package/engine/map-lexicon.mjs +262 -47
- 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/names.mjs +36 -9
- package/engine/note-matter.mjs +66 -0
- package/engine/note-vocabulary.mjs +187 -3
- package/engine/pdf-build.mjs +69 -133
- package/engine/pdf-render.mjs +205 -58
- 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/read-stdin.mjs +29 -0
- package/engine/run-rows.mjs +2 -2
- package/engine/run-words.mjs +6 -112
- 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 +260 -315
- 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 +52 -525
- package/engine/site-render.mjs +593 -0
- package/engine/site-root.mjs +22 -13
- package/engine/site-search.mjs +161 -0
- package/engine/site-serve.mjs +273 -0
- package/engine/site-theme-banner.mjs +154 -0
- package/engine/site-theme-urls.mjs +125 -0
- package/engine/site-theme.mjs +926 -0
- package/engine/sql-tables.mjs +20 -3
- 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 +364 -0
- package/engine/word-rows.mjs +12 -2
- package/engine/word-terms.mjs +38 -4
- package/manifest.mjs +3 -4
- package/package.json +11 -8
- 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 +106 -14
- 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/code-fences.d.mts +3 -3
- 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 +70 -4
- 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/content-verse.d.mts +240 -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/dictionary-rows.d.mts +10 -0
- package/types/engine/field-reference.d.mts +2 -2
- 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/key-case-collisions.d.mts +28 -0
- package/types/engine/language-data.d.mts +0 -2
- package/types/engine/language-terms.d.mts +24 -2
- package/types/engine/logographic.d.mts +45 -0
- package/types/engine/map-lexicon.d.mts +66 -13
- 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/names.d.mts +34 -3
- package/types/engine/note-matter.d.mts +48 -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/read-stdin.d.mts +11 -0
- package/types/engine/run-rows.d.mts +2 -2
- package/types/engine/run-words.d.mts +0 -15
- 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-render.d.mts +171 -0
- package/types/engine/site-root.d.mts +12 -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/sql-tables.d.mts +4 -1
- 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 +83 -0
- 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/content-poetry.mjs +0 -240
- 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/content-poetry.d.mts +0 -58
- 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
|
@@ -7,8 +7,9 @@ subType: reference
|
|
|
7
7
|
|
|
8
8
|
# What the theme draws
|
|
9
9
|
|
|
10
|
-
`package-build site`
|
|
11
|
-
|
|
10
|
+
`package-build site build` settles a page's front matter and body; the shared
|
|
11
|
+
site theme draws the page around them. This reference describes that second
|
|
12
|
+
half —
|
|
12
13
|
the infobox rail, the hero band, the generated sections, the related card,
|
|
13
14
|
search, and the markup an image or a figure renders as — and names the
|
|
14
15
|
classes a consumer styles against.
|
|
@@ -30,7 +31,7 @@ A place’s Government row links to its authored governing affiliation. Explicit
|
|
|
30
31
|
The toolchain settles what each box holds and in what order — see
|
|
31
32
|
[the infobox](format-details.md#the-infobox) for the field semantics, the
|
|
32
33
|
three states a system box can say, and the four section layouts a box is
|
|
33
|
-
built from. On the website, `
|
|
34
|
+
built from. On the website, the `infobox` partial draws the whole list by
|
|
34
35
|
switching on a section's `layout` and a value's `kind`, never on a note type
|
|
35
36
|
or a field name:
|
|
36
37
|
|
|
@@ -121,13 +122,13 @@ A page whose front matter declares no `infoboxes:` renders no rail.
|
|
|
121
122
|
|
|
122
123
|
## The hero banner
|
|
123
124
|
|
|
124
|
-
Nearly every page opens with a hero band, and `
|
|
125
|
+
Nearly every page opens with a hero band, and the `hero-banner` partial
|
|
125
126
|
decides what sits behind it. A page arrives with its hero image stated in one
|
|
126
127
|
of two ways, and the difference is who resolved it: a content page carries
|
|
127
128
|
`data.banner`, which the build resolved from the asset Address the note
|
|
128
129
|
declared into the address its asset host serves; a hand-authored page carries
|
|
129
130
|
a top-level `banner:`, which the theme resolves against `params.cdnBaseURL`
|
|
130
|
-
(see [`params.cdnBaseURL`](../configuration.md#the-
|
|
131
|
+
(see [`params.cdnBaseURL`](../configuration.md#what-the-site-build-reads)).
|
|
131
132
|
|
|
132
133
|
**Resolution order.**
|
|
133
134
|
|
|
@@ -143,13 +144,13 @@ a top-level `banner:`, which the theme resolves against `params.cdnBaseURL`
|
|
|
143
144
|
4. `images/banners/default.webp` — when the page has no type, **and** whenever
|
|
144
145
|
the name picked by 2 or 3 is not in the declared inventory.
|
|
145
146
|
|
|
146
|
-
**Why step 4 is a declaration, not a test.**
|
|
147
|
-
whether a URL exists, so a banner that was never drawn would 404 in
|
|
148
|
-
the band renders with its title, palette and gradient intact behind
|
|
149
|
-
and nothing fails: not the build, not
|
|
150
|
-
`
|
|
151
|
-
|
|
152
|
-
|
|
147
|
+
**Why step 4 is a declaration, not a test.** The build cannot ask a remote
|
|
148
|
+
host whether a URL exists, so a banner that was never drawn would 404 in
|
|
149
|
+
silence — the band renders with its title, palette and gradient intact behind
|
|
150
|
+
a dead URL, and nothing fails: not the build, not the deploy guard.
|
|
151
|
+
`banners.yaml` is the declaration that stands in for the test the template
|
|
152
|
+
cannot make. A name listed in its `available` is asserted to exist; a resolved
|
|
153
|
+
name that is absent falls back to `fallback`, and the build reports one
|
|
153
154
|
deduplicated warning naming the missing banner and the first page that wanted
|
|
154
155
|
it. The fallback applies only to a relative path landing directly in the
|
|
155
156
|
declared `dir` — an absolute URL, and a fragment pointing anywhere else under
|
|
@@ -158,7 +159,7 @@ either and must not second-guess an address it cannot know about. A step 1
|
|
|
158
159
|
address is not checked for the same reason: the question has already been
|
|
159
160
|
answered upstream.
|
|
160
161
|
|
|
161
|
-
**The kind mapping.** `
|
|
162
|
+
**The kind mapping.** `banner-kinds.yaml` declares, once, which banner a
|
|
162
163
|
page of each note `type` opens with. A type maps to one banner name for all of
|
|
163
164
|
its subTypes, or to a table that names a banner for every subType the note
|
|
164
165
|
vocabulary declares for it:
|
|
@@ -178,20 +179,15 @@ kinds:
|
|
|
178
179
|
warning. A type missing from the file resolves to its own name, so a kind with
|
|
179
180
|
no declared art still produces the missing-banner warning. The lint check and
|
|
180
181
|
the test suite fail on a mapped name that `banners.yaml` does not declare, and
|
|
181
|
-
on a type or subType of the note vocabulary that the mapping omits.
|
|
182
|
-
publishing its own artwork set ships its own `data/banner-kinds.yaml` beside
|
|
183
|
-
its `data/banners.yaml`.
|
|
182
|
+
on a type or subType of the note vocabulary that the mapping omits.
|
|
184
183
|
|
|
185
|
-
**One resolver.** The order above lives in
|
|
186
|
-
returns a URL or an empty string; `hero-banner
|
|
187
|
-
|
|
184
|
+
**One resolver.** The order above lives in one function of the engine, which
|
|
185
|
+
returns a URL or an empty string; the `hero-banner` partial is given the
|
|
186
|
+
result.
|
|
188
187
|
|
|
189
|
-
**Keeping the inventory honest.** The lint check over `
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
published page. A consumer publishing its own artwork set replaces the whole
|
|
193
|
-
list by shipping its own `data/banners.yaml`, which Hugo reads in preference
|
|
194
|
-
to the theme's bundled one, and can run the same check against it.
|
|
188
|
+
**Keeping the inventory honest.** The lint check over `banners.yaml` fetches
|
|
189
|
+
every declared name from the asset host and fails on any non-200 response, so
|
|
190
|
+
a name added optimistically is caught here rather than on a published page.
|
|
195
191
|
|
|
196
192
|
**Declining a hero image.** `banner: none` on a hand-authored page, and a
|
|
197
193
|
blank `data.banner` on a note (which the build emits for `data.banner: none`),
|
|
@@ -246,7 +242,7 @@ is the way to choose different contents for one, or to turn one off.
|
|
|
246
242
|
|
|
247
243
|
## The related card
|
|
248
244
|
|
|
249
|
-
`
|
|
245
|
+
The `related` partial renders a bordered "Related" card below the body,
|
|
250
246
|
listing the pages connected to this one. The build emits this front matter on
|
|
251
247
|
every content page; what links to a page is a fact about every other page, so
|
|
252
248
|
an authored `related:` is refused and dropped:
|
|
@@ -335,13 +331,88 @@ Caption classes are unrestricted. The built-in `border` class draws the block as
|
|
|
335
331
|
| `.content-figure-label` | the label, number and caption together |
|
|
336
332
|
| `.border` | the block as a boxed aside |
|
|
337
333
|
|
|
334
|
+
## Verse
|
|
335
|
+
|
|
336
|
+
A verse fence reaches the page as a `.verse` block holding a paragraph per
|
|
337
|
+
stanza and a `.verse-line` per line, its indent level as `i1` to `i8`. Its
|
|
338
|
+
keys reach the block as written, `lang` as its language and the rest as
|
|
339
|
+
`data-*` attributes. A numbered verse also carries `.verse-numbered`, and each
|
|
340
|
+
numbered line starts with its `.verse-number`.
|
|
341
|
+
|
|
342
|
+
A [verse in columns](../authoring/links-and-markup.md#verse-in-columns) also
|
|
343
|
+
carries `.verse-columns`, and each verse line is one `.verse-row`:
|
|
344
|
+
|
|
345
|
+
```html
|
|
346
|
+
<div class="verse verse-columns verse-numbered" lang="art-x-vyl" data-numstep="5">
|
|
347
|
+
<p>
|
|
348
|
+
<span class="verse-row"
|
|
349
|
+
><span class="verse-number"></span
|
|
350
|
+
><span class="verse-column"
|
|
351
|
+
><span class="verse-part"
|
|
352
|
+
><span class="script hl-semaron-kuriale" lang="art-x-vyl">…</span></span
|
|
353
|
+
></span
|
|
354
|
+
><span class="verse-column"
|
|
355
|
+
><span class="verse-part"><span lang="en">The hallowed boundary I sing,</span></span
|
|
356
|
+
><span class="verse-part verse-secondary"
|
|
357
|
+
><span lang="art-x-vyl">Thiruthriman sorimamen,</span></span
|
|
358
|
+
></span
|
|
359
|
+
></span
|
|
360
|
+
>
|
|
361
|
+
…
|
|
362
|
+
</p>
|
|
363
|
+
</div>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
A numbered verse in columns gives every row a `.verse-number`, empty on the
|
|
367
|
+
lines it does not number, so the columns stay aligned. A part whose text runs
|
|
368
|
+
right to left carries `dir="rtl"`. Each row is its own grid, so a long line
|
|
369
|
+
keeps its partner level with it. Below a block width of `32rem` a row stacks
|
|
370
|
+
its columns in order; it is a container query, so a narrow journal window
|
|
371
|
+
stacks as well. The Foundry stylesheet draws the same.
|
|
372
|
+
|
|
373
|
+
| class | drawn as |
|
|
374
|
+
| ------------------ | ------------------------------------------------------------- |
|
|
375
|
+
| `.verse` | the poem |
|
|
376
|
+
| `.verse-line` | one line of a poem without columns |
|
|
377
|
+
| `.verse-numbered` | a numbered poem, with a margin for its numbers |
|
|
378
|
+
| `.verse-number` | a line's number, muted |
|
|
379
|
+
| `.verse-columns` | a poem in columns, and the container its rows are measured by |
|
|
380
|
+
| `.verse-row` | one verse line: its number and its columns |
|
|
381
|
+
| `.verse-column` | one column, its entries stacked |
|
|
382
|
+
| `.verse-part` | one entry's text, in the body serif unless its face sets it |
|
|
383
|
+
| `.verse-secondary` | every entry after a column's first, muted |
|
|
384
|
+
|
|
385
|
+
## Emphasis in a script
|
|
386
|
+
|
|
387
|
+
Emphasis inside a run set in a face stays an `<em>` or a `<strong>`, and its
|
|
388
|
+
class names the convention its language or script states (see
|
|
389
|
+
[script notes and emphasis](format-details.md#script-notes-and-emphasis)):
|
|
390
|
+
|
|
391
|
+
| class | drawn as |
|
|
392
|
+
| ---------------- | ----------------------------- |
|
|
393
|
+
| `.emph-rubric` | the text in `var(--rubric)` |
|
|
394
|
+
| `.emph-overline` | the text with a line above it |
|
|
395
|
+
|
|
396
|
+
`.script em` and `.script strong` keep the face's Regular: no slant, no added
|
|
397
|
+
weight, and `font-synthesis: none`. A script whose notes state no convention
|
|
398
|
+
gives a bare `<em>` or `<strong>`, which therefore looks like the text around
|
|
399
|
+
it.
|
|
400
|
+
|
|
401
|
+
The theme's `--rubric` is `#e0705f`, a warm red for its dark ground. Because a
|
|
402
|
+
rubric carries emphasis by colour alone, it holds 4.5:1 against `--bg`,
|
|
403
|
+
`--bg-card` and `--surface`, and 1.75:1 against `--text`, so a reader who
|
|
404
|
+
cannot see its hue still sees a lighter or darker word. A site that overrides
|
|
405
|
+
`--rubric` keeps both. Foundry's base stylesheet sets the same classes from
|
|
406
|
+
`--pb-rubric`, `light-dark(#9c281b, #e0705f)`, against Foundry's journal page in
|
|
407
|
+
each theme, and the book prints its rubric in `#9c281b` on its paper.
|
|
408
|
+
|
|
338
409
|
## Search
|
|
339
410
|
|
|
340
411
|
`params.search = true` renders a search box in the header; left unset (or
|
|
341
|
-
`false`), `
|
|
412
|
+
`false`), the `search` partial renders nothing. The box, and everything it
|
|
342
413
|
opens, is the theme's own — the index it reads is not.
|
|
343
414
|
|
|
344
|
-
**Where the index comes from.** `package-build site
|
|
415
|
+
**Where the index comes from.** `package-build site build` writes a
|
|
345
416
|
[Pagefind](https://pagefind.app) index at `pagefind/` beside the rendered
|
|
346
417
|
pages, when `site.search` in `package-build.config.yaml` is left at its
|
|
347
418
|
default of `true` (see [`site.search`](../configuration.md#site) and
|
|
@@ -352,26 +423,40 @@ Pagefind version. Turning `params.search` on without `site.search` indexing
|
|
|
352
423
|
the site (or with it set `false`) shows an empty results box that never finds
|
|
353
424
|
anything — the two settings are independent, and a consumer sets both.
|
|
354
425
|
|
|
355
|
-
Both files are
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
finds its own index rather than another package's, and the theme carries no
|
|
359
|
-
address of its own.
|
|
426
|
+
Both files are addressed relative to the site's base, so a package served
|
|
427
|
+
under a prefix (`/thalorna/pagefind/…`) finds its own index rather than
|
|
428
|
+
another package's, and the theme carries no address of its own.
|
|
360
429
|
|
|
361
430
|
**Why a header box and not a `/search/` page.** A site is its homepage and
|
|
362
431
|
its pages, with nothing generated between them — a results page would need a
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
432
|
+
note at that address. Pagefind's own panel UI needs no page of its own: the
|
|
433
|
+
header button opens it in place.
|
|
434
|
+
|
|
435
|
+
**What is indexed.** `data-pagefind-body` on a page's prose scopes indexing to
|
|
436
|
+
it; the theme's own chrome carries `data-pagefind-ignore` — the header, the
|
|
437
|
+
footer, the infobox rail, the table of contents, the Related card, and the
|
|
438
|
+
hero banner's title and tagline.
|
|
439
|
+
|
|
440
|
+
**What a page tells the search.** Each page carries hidden metadata the
|
|
441
|
+
search reads: its title, its filters, its aliases, its picture and, for a
|
|
442
|
+
post, its date.
|
|
443
|
+
|
|
444
|
+
| Filter | Values |
|
|
445
|
+
| ----------- | -------------------------------------------- |
|
|
446
|
+
| `package` | the package that publishes the note |
|
|
447
|
+
| `type` | the note's `type` |
|
|
448
|
+
| `subtype` | the note's `subType` |
|
|
449
|
+
| `culture` | the name of the culture `data.culture` names |
|
|
450
|
+
| `continent` | the continent the note lies in |
|
|
451
|
+
| `region` | the outermost region beneath that continent |
|
|
452
|
+
|
|
453
|
+
A post carries `author` and `tags` filters and sorts by its `date`. A note's
|
|
454
|
+
name and its aliases count ten times a word of its body, so a search for a name
|
|
455
|
+
opens that note first and a search for an alias finds it. A result shows the
|
|
456
|
+
note's `data.icon`, or its hero banner where it has none. A note's tags and its
|
|
457
|
+
draft state are not filters. Secret blocks, inline secrets and `.secret`
|
|
458
|
+
sections are kept out of the index. [The site guide](../guides/site.md#search)
|
|
459
|
+
says where a note lies and how a merged search reads other sites' indexes.
|
|
375
460
|
|
|
376
461
|
**Classes added:** `.site-search`, `.search-toggle`, `.search-panel`,
|
|
377
462
|
`.search-panel-inner`, and `.header-actions` (the header's nav/search/toggle
|
|
@@ -379,20 +464,20 @@ group). `.search-panel-inner` carries Pagefind's own `--pagefind-ui-*`
|
|
|
379
464
|
theming variables, set from the theme's own tokens so results match the
|
|
380
465
|
chrome around them.
|
|
381
466
|
|
|
382
|
-
## What a page, a homepage and a
|
|
467
|
+
## What a page, a homepage and a listing carry
|
|
383
468
|
|
|
384
469
|
### A page
|
|
385
470
|
|
|
386
|
-
`
|
|
387
|
-
|
|
388
|
-
|
|
471
|
+
The `page` layout draws every note that is not the homepage: the hero, the
|
|
472
|
+
infobox rail, the body, any `related:` block, and prev/next links through the
|
|
473
|
+
page's own catalog.
|
|
389
474
|
|
|
390
475
|
**Emitted.** A note's page arrives with `title` (the note's name), `type`,
|
|
391
476
|
`subType`, `description` and `tags` already set, and `data.banner` resolved.
|
|
392
|
-
The form below is the hand-written one, which is what a
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
477
|
+
The form below is the hand-written one, which is what a curated landing
|
|
478
|
+
carries: `title`, `date` and a top-level `banner:` are keys the content build
|
|
479
|
+
never writes, and a note's page therefore has no `date` and no meta-line date
|
|
480
|
+
at all.
|
|
396
481
|
|
|
397
482
|
```yaml
|
|
398
483
|
---
|
|
@@ -408,13 +493,13 @@ tags: [archetype, mercantyl] # optional; shown in the page meta line
|
|
|
408
493
|
|
|
409
494
|
- **`type`** is the page's catalog key, unless it is `doc` — prose rather than
|
|
410
495
|
a catalog of its own — in which case the key is `subType` (what the build
|
|
411
|
-
compiles from a note's classification) or, failing that, `category
|
|
412
|
-
|
|
413
|
-
catalog.
|
|
496
|
+
compiles from a note's classification) or, failing that, `category`. A page
|
|
497
|
+
with no `type` has no catalog.
|
|
414
498
|
- **`date`**, **`tags`** — each optional and shown only when present, in a
|
|
415
|
-
meta line above the body. A tag links to `tags/<tag
|
|
499
|
+
meta line above the body. A tag links to `tags/<tag>/` where the site writes
|
|
500
|
+
a page for each tag (`site.tags`), and is plain text otherwise.
|
|
416
501
|
- **`subType`** — shown as a plain label for `type: being` pages. It does not
|
|
417
|
-
create a tag
|
|
502
|
+
create a tag.
|
|
418
503
|
|
|
419
504
|
**The draft notice.** A page tagged `draft` states that its content is not
|
|
420
505
|
settled, at the head of the article — above the infobox rail and above the
|
|
@@ -433,29 +518,34 @@ out of the meta line's tag row and said here instead.
|
|
|
433
518
|
it states may change, and nothing in it is settled._
|
|
434
519
|
- **`.draft-notice`**, **`.draft-notice-icon`**, **`.draft-notice-text`** and
|
|
435
520
|
**`.draft-notice-label`** are the classes a consumer styles against.
|
|
436
|
-
- The mark is Font Awesome, which
|
|
521
|
+
- The mark is Font Awesome, which the base layout already loads; the sentence
|
|
437
522
|
reads on its own where it does not arrive.
|
|
438
523
|
- The sentence is an `em`: the label is the page's own voice naming the
|
|
439
524
|
state, and the sentence is the page speaking about itself.
|
|
440
525
|
- A page carrying the notice also carries **`.single-with-notice`** on its
|
|
441
526
|
article, which is what moves a two-column page's content and rail below it.
|
|
442
527
|
|
|
443
|
-
**Prev/next.**
|
|
444
|
-
site
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
528
|
+
**Prev/next.** The links walk the pages of the site in the order a reader
|
|
529
|
+
walks them. A site holding more than one catalog narrows the walk to the pages
|
|
530
|
+
sharing this page's catalog key, so reading through the afflictions does not
|
|
531
|
+
surface a skill; a site holding a single catalog is untouched.
|
|
532
|
+
|
|
533
|
+
### A post
|
|
534
|
+
|
|
535
|
+
A note of `type: doc` and `subType: post` is drawn by the `blog-post` layout:
|
|
536
|
+
the post's title, its date and writer, its series where it states one, its
|
|
537
|
+
tags, and its body. Posts are listed newest first on the page of the section
|
|
538
|
+
`site.feed` names, and the site writes an Atom feed beside that page.
|
|
450
539
|
|
|
451
540
|
### The homepage
|
|
452
541
|
|
|
453
|
-
A package's home page is `
|
|
454
|
-
|
|
542
|
+
A package's home page is the `type: homepage` note, drawn by the `home`
|
|
543
|
+
layout at the package root. The layout selects between two shapes by what the
|
|
544
|
+
page carries.
|
|
455
545
|
|
|
456
546
|
**`type: homepage`** renders the page through the same structure a note gets
|
|
457
|
-
from `
|
|
458
|
-
sharing the markup through `
|
|
547
|
+
from the `page` layout — the hero from its `banner:`, then its body —
|
|
548
|
+
sharing the markup through the `page-body` partial so a homepage and a page
|
|
459
549
|
read as one family:
|
|
460
550
|
|
|
461
551
|
```yaml
|
|
@@ -465,11 +555,10 @@ title: Song of Heroic Lands # hero heading
|
|
|
465
555
|
description: A classless, skill-based fantasy system … # hero standfirst
|
|
466
556
|
|
|
467
557
|
# The hero image. The same `banner:` every other page in this theme uses,
|
|
468
|
-
# resolved
|
|
469
|
-
#
|
|
470
|
-
#
|
|
471
|
-
#
|
|
472
|
-
# entirely.
|
|
558
|
+
# resolved in the documented order and through `params.cdnBaseURL` — see "The
|
|
559
|
+
# hero banner" above. With none set, the subtype default lands on
|
|
560
|
+
# `images/banners/homepage.webp`, since the subtype default is keyed on the
|
|
561
|
+
# page's `type`. `banner: none` declines a hero image entirely.
|
|
473
562
|
banner: brand/sohl-banner.webp
|
|
474
563
|
---
|
|
475
564
|
Everything published for the system lives under this address …
|
|
@@ -479,39 +568,20 @@ The home page declares no `infoboxes:`, `related:`, `date:` or `tags:`, so
|
|
|
479
568
|
those pieces of a page stay silent.
|
|
480
569
|
|
|
481
570
|
**No `type` at all** — a site whose home page is a set of entry points into
|
|
482
|
-
everything it publishes — renders the featured grid from `params.home
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
members (`.Pages`) as a gap-filler: a member the body already links,
|
|
497
|
-
directly or transitively, is not repeated, and the rest appear under
|
|
498
|
-
"Orphaned Pages" when the body links some of them, or plainly when it links
|
|
499
|
-
none. A tag's term page lists the pages carrying it; the tag index itself
|
|
500
|
-
lists every tag with its page count.
|
|
501
|
-
|
|
502
|
-
```yaml
|
|
503
|
-
---
|
|
504
|
-
# content/projects/_index.md — a hand-curated landing, no `type:` at all
|
|
505
|
-
title: Projects
|
|
506
|
-
description: Foundry VTT systems, modules, and reference content …
|
|
507
|
-
---
|
|
508
|
-
Each section below has its own landing page.
|
|
509
|
-
|
|
510
|
-
# [Song of Heroic Lands](/projects/song-of-heroic-lands/)
|
|
511
|
-
…
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
A row is a linked title and, when the page carries one, its description.
|
|
571
|
+
everything it publishes — renders the featured grid from `params.home`: a hero
|
|
572
|
+
(`heroimage`, `herotitle`, `herotagline`), the section headings, and a card for
|
|
573
|
+
each entry of `cards`, each with a title, an address, a line of text and an
|
|
574
|
+
optional image.
|
|
575
|
+
|
|
576
|
+
### A listing
|
|
577
|
+
|
|
578
|
+
The `list` layout draws a page that lists other pages: a section a note
|
|
579
|
+
stands for (`site.sections`), and the tag pages `site.tags` writes. It opens
|
|
580
|
+
with the hero and any authored body, then lists the members the body does not
|
|
581
|
+
already link, directly or transitively, under a heading when the body links
|
|
582
|
+
some of them, or plainly when it links none. A tag's page lists the pages
|
|
583
|
+
carrying it; the tag index lists every tag with its page count. A row is a
|
|
584
|
+
linked title and, when the page carries one, its description.
|
|
515
585
|
|
|
516
586
|
## Alerts
|
|
517
587
|
|
package/docs/source-preview.md
CHANGED
|
@@ -9,7 +9,8 @@ subType: reference
|
|
|
9
9
|
|
|
10
10
|
Preview renders only the supplied Markdown buffer. It works with ordinary
|
|
11
11
|
Markdown, optional YAML frontmatter, and local Heroic Lands extensions, without
|
|
12
|
-
configuration, a content tree, dependency caches, a content index or Pandoc.
|
|
12
|
+
configuration, a content tree, dependency caches, a content index or Pandoc. A
|
|
13
|
+
host that holds a content index can give it to the preview for a fuller view.
|
|
13
14
|
|
|
14
15
|
```sh
|
|
15
16
|
package-build-preview < note.md > preview.html
|
|
@@ -25,6 +26,19 @@ is the default; `--dark` is explicit and independent of browser preferences.
|
|
|
25
26
|
options. Unsupported arguments exit 1. Findings go to stderr; success exits 0,
|
|
26
27
|
and render errors exit 1. A partial preview may accompany error findings.
|
|
27
28
|
|
|
29
|
+
Preview renders through the same renderer as the packs and the websites, so an
|
|
30
|
+
alert, a secret block, a verse, a captioned item, a footnote section and a
|
|
31
|
+
picture's size and position read as they do on those surfaces. Fenced code that
|
|
32
|
+
names a language is highlighted. A tag written in a note is shown as text.
|
|
33
|
+
|
|
34
|
+
The default view needs no content index, so it shows what it cannot resolve as
|
|
35
|
+
source. A host that holds the package's content index builds an index with
|
|
36
|
+
`previewIndex` and passes it to `renderPreview` as `index`. Rendered that way, a
|
|
37
|
+
wikilink is a link, a link to a concealed note is concealed, an embed draws its
|
|
38
|
+
picture, marked text is mapped and set in its face, an icon is drawn, and a
|
|
39
|
+
caption is numbered with its asset's role, so a map is a **Map**. A query, which
|
|
40
|
+
a buffer cannot run, stays highlighted source in both views.
|
|
41
|
+
|
|
28
42
|
Wikilinks, image and portrait links retain their complete source: blue brackets,
|
|
29
43
|
purple addresses, bold foreground labels and grey attributes. Entire spans are bold, including their visible brackets and attributes.
|
|
30
44
|
Definition-list terms are bold and definitions use normal text. SQL and pagelist fences remain grey source;
|
|
@@ -156,7 +170,7 @@ go run check-sanitizer.go /path/to/gitea.ini < preview.html > sanitized.html
|
|
|
156
170
|
```
|
|
157
171
|
|
|
158
172
|
Check both light and dark fixtures containing all four alert types, a custom
|
|
159
|
-
title, nesting, wikilinks and attributes, SQL/pagelist fences, infoboxes,
|
|
173
|
+
title, nesting, wikilinks and attributes, SQL/pagelist fences, infoboxes, verse
|
|
160
174
|
and footnotes. All wrapper/token classes and icon shapes should remain, while
|
|
161
175
|
injected scripts and event-handler attributes should disappear. This replay
|
|
162
176
|
checks the sanitizer primitives; also inspect the result in the actual Gitea
|
package/engine/anchors.mjs
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
import { scanAlerts } from "./content-alerts.mjs";
|
|
39
39
|
import { scanBlocks } from "./content-blocks.mjs";
|
|
40
|
-
import {
|
|
40
|
+
import { scanVerse } from "./content-verse.mjs";
|
|
41
41
|
import { scanSpans } from "./content-spans.mjs";
|
|
42
42
|
import { slugify } from "./content-slug.mjs";
|
|
43
43
|
import { scanFigures } from "./content-figures.mjs";
|
|
@@ -123,7 +123,7 @@ export function collectAnchors(body, bodyLine = 1, resolveRole, syntax) {
|
|
|
123
123
|
kind: "prose",
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
|
-
for (const poem of
|
|
126
|
+
for (const poem of scanVerse(body).blocks) {
|
|
127
127
|
if (poem.id)
|
|
128
128
|
anchors.push({
|
|
129
129
|
slug: slugify(poem.id),
|
|
@@ -272,8 +272,11 @@ export function assetsManifest(staged, stageDir) {
|
|
|
272
272
|
*
|
|
273
273
|
* The pictures are written beside whatever a `packageBuild.assets` row already
|
|
274
274
|
* put under `icons/` and `images/`; nothing there is removed. A picture whose
|
|
275
|
-
* deployed path
|
|
276
|
-
*
|
|
275
|
+
* deployed path already holds a file with the bytes it would stage — after the
|
|
276
|
+
* transform, when there is one — is its own earlier output and is skipped, so
|
|
277
|
+
* staging twice into one directory is quiet. A file there with other bytes is a
|
|
278
|
+
* finding, and no picture is written. Clearing an earlier run's pictures is the
|
|
279
|
+
* stage reset's work.
|
|
277
280
|
*
|
|
278
281
|
* @param {object} opts - Options.
|
|
279
282
|
* @param {string} opts.assetsBase - The package's asset directory, the roots'
|
|
@@ -309,13 +312,22 @@ export function stagePackageAssets({
|
|
|
309
312
|
if (findings.length) return { staged: [], excluded: [], findings, manifest: null };
|
|
310
313
|
|
|
311
314
|
const { staged, excluded } = selectStagedAssets(records, shippingLicenses);
|
|
312
|
-
const planned = staged.map((record) =>
|
|
313
|
-
record
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
315
|
+
const planned = staged.map((record) => {
|
|
316
|
+
const from = path.join(assetsBase, ...record.asset.path.split("/"));
|
|
317
|
+
return {
|
|
318
|
+
record,
|
|
319
|
+
from,
|
|
320
|
+
transformed: transform ? transform(from) : null,
|
|
321
|
+
to: path.join(
|
|
322
|
+
stageDir,
|
|
323
|
+
.../** @type {string} */ (deployedAssetPath(record)).split("/"),
|
|
324
|
+
),
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
for (const { record, from, to, transformed } of planned) {
|
|
318
328
|
if (!fs.existsSync(to)) continue;
|
|
329
|
+
const bytes = transformed != null ? transformed : fs.readFileSync(from);
|
|
330
|
+
if (Buffer.from(fs.readFileSync(to)).equals(Buffer.from(bytes))) continue;
|
|
319
331
|
findings.push({
|
|
320
332
|
file: to,
|
|
321
333
|
severity: "error",
|
|
@@ -326,9 +338,9 @@ export function stagePackageAssets({
|
|
|
326
338
|
});
|
|
327
339
|
}
|
|
328
340
|
if (findings.length) return { staged: [], excluded: [], findings, manifest: null };
|
|
329
|
-
for (const { from, to } of planned) {
|
|
341
|
+
for (const { from, to, transformed } of planned) {
|
|
342
|
+
if (fs.existsSync(to)) continue;
|
|
330
343
|
fs.mkdirSync(path.dirname(to), { recursive: true });
|
|
331
|
-
const transformed = transform ? transform(from) : null;
|
|
332
344
|
if (transformed != null) fs.writeFileSync(to, transformed);
|
|
333
345
|
else fs.copyFileSync(from, to);
|
|
334
346
|
}
|