@heroiclands/package-build 23.12.5 → 23.12.7
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 +22 -0
- package/assets/styles/content-base.css +25 -0
- package/bin/content-commands.mjs +264 -3
- package/bin/package-build.mjs +25 -0
- package/content-config.mjs +98 -0
- package/docs/api.md +18 -14
- package/docs/authoring/dates-and-calendars.md +29 -1
- package/docs/authoring/links-and-markup.md +442 -50
- package/docs/commands.md +127 -0
- package/docs/configuration.md +90 -3
- package/docs/content-format.md +3 -1
- package/docs/guides/book.md +11 -0
- package/docs/guides/module-project.md +17 -1
- package/docs/guides/site.md +19 -0
- package/docs/reference/format-details.md +434 -23
- package/docs/reference/note-types.md +45 -21
- package/engine/base-compiler.mjs +2 -0
- package/engine/bundles.mjs +7 -2
- package/engine/compile-corpus.mjs +3 -1
- package/engine/content-charset.mjs +21 -2
- package/engine/content-format.yaml +1 -2
- package/engine/content-index.mjs +33 -2
- package/engine/content-links.mjs +3 -0
- package/engine/content-poetry.mjs +22 -4
- package/engine/content-scripts.mjs +1219 -0
- package/engine/content-session.mjs +2 -0
- package/engine/data-keys.mjs +5 -1
- package/engine/dictionary-layout.mjs +18 -12
- package/engine/dictionary-rows.mjs +11 -2
- package/engine/event-rows.mjs +63 -18
- package/engine/event-views.mjs +28 -15
- package/engine/helpers.mjs +8 -2
- package/engine/index-records.mjs +2 -0
- package/engine/infobox.mjs +4 -8
- package/engine/journals.mjs +14 -3
- package/engine/language-data.mjs +137 -1
- package/engine/language-tag.mjs +103 -0
- package/engine/language-terms.mjs +16 -4
- package/engine/map-lexicon.mjs +762 -0
- package/engine/markdown-expressions.mjs +72 -17
- package/engine/markup-validation.mjs +17 -3
- package/engine/names.mjs +1 -1
- package/engine/note-calendars.mjs +314 -0
- package/engine/note-vocabulary.mjs +124 -16
- package/engine/pdf-build.mjs +28 -10
- package/engine/pdf-render.mjs +116 -11
- package/engine/reckoning-markers.mjs +63 -3
- package/engine/run-rows.mjs +119 -0
- package/engine/run-words.mjs +266 -0
- package/engine/scenes.mjs +1 -0
- package/engine/script-font-delivery.mjs +321 -0
- package/engine/script-fonts.mjs +172 -0
- package/engine/site-build.mjs +10 -3
- package/engine/site-config.mjs +5 -0
- package/engine/site-root.mjs +19 -5
- package/engine/sql-tables.mjs +120 -4
- package/engine/text-maps.mjs +607 -0
- package/engine/verb-pattern.mjs +99 -0
- package/engine/word-pattern.mjs +27 -0
- package/engine/word-rows.mjs +8 -2
- package/engine/word-terms.mjs +44 -0
- package/hugo-theme/layouts/_default/baseof.html +3 -0
- package/hugo-theme/static/css/style.css +10 -0
- package/manifest.mjs +9 -1
- package/package.json +1 -1
- package/types/content-config.d.mts +38 -0
- package/types/engine/compile-corpus.d.mts +2 -1
- package/types/engine/content-index.d.mts +17 -3
- package/types/engine/content-poetry.d.mts +7 -0
- package/types/engine/content-scripts.d.mts +226 -0
- package/types/engine/data-keys.d.mts +2 -2
- package/types/engine/dictionary-rows.d.mts +15 -0
- package/types/engine/event-rows.d.mts +16 -1
- package/types/engine/event-views.d.mts +2 -1
- package/types/engine/helpers.d.mts +5 -1
- package/types/engine/journals.d.mts +7 -2
- package/types/engine/language-data.d.mts +2 -0
- package/types/engine/language-tag.d.mts +8 -0
- package/types/engine/language-terms.d.mts +2 -1
- package/types/engine/map-lexicon.d.mts +274 -0
- package/types/engine/markup-validation.d.mts +7 -2
- package/types/engine/note-calendars.d.mts +60 -0
- package/types/engine/pdf-build.d.mts +26 -3
- package/types/engine/pdf-render.d.mts +17 -2
- package/types/engine/reckoning-markers.d.mts +32 -1
- package/types/engine/run-rows.d.mts +89 -0
- package/types/engine/run-words.d.mts +86 -0
- package/types/engine/script-font-delivery.d.mts +134 -0
- package/types/engine/script-fonts.d.mts +168 -0
- package/types/engine/site-build.d.mts +2 -1
- package/types/engine/site-root.d.mts +11 -3
- package/types/engine/text-maps.d.mts +175 -0
- package/types/engine/verb-pattern.d.mts +65 -0
- package/types/engine/word-pattern.d.mts +13 -0
- package/types/engine/word-terms.d.mts +6 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Song of Heroic Lands (SoHL) system for Foundry VTT.
|
|
3
|
+
* Copyright (c) 2024-2026 Tom Rodriguez ("Toasty") — <toasty@heroiclands.org>
|
|
4
|
+
*
|
|
5
|
+
* This work is licensed under the GNU General Public License v3.0 (GPLv3).
|
|
6
|
+
* You may copy, modify, and distribute it under the terms of that license.
|
|
7
|
+
*
|
|
8
|
+
* For full terms, see the LICENSE.md file in the project root or visit:
|
|
9
|
+
* https://www.gnu.org/licenses/gpl-3.0.html
|
|
10
|
+
*
|
|
11
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* **A language's one regular verb pattern, read once for every reader.** A
|
|
16
|
+
* language's `data.grammar.verbs` is `{ invariant: true }` or six `persons`
|
|
17
|
+
* endings, optionally with `replaces`. A present form is the citation form
|
|
18
|
+
* with the ending added; where the pattern states `replaces`, a citation form
|
|
19
|
+
* closing on those letters has them swapped for the ending, and one closing
|
|
20
|
+
* otherwise takes the ending whole, as a suffix's `replaces` does.
|
|
21
|
+
*
|
|
22
|
+
* The dictionary's verb table and a mapped run's lexicon check both read the
|
|
23
|
+
* pattern through {@link verbPattern} and build forms with {@link verbForm}.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { VERB_PERSON_FIELDS } from "./language-terms.mjs";
|
|
29
|
+
|
|
30
|
+
/** Whether a value is a plain map. */
|
|
31
|
+
const isMap = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A stated verb pattern, as its readers use it.
|
|
35
|
+
*
|
|
36
|
+
* @typedef {object} VerbPattern
|
|
37
|
+
* @property {boolean} invariant - Whether verbs keep the citation form for
|
|
38
|
+
* every person.
|
|
39
|
+
* @property {string|undefined} replaces - The letters each ending takes the
|
|
40
|
+
* place of, where the pattern states them.
|
|
41
|
+
* @property {Array<{name: string, label: string, ending: string}>} endings -
|
|
42
|
+
* The six endings in presentation order; empty for an invariant pattern.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Read a language's verb pattern.
|
|
47
|
+
*
|
|
48
|
+
* @param {unknown} verbs - The language's `data.grammar.verbs`, as authored or
|
|
49
|
+
* as a SQL row carries it (absent fields `null`).
|
|
50
|
+
* @returns {VerbPattern|undefined} The pattern, or `undefined` where none is
|
|
51
|
+
* stated in full.
|
|
52
|
+
*/
|
|
53
|
+
export function verbPattern(verbs) {
|
|
54
|
+
if (!isMap(verbs)) return undefined;
|
|
55
|
+
const replaces =
|
|
56
|
+
typeof verbs.replaces === "string" && verbs.replaces.trim() ? verbs.replaces : undefined;
|
|
57
|
+
if (verbs.invariant === true) return { invariant: true, replaces, endings: [] };
|
|
58
|
+
const persons = isMap(verbs.persons) ? verbs.persons : undefined;
|
|
59
|
+
if (!persons || !VERB_PERSON_FIELDS.every(({ name }) => typeof persons[name] === "string"))
|
|
60
|
+
return undefined;
|
|
61
|
+
return {
|
|
62
|
+
invariant: false,
|
|
63
|
+
replaces,
|
|
64
|
+
endings: VERB_PERSON_FIELDS.map(({ name, label }) => ({
|
|
65
|
+
name,
|
|
66
|
+
label,
|
|
67
|
+
ending: persons[name],
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A stem with its closing letters swapped for an ending, or with the ending
|
|
74
|
+
* added where the stem does not close on them.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} stem - The stem.
|
|
77
|
+
* @param {string} ending - The ending.
|
|
78
|
+
* @param {string|undefined} letters - The closing letters the ending takes
|
|
79
|
+
* the place of; none adds the ending.
|
|
80
|
+
* @returns {string} The form.
|
|
81
|
+
*/
|
|
82
|
+
export function replaceClosing(stem, ending, letters) {
|
|
83
|
+
return letters && stem.endsWith(letters) ?
|
|
84
|
+
stem.slice(0, -letters.length) + ending
|
|
85
|
+
: stem + ending;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The present form of a verb for one ending.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} citation - The citation form.
|
|
92
|
+
* @param {string} ending - The person's ending; empty leaves the citation
|
|
93
|
+
* form, less any closing `replaces`.
|
|
94
|
+
* @param {string} [replaces] - The pattern's `replaces`.
|
|
95
|
+
* @returns {string} The form.
|
|
96
|
+
*/
|
|
97
|
+
export function verbForm(citation, ending, replaces) {
|
|
98
|
+
return replaceClosing(citation, ending, replaces);
|
|
99
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Song of Heroic Lands (SoHL) system for Foundry VTT.
|
|
3
|
+
* Copyright (c) 2024-2026 Tom Rodriguez ("Toasty") — <toasty@heroiclands.org>
|
|
4
|
+
*
|
|
5
|
+
* This work is licensed under the GNU General Public License v3.0 (GPLv3).
|
|
6
|
+
* You may copy, modify, and distribute it under the terms of that license.
|
|
7
|
+
*
|
|
8
|
+
* For full terms, see the LICENSE.md file in the project root or visit:
|
|
9
|
+
* https://www.gnu.org/licenses/gpl-3.0.html
|
|
10
|
+
*
|
|
11
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* **What a word is in running text.** A word is a maximal run of letters,
|
|
16
|
+
* combining marks and digits, and an apostrophe (`'` or `’`), a hyphen or an
|
|
17
|
+
* en dash joins two such runs into one word: `k'aralzon`, `Arzen-Thalor`.
|
|
18
|
+
* Anything else, whitespace and punctuation included, sits between words.
|
|
19
|
+
*
|
|
20
|
+
* The name catalog reads a label's last word by it, and a mapped run reads
|
|
21
|
+
* each word it looks up in a lexicon by it.
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** One word; global, so `matchAll` walks every word of a text. */
|
|
27
|
+
export const WORD = /[\p{L}\p{M}\p{N}]+(?:[’'–-][\p{L}\p{M}\p{N}]+)*/gu;
|
package/engine/word-rows.mjs
CHANGED
|
@@ -47,6 +47,12 @@ import {
|
|
|
47
47
|
glossText,
|
|
48
48
|
} from "./word-terms.mjs";
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* The word's own keys a word row carries: all but `native`, whose entries are
|
|
52
|
+
* rows of the `natives` relation.
|
|
53
|
+
*/
|
|
54
|
+
const WORD_ROW_KEYS = Object.freeze(WORD_KEYS.filter((key) => key !== "native"));
|
|
55
|
+
|
|
50
56
|
/** The columns a word row carries before the word's own keys. */
|
|
51
57
|
const WORD_IDENTITY_COLUMNS = Object.freeze(["language", "position"]);
|
|
52
58
|
|
|
@@ -56,7 +62,7 @@ const WORD_DERIVED_COLUMNS = Object.freeze(["built_text", "built_parts", "senses
|
|
|
56
62
|
/** Every column of the `words` relation, in order. */
|
|
57
63
|
export const WORD_COLUMNS = Object.freeze([
|
|
58
64
|
...WORD_IDENTITY_COLUMNS,
|
|
59
|
-
...
|
|
65
|
+
...WORD_ROW_KEYS,
|
|
60
66
|
...WORD_DERIVED_COLUMNS,
|
|
61
67
|
]);
|
|
62
68
|
|
|
@@ -260,7 +266,7 @@ export function wordRows(records, all = records) {
|
|
|
260
266
|
words.forEach((entry, position) => {
|
|
261
267
|
if (!isMap(entry)) return;
|
|
262
268
|
const row = { language, position };
|
|
263
|
-
for (const key of
|
|
269
|
+
for (const key of WORD_ROW_KEYS) row[key] = entry[key] ?? null;
|
|
264
270
|
if (row.name_sort === null) row.name_sort = row.form;
|
|
265
271
|
const built = Array.isArray(entry.built) ? entry.built.map(String) : [];
|
|
266
272
|
row.built_text = built.length ? built.join(" + ") : null;
|
package/engine/word-terms.mjs
CHANGED
|
@@ -99,6 +99,37 @@ export const WORD_SOURCE_FIELDS = Object.freeze([
|
|
|
99
99
|
}),
|
|
100
100
|
]);
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* The keys of one entry of a word's `native`.
|
|
104
|
+
*
|
|
105
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
106
|
+
*/
|
|
107
|
+
export const WORD_NATIVE_FIELDS = Object.freeze([
|
|
108
|
+
Object.freeze({
|
|
109
|
+
name: "map",
|
|
110
|
+
kind: "string",
|
|
111
|
+
required: true,
|
|
112
|
+
shape: "a mapping note's `data.map.name`",
|
|
113
|
+
describe: "The map the native form is written for.",
|
|
114
|
+
}),
|
|
115
|
+
Object.freeze({
|
|
116
|
+
name: "font",
|
|
117
|
+
kind: "string",
|
|
118
|
+
shape: "a face the map lists",
|
|
119
|
+
describe:
|
|
120
|
+
"The one face the native form is for; unstated, it is for every face the map lists, " +
|
|
121
|
+
"and a form stated for a face wins over it there.",
|
|
122
|
+
}),
|
|
123
|
+
Object.freeze({
|
|
124
|
+
name: "text",
|
|
125
|
+
kind: "string",
|
|
126
|
+
required: true,
|
|
127
|
+
shape: "the word in the script, as the map's characters",
|
|
128
|
+
describe:
|
|
129
|
+
"The word as the script writes it, where the map's rows would write it otherwise.",
|
|
130
|
+
}),
|
|
131
|
+
]);
|
|
132
|
+
|
|
102
133
|
/**
|
|
103
134
|
* The keys one word of a language note's `data.words` carries.
|
|
104
135
|
*
|
|
@@ -209,6 +240,19 @@ export const WORD_FIELDS = Object.freeze([
|
|
|
209
240
|
shape: "a frame of the language's `sounds.frames`",
|
|
210
241
|
describe: "The frame a root is set in, named in the language's `sounds.frames`.",
|
|
211
242
|
}),
|
|
243
|
+
Object.freeze({
|
|
244
|
+
name: "native",
|
|
245
|
+
kind: "list",
|
|
246
|
+
shape: "a list of `{ map, font?, text }`",
|
|
247
|
+
entries: Object.freeze({
|
|
248
|
+
kind: "map",
|
|
249
|
+
shape: "a map — `{ map, font?, text }`",
|
|
250
|
+
fields: WORD_NATIVE_FIELDS,
|
|
251
|
+
}),
|
|
252
|
+
describe:
|
|
253
|
+
"The word's native form under a map, stated only where the map's rows spell it " +
|
|
254
|
+
"differently. Its derived forms are spelled by the rows.",
|
|
255
|
+
}),
|
|
212
256
|
]);
|
|
213
257
|
|
|
214
258
|
/** The keys of {@link WORD_FIELDS}, in declared order. */
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
10
|
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600&display=swap" rel="stylesheet">
|
|
11
11
|
<link rel="stylesheet" href="{{ "css/style.css" | relURL }}">
|
|
12
|
+
{{/* Script fonts: the site build sets params.scriptFonts only when it has
|
|
13
|
+
copied them. */}}
|
|
14
|
+
{{ with .Site.Params.scriptFonts }}<link rel="stylesheet" href="{{ . | relURL }}">{{ end }}
|
|
12
15
|
{{/* Icon glyphs. SoHL documentation writes icons as <i class="fa-solid …">
|
|
13
16
|
or <i class="ginf-…">, the same markup the Foundry client renders, so a
|
|
14
17
|
page reads identically in a journal and here. Font Awesome's FREE set is
|
|
@@ -3022,3 +3022,13 @@ summary.info-sidebar-title::after {
|
|
|
3022
3022
|
.single-body .dictionary > div > dd > :is(p, ul, ol, dl, blockquote, pre, table, div) { text-indent:0; }
|
|
3023
3023
|
.single-body .dictionary > div > dd > p:first-child { display:inline; }
|
|
3024
3024
|
@media (max-width:600px) { .single-body .dictionary { --indent:100px; } }
|
|
3025
|
+
|
|
3026
|
+
/* ---- Text in one of the faces ----
|
|
3027
|
+
The font family and features come from the face's own class. A
|
|
3028
|
+
right-to-left block or verse reads from the right. `font=serif`, `sans`
|
|
3029
|
+
and `mono` set the site's own serif and mono, and the reader's sans. */
|
|
3030
|
+
.script-block { margin:1rem 0; line-height:1.7; }
|
|
3031
|
+
.script-block[dir="rtl"], .poetry[dir="rtl"] { text-align:start; }
|
|
3032
|
+
.font-serif { font-family:var(--font-body); }
|
|
3033
|
+
.font-sans { font-family:sans-serif; }
|
|
3034
|
+
.font-mono { font-family:var(--font-mono); }
|
package/manifest.mjs
CHANGED
|
@@ -54,6 +54,7 @@ import fsSync from "node:fs";
|
|
|
54
54
|
import path from "node:path";
|
|
55
55
|
|
|
56
56
|
import { withBaseStyle } from "./engine/base-styles.mjs";
|
|
57
|
+
import { scriptFontFiles, withScriptFontStyle } from "./engine/script-font-delivery.mjs";
|
|
57
58
|
import { emitDiagnostic, formatDiagnostic, positionOfYamlPath } from "./engine/diagnostics.mjs";
|
|
58
59
|
import { metadataFileName } from "./engine/metadata-index.mjs";
|
|
59
60
|
|
|
@@ -571,11 +572,18 @@ export function buildManifest({ config, packageJson, artifact, flags }) {
|
|
|
571
572
|
// the five that do have no stylesheet of their own to name it from. See
|
|
572
573
|
// `engine/base-styles.mjs` for the layer it loads into and why that is what
|
|
573
574
|
// lets a package override it.
|
|
574
|
-
const
|
|
575
|
+
const withBase = withBaseStyle({
|
|
575
576
|
declared: declared.styles,
|
|
576
577
|
artifact: /** @type {"system"|"module"} */ (artifact),
|
|
577
578
|
enabled: config.packageBuild?.baseStyles !== false,
|
|
578
579
|
});
|
|
580
|
+
// The installed script fonts' stylesheet follows it, when the module
|
|
581
|
+
// carries them: see `engine/script-font-delivery.mjs`.
|
|
582
|
+
const styles = withScriptFontStyle({
|
|
583
|
+
styles: withBase,
|
|
584
|
+
artifact: /** @type {"system"|"module"} */ (artifact),
|
|
585
|
+
delivered: scriptFontFiles(config, ["woff2"]) !== undefined,
|
|
586
|
+
});
|
|
579
587
|
if (styles !== undefined) merged.styles = styles;
|
|
580
588
|
|
|
581
589
|
// The index every consumer resolves this package's addresses through.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "23.12.
|
|
3
|
+
"version": "23.12.7",
|
|
4
4
|
"description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — content compilation, manifest, localization, staging, bundle, release and deployment.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -637,6 +637,13 @@ export type ContentBuildConfigInput = {
|
|
|
637
637
|
* Setting-wide neutral current date; defaults to "720.1".
|
|
638
638
|
*/
|
|
639
639
|
currentDate?: string | undefined;
|
|
640
|
+
/**
|
|
641
|
+
* Shortcode of the `lore` note with
|
|
642
|
+
* `subType: calendar` that prints the
|
|
643
|
+
* dates of a note no other rule gives a
|
|
644
|
+
* calendar.
|
|
645
|
+
*/
|
|
646
|
+
defaultCalendar?: string | undefined;
|
|
640
647
|
/**
|
|
641
648
|
* Content package name — the address
|
|
642
649
|
* namespace every note in this
|
|
@@ -696,6 +703,12 @@ export type ContentBuildConfigInput = {
|
|
|
696
703
|
* vocabulary is their union.
|
|
697
704
|
*/
|
|
698
705
|
itemBuilders?: Record<string, ItemBuilderEntry> | readonly ItemRegistrySpec[] | undefined;
|
|
706
|
+
/**
|
|
707
|
+
* The languages a
|
|
708
|
+
* note may tag text with, by short
|
|
709
|
+
* name. Default `{}`.
|
|
710
|
+
*/
|
|
711
|
+
languages?: Record<string, LanguageSpec> | undefined;
|
|
699
712
|
/**
|
|
700
713
|
* Packs to compile. More than one entry
|
|
701
714
|
* may share a `type`: a note then names
|
|
@@ -761,6 +774,11 @@ export type ContentBuildConfig = {
|
|
|
761
774
|
* Setting-wide neutral current date.
|
|
762
775
|
*/
|
|
763
776
|
currentDate: string;
|
|
777
|
+
/**
|
|
778
|
+
* The calendar of last resort's
|
|
779
|
+
* shortcode, `null` when none is named.
|
|
780
|
+
*/
|
|
781
|
+
defaultCalendar: string | null;
|
|
764
782
|
rootDir: string;
|
|
765
783
|
contentPackage: string;
|
|
766
784
|
/**
|
|
@@ -879,6 +897,10 @@ export type ContentBuildConfig = {
|
|
|
879
897
|
* none.
|
|
880
898
|
*/
|
|
881
899
|
icons: import("./engine/content-icons.mjs").IconRegistry;
|
|
900
|
+
/**
|
|
901
|
+
* Frozen; `{}` when absent.
|
|
902
|
+
*/
|
|
903
|
+
languages: Readonly<Record<string, Readonly<LanguageSpec>>>;
|
|
882
904
|
packs: readonly Readonly<ResolvedPackSpec>[];
|
|
883
905
|
/**
|
|
884
906
|
* Derived: every pack directory
|
|
@@ -906,3 +928,19 @@ export type ContentBuildConfig = {
|
|
|
906
928
|
relationships: Readonly<Relationships>;
|
|
907
929
|
publish: Readonly<PublishSwitches>;
|
|
908
930
|
};
|
|
931
|
+
/**
|
|
932
|
+
* One entry of `languages`.
|
|
933
|
+
*/
|
|
934
|
+
export type LanguageSpec = {
|
|
935
|
+
/**
|
|
936
|
+
* Its BCP 47 tag. A constructed language takes
|
|
937
|
+
* `art-x-<name>`.
|
|
938
|
+
*/
|
|
939
|
+
tag: string;
|
|
940
|
+
/**
|
|
941
|
+
* The Address of its language note, whose
|
|
942
|
+
* `data.words` is the lexicon a mapped run in the
|
|
943
|
+
* language reads first.
|
|
944
|
+
*/
|
|
945
|
+
note?: string | undefined;
|
|
946
|
+
};
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* the index refuses is a note the compile must still *report*, exactly as the
|
|
17
17
|
* compile loop reported it when the loop was the first to see it.
|
|
18
18
|
* @param {import("./content-session.mjs").ContentSession} [opts.session] - Captured context shared with other operations.
|
|
19
|
-
* @returns {Promise<{currentDate: string, records: object[], parsed: Map<string, object>, linkIndex: object, sqlTables: Map<string, object[]>|undefined, problems: object[], syntax?: import("./content-session.mjs").ContentSyntax}>} The corpus,
|
|
19
|
+
* @returns {Promise<{currentDate: string, runs: import("./content-scripts.mjs").RunContext, records: object[], parsed: Map<string, object>, linkIndex: object, sqlTables: Map<string, object[]>|undefined, problems: object[], syntax?: import("./content-session.mjs").ContentSyntax}>} The corpus,
|
|
20
20
|
* its indexes, and the notes it could not record.
|
|
21
21
|
*/
|
|
22
22
|
export function buildCompileCorpus({ contentBase, assetsBase, skipDirectories, router, config, problems, session, }: {
|
|
@@ -29,6 +29,7 @@ export function buildCompileCorpus({ contentBase, assetsBase, skipDirectories, r
|
|
|
29
29
|
session?: import("./content-session.mjs").ContentSession | undefined;
|
|
30
30
|
}): Promise<{
|
|
31
31
|
currentDate: string;
|
|
32
|
+
runs: import("./content-scripts.mjs").RunContext;
|
|
32
33
|
records: object[];
|
|
33
34
|
parsed: Map<string, object>;
|
|
34
35
|
linkIndex: object;
|
|
@@ -81,6 +81,8 @@ export function asciiAliases(aliases: unknown): Array<string>;
|
|
|
81
81
|
* `name` reads `Map 1` rather than `Figure 1` where it is due — see
|
|
82
82
|
* {@link module:engine/content-figures.scanFigures}.
|
|
83
83
|
* @param {import("./content-session.mjs").ContentSyntax} [options.syntax] - Session scanner projections.
|
|
84
|
+
* @param {import("./content-scripts.mjs").RunContext} [options.runContext] -
|
|
85
|
+
* The configured languages, which give each run's `lang=` its tag.
|
|
84
86
|
* @returns {Record<string, any>} The record, keys sorted at every depth. A
|
|
85
87
|
* **stub** — a note with an empty body, on a type an empty body suppresses —
|
|
86
88
|
* carries `address` and `anchors` as `null`: it publishes no page, so it
|
|
@@ -92,7 +94,7 @@ export function asciiAliases(aliases: unknown): Array<string>;
|
|
|
92
94
|
* otherwise be overwritten without a word. `file` and, where the file was
|
|
93
95
|
* read, `position` ride on the error.
|
|
94
96
|
*/
|
|
95
|
-
export function buildIndexRecord({ frontmatter, relPath, absPath, raw, contentPackage, body, bodyLine, bodyColumn, nameTypes, manifest, addressContext, dateContext, resolveRole, syntax, }: {
|
|
97
|
+
export function buildIndexRecord({ frontmatter, relPath, absPath, raw, contentPackage, body, bodyLine, bodyColumn, nameTypes, manifest, addressContext, dateContext, resolveRole, syntax, runContext, }: {
|
|
96
98
|
frontmatter: Record<string, any>;
|
|
97
99
|
relPath: string;
|
|
98
100
|
absPath?: string | undefined;
|
|
@@ -107,12 +109,13 @@ export function buildIndexRecord({ frontmatter, relPath, absPath, raw, contentPa
|
|
|
107
109
|
dateContext?: object | undefined;
|
|
108
110
|
resolveRole?: ((address: string) => string | undefined) | undefined;
|
|
109
111
|
syntax?: import("./content-session.mjs").ContentSyntax | undefined;
|
|
112
|
+
runContext?: import("./content-scripts.mjs").RunContext | undefined;
|
|
110
113
|
}): Record<string, any>;
|
|
111
114
|
/**
|
|
112
115
|
* Derive every index record belonging to one parsed note.
|
|
113
116
|
* @param {Parameters<typeof buildIndexRecord>[0]} options - Authored note and its context.
|
|
114
117
|
*/
|
|
115
|
-
export function indexRecordsForNote({ frontmatter, body, bodyLine, bodyColumn, nameTypes, relPath, absPath, raw, contentPackage, manifest, addressContext, dateContext, resolveRole, syntax, }: Parameters<typeof buildIndexRecord>[0]): object[];
|
|
118
|
+
export function indexRecordsForNote({ frontmatter, body, bodyLine, bodyColumn, nameTypes, relPath, absPath, raw, contentPackage, manifest, addressContext, dateContext, resolveRole, syntax, runContext, }: Parameters<typeof buildIndexRecord>[0]): object[];
|
|
116
119
|
/**
|
|
117
120
|
* Write each note's resolved culture into its record, as `data.culture`.
|
|
118
121
|
*
|
|
@@ -205,6 +208,12 @@ export function resolveCultures(records: Array<Record<string, any>>, { contentPa
|
|
|
205
208
|
* reader receives each as a finding, and the emitter throws once, listing
|
|
206
209
|
* every one.
|
|
207
210
|
* @param {string} [options.currentDate="720.1"] - Setting-wide neutral current date.
|
|
211
|
+
* @param {string} [options.defaultCalendar] - The calendar of last resort, a
|
|
212
|
+
* calendar note's shortcode; see {@link module:engine/note-calendars}.
|
|
213
|
+
* @param {string} [options.configFile] - The configuration file, where an
|
|
214
|
+
* unknown `defaultCalendar` is reported.
|
|
215
|
+
* @param {Readonly<Record<string, {tag: string}>>} [options.languages] - The
|
|
216
|
+
* configured languages, which give each run's `lang=` its tag.
|
|
208
217
|
* @param {(key: string) => ({culture?: unknown}|undefined)} [options.foreignRecord] -
|
|
209
218
|
* Another package's entry for a canonical address, read for a parent that
|
|
210
219
|
* package publishes; see {@link resolveCultures}.
|
|
@@ -217,7 +226,7 @@ export function resolveCultures(records: Array<Record<string, any>>, { contentPa
|
|
|
217
226
|
* @returns {Array<Record<string, any>>} The records, in a total order that does
|
|
218
227
|
* not depend on directory-read order.
|
|
219
228
|
*/
|
|
220
|
-
export function collectContentIndex(contentBase: string, { contentPackage, currentDate, skipDirectories, assetsBase, manifest, problems, addressContext, foreignRecord, parsed, sources, syntax, nameTypes, }: {
|
|
229
|
+
export function collectContentIndex(contentBase: string, { contentPackage, currentDate, defaultCalendar, configFile, languages, skipDirectories, assetsBase, manifest, problems, addressContext, foreignRecord, parsed, sources, syntax, nameTypes, }: {
|
|
221
230
|
contentPackage: string;
|
|
222
231
|
skipDirectories: readonly string[];
|
|
223
232
|
assetsBase?: string | undefined;
|
|
@@ -225,6 +234,11 @@ export function collectContentIndex(contentBase: string, { contentPackage, curre
|
|
|
225
234
|
addressContext?: object | undefined;
|
|
226
235
|
problems?: object[] | undefined;
|
|
227
236
|
currentDate?: string | undefined;
|
|
237
|
+
defaultCalendar?: string | undefined;
|
|
238
|
+
configFile?: string | undefined;
|
|
239
|
+
languages?: Readonly<Record<string, {
|
|
240
|
+
tag: string;
|
|
241
|
+
}>> | undefined;
|
|
228
242
|
foreignRecord?: ((key: string) => ({
|
|
229
243
|
culture?: unknown;
|
|
230
244
|
} | undefined)) | undefined;
|
|
@@ -49,3 +49,10 @@ export function renderPoetry(source: string): {
|
|
|
49
49
|
message: string;
|
|
50
50
|
}[];
|
|
51
51
|
};
|
|
52
|
+
/**
|
|
53
|
+
* The keys a poetry fence's attribute block takes. `lang`, `font` and `map`
|
|
54
|
+
* are read by `scanRuns` in content-scripts.mjs; `dir`, and on the site
|
|
55
|
+
* `data-pagefind-ignore`, are written by its rewrite of a fence set in one of
|
|
56
|
+
* the faces, and reach the element as they are written.
|
|
57
|
+
*/
|
|
58
|
+
export const POETRY_KEYS: readonly string[];
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The context a resolved configuration gives, and the maps an index holds.
|
|
3
|
+
*
|
|
4
|
+
* @param {{languages?: object, rootDir?: string}|undefined} config - The
|
|
5
|
+
* resolved configuration.
|
|
6
|
+
* @param {Iterable<Record<string, any>>} [records] - The content index's
|
|
7
|
+
* records, whose mapping notes give the maps. Without them no map is known.
|
|
8
|
+
* @returns {RunContext} Its languages, the faces installed where it sits, and
|
|
9
|
+
* the maps. A fonts package that cannot be read gives no faces; a run naming
|
|
10
|
+
* one is reported.
|
|
11
|
+
*/
|
|
12
|
+
export function runContext(config: {
|
|
13
|
+
languages?: object;
|
|
14
|
+
rootDir?: string;
|
|
15
|
+
} | undefined, records?: Iterable<Record<string, any>>): RunContext;
|
|
16
|
+
/**
|
|
17
|
+
* Find the spans, divs and poetry fences marked with `lang=`, `font=` or
|
|
18
|
+
* `map=`, and every fault in their markup and their text.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} source - Authored Markdown: a note body, or a whole file
|
|
21
|
+
* whose frontmatter is blanked.
|
|
22
|
+
* @param {RunContext} [ctx] - The configured languages, the installed faces
|
|
23
|
+
* and the maps. Without them every `lang=` must be a tag, every face and
|
|
24
|
+
* map is unknown, and only `mono`, `serif` and `sans` are fonts.
|
|
25
|
+
* @param {import("./content-session.mjs").ContentSyntax} [syntax] - Session
|
|
26
|
+
* scanner projections, so the source's spans and blocks are scanned once.
|
|
27
|
+
* @returns {{runs: Run[], errors: Array<{line: number, column: number, message: string}>, warnings: Array<{line: number, column: number, message: string}>}}
|
|
28
|
+
* The runs in source order, and each finding at its 1-based position. A
|
|
29
|
+
* warning is a `lang=` read as a tag that sits within one edit of a
|
|
30
|
+
* declared name.
|
|
31
|
+
*/
|
|
32
|
+
export function scanRuns(source: string, ctx?: RunContext, syntax?: import("./content-session.mjs").ContentSyntax): {
|
|
33
|
+
runs: Run[];
|
|
34
|
+
errors: Array<{
|
|
35
|
+
line: number;
|
|
36
|
+
column: number;
|
|
37
|
+
message: string;
|
|
38
|
+
}>;
|
|
39
|
+
warnings: Array<{
|
|
40
|
+
line: number;
|
|
41
|
+
column: number;
|
|
42
|
+
message: string;
|
|
43
|
+
}>;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Rewrite text marked with `lang=`, `font=` and `map=` into the plain span,
|
|
47
|
+
* div and poetry grammar the rest of each chain renders, one line for one line.
|
|
48
|
+
*
|
|
49
|
+
* - **The map, if any, is applied first.** Characters Markdown would read are
|
|
50
|
+
* then backslash-escaped, so they reach every later pass as characters.
|
|
51
|
+
* - **The construct carries** the language's tag as `lang`, the face's class
|
|
52
|
+
* (with `script`, and `script-block` on a div) or the generic family's
|
|
53
|
+
* class. On the site, a face's construct also carries
|
|
54
|
+
* `data-pagefind-ignore`, since site search cannot read its code points;
|
|
55
|
+
* Foundry and the book receive no search marker.
|
|
56
|
+
* - **A div or fence in a right-to-left face** carries `dir=rtl`. No direction
|
|
57
|
+
* mark, `<bdo>` or `<bdi>` is ever written: the code points carry their own
|
|
58
|
+
* direction.
|
|
59
|
+
*
|
|
60
|
+
* A run with a finding is left as written; {@link scanRuns} reports it.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} source - Authored Markdown: a note body.
|
|
63
|
+
* @param {RunContext} [ctx] - The configured languages, faces and maps.
|
|
64
|
+
* @param {import("./content-session.mjs").ContentSyntax} [syntax] - Session
|
|
65
|
+
* scanner projections.
|
|
66
|
+
* @param {{target?: "site"|"foundry"|"book"}} [options] - The target the
|
|
67
|
+
* Markdown is rendered for; only `site` writes the search marker.
|
|
68
|
+
* @returns {{markdown: string, errors: Array<{line: number, column: number, message: string}>}}
|
|
69
|
+
* The rewritten Markdown, and the findings of {@link scanRuns}.
|
|
70
|
+
*/
|
|
71
|
+
export function renderRuns(source: string, ctx?: RunContext, syntax?: import("./content-session.mjs").ContentSyntax, options?: {
|
|
72
|
+
target?: "site" | "foundry" | "book";
|
|
73
|
+
}): {
|
|
74
|
+
markdown: string;
|
|
75
|
+
errors: Array<{
|
|
76
|
+
line: number;
|
|
77
|
+
column: number;
|
|
78
|
+
message: string;
|
|
79
|
+
}>;
|
|
80
|
+
};
|
|
81
|
+
/** The keys this module reads, which no construct passes through as written. */
|
|
82
|
+
export const RUN_KEYS: readonly string[];
|
|
83
|
+
/** The generic families `font=` may name, each with the class that sets it. */
|
|
84
|
+
export const GENERIC_FONTS: Readonly<{
|
|
85
|
+
mono: "font-mono";
|
|
86
|
+
serif: "font-serif";
|
|
87
|
+
sans: "font-sans";
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* One marked construct, with what rendering it needs beside its {@link Run}.
|
|
91
|
+
*/
|
|
92
|
+
export type RunDetail = {
|
|
93
|
+
/**
|
|
94
|
+
* - The run.
|
|
95
|
+
*/
|
|
96
|
+
run: Run;
|
|
97
|
+
/**
|
|
98
|
+
* -
|
|
99
|
+
* What the construct carries besides the run keys.
|
|
100
|
+
*/
|
|
101
|
+
own: {
|
|
102
|
+
id: string;
|
|
103
|
+
classes: string[];
|
|
104
|
+
values: Array<[string, string]>;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* - The run keys it states itself.
|
|
108
|
+
*/
|
|
109
|
+
keys: Record<string, string>;
|
|
110
|
+
/**
|
|
111
|
+
* - Whether its text is set.
|
|
112
|
+
*/
|
|
113
|
+
plain: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* - Its face.
|
|
116
|
+
*/
|
|
117
|
+
face: import("./script-fonts.mjs").Face | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* - Its generic family's class.
|
|
120
|
+
*/
|
|
121
|
+
generic: string | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* - Its map.
|
|
124
|
+
*/
|
|
125
|
+
textMap: import("./text-maps.mjs").TextMap | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* - Its map,
|
|
128
|
+
* face and lexicon, which its text is set by.
|
|
129
|
+
*/
|
|
130
|
+
mapping: import("./map-lexicon.mjs").Mapping | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* - The marked spans inside it.
|
|
133
|
+
*/
|
|
134
|
+
holes: Map<number, number>;
|
|
135
|
+
/**
|
|
136
|
+
* - A div's or fence's body, as
|
|
137
|
+
* offsets: the first body line's start to the end of the last.
|
|
138
|
+
*/
|
|
139
|
+
body: [number, number] | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* - A span's offset of its closing `]`.
|
|
142
|
+
*/
|
|
143
|
+
contentEnd: number | undefined;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* What a run is checked against.
|
|
147
|
+
*/
|
|
148
|
+
export type RunContext = {
|
|
149
|
+
/**
|
|
150
|
+
* - The
|
|
151
|
+
* configured languages.
|
|
152
|
+
*/
|
|
153
|
+
languages?: Readonly<Record<string, {
|
|
154
|
+
tag: string;
|
|
155
|
+
}>> | undefined;
|
|
156
|
+
/**
|
|
157
|
+
* -
|
|
158
|
+
* The installed faces by slug, from
|
|
159
|
+
* {@link module :engine/script-fonts.resolveScriptFonts}.
|
|
160
|
+
*/
|
|
161
|
+
faces?: ReadonlyMap<string, import("./script-fonts.mjs").Face> | undefined;
|
|
162
|
+
/**
|
|
163
|
+
* -
|
|
164
|
+
* The mapping notes' maps by name, from
|
|
165
|
+
* {@link module :engine/text-maps.mapsFromRecords}.
|
|
166
|
+
*/
|
|
167
|
+
maps?: ReadonlyMap<string, import("./text-maps.mjs").TextMap> | undefined;
|
|
168
|
+
/**
|
|
169
|
+
* -
|
|
170
|
+
* Each configured language's lexicon by name, from
|
|
171
|
+
* {@link module :engine/map-lexicon.lexiconsFromRecords}.
|
|
172
|
+
*/
|
|
173
|
+
lexicons?: ReadonlyMap<string, import("./map-lexicon.mjs").Lexicon> | undefined;
|
|
174
|
+
/**
|
|
175
|
+
* -
|
|
176
|
+
* What each configured language's mapped runs are checked against, from
|
|
177
|
+
* {@link module :engine/run-words.wordBooksFromRecords}.
|
|
178
|
+
*/
|
|
179
|
+
wordBooks?: ReadonlyMap<string, import("./run-words.mjs").WordBook> | undefined;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* One span, div or poetry fence carrying `lang=`, `font=` or `map=`. Its
|
|
183
|
+
* `lang`, `font` and `map` are the ones it is set with: its own, else the
|
|
184
|
+
* innermost div or fence around it that states one.
|
|
185
|
+
*/
|
|
186
|
+
export type Run = {
|
|
187
|
+
/**
|
|
188
|
+
* - Which construct.
|
|
189
|
+
*/
|
|
190
|
+
kind: "span" | "block" | "poetry";
|
|
191
|
+
/**
|
|
192
|
+
* - The language as written.
|
|
193
|
+
*/
|
|
194
|
+
lang: string | undefined;
|
|
195
|
+
/**
|
|
196
|
+
* - The BCP 47 tag it resolves to; `undefined`
|
|
197
|
+
* when it resolves to none.
|
|
198
|
+
*/
|
|
199
|
+
tag: string | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* - The font as written.
|
|
202
|
+
*/
|
|
203
|
+
font: string | undefined;
|
|
204
|
+
/**
|
|
205
|
+
* - The map as written.
|
|
206
|
+
*/
|
|
207
|
+
map: string | undefined;
|
|
208
|
+
/**
|
|
209
|
+
* - 1-based line of the construct's opening.
|
|
210
|
+
*/
|
|
211
|
+
line: number;
|
|
212
|
+
/**
|
|
213
|
+
* - 1-based UTF-16 column of its opening.
|
|
214
|
+
*/
|
|
215
|
+
column: number;
|
|
216
|
+
/**
|
|
217
|
+
* - A span's offset of `[`; a div's or fence's
|
|
218
|
+
* 0-based opening line.
|
|
219
|
+
*/
|
|
220
|
+
start: number;
|
|
221
|
+
/**
|
|
222
|
+
* - A span's offset past its attributes; a div's or
|
|
223
|
+
* fence's 0-based closing line.
|
|
224
|
+
*/
|
|
225
|
+
end: number;
|
|
226
|
+
};
|