@heroiclands/package-build 22.14.1 → 22.14.3
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 +26 -0
- package/bin/content-build.mjs +6 -6
- package/bin/package-build.mjs +10 -0
- package/config.mjs +18 -1
- package/content-config.mjs +2 -2
- package/docs/api.md +63 -35
- package/docs/configuration.md +16 -7
- package/docs/content-format.md +157 -181
- package/docs/getting-started.md +42 -11
- package/docs/project-setup.md +5 -6
- package/engine/address.mjs +3 -5
- package/engine/asset-bindings.mjs +66 -0
- package/engine/calendar-notes.mjs +74 -0
- package/engine/changelog-lint.mjs +2 -2
- package/engine/content-index.mjs +63 -36
- package/engine/content-lint.mjs +1 -2
- package/engine/content-package.mjs +2 -2
- package/engine/content-tables.mjs +4 -8
- package/engine/folder-notes.mjs +1 -2
- package/engine/foundry-entries.mjs +21 -6
- package/engine/frontmatter-lint.mjs +3 -4
- package/engine/frontmatter.mjs +5 -8
- package/engine/helpers.mjs +3 -4
- package/engine/index.mjs +3 -0
- package/engine/infobox.mjs +67 -2
- package/engine/item-registry.mjs +2 -2
- package/engine/note-vocabulary.mjs +92 -6
- package/engine/pack-config.mjs +2 -2
- package/engine/pack-router.mjs +2 -2
- package/engine/pdf-render.mjs +1 -1
- package/engine/pdf-toc.mjs +3 -3
- package/engine/retired-fields.mjs +1 -1
- package/engine/scene-levels.mjs +4 -4
- package/engine/schema-check.mjs +1 -1
- package/engine/site-build.mjs +134 -121
- package/engine/site-preview.mjs +293 -0
- package/engine/site-root.mjs +20 -2
- package/engine/social-tie-terms.mjs +11 -0
- package/engine/social-ties.mjs +84 -0
- package/engine/sql-tables.mjs +4 -9
- package/hm3/actors.mjs +1 -1
- package/package.json +3 -3
- package/sohl/item-fields.mjs +2 -2
- package/types/config.d.mts +8 -0
- package/types/content-config.d.mts +1 -1
- package/types/engine/address.d.mts +3 -5
- package/types/engine/asset-bindings.d.mts +6 -0
- package/types/engine/calendar-notes.d.mts +12 -0
- package/types/engine/content-index.d.mts +11 -0
- package/types/engine/content-package.d.mts +2 -2
- package/types/engine/folder-notes.d.mts +1 -2
- package/types/engine/frontmatter-lint.d.mts +1 -2
- package/types/engine/frontmatter.d.mts +2 -4
- package/types/engine/helpers.d.mts +3 -4
- package/types/engine/index.d.mts +1 -0
- package/types/engine/item-registry.d.mts +2 -2
- package/types/engine/note-vocabulary.d.mts +5 -6
- package/types/engine/pack-config.d.mts +1 -1
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/pdf-render.d.mts +1 -1
- package/types/engine/pdf-toc.d.mts +1 -1
- package/types/engine/site-build.d.mts +36 -3
- package/types/engine/site-preview.d.mts +34 -0
- package/types/engine/social-tie-terms.d.mts +5 -0
- package/types/engine/social-ties.d.mts +10 -0
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { parseAddress, renderAddress } from "./address.mjs";
|
|
12
|
+
import { positionOfFrontmatterPath } from "./diagnostics.mjs";
|
|
13
|
+
import { SOCIAL_TIES } from "./social-tie-terms.mjs";
|
|
14
|
+
|
|
15
|
+
export { SOCIAL_TIES };
|
|
16
|
+
|
|
17
|
+
const TERMS = new Set(SOCIAL_TIES.map(({ term }) => term));
|
|
18
|
+
const ACCEPTED = new Set(["being", "affiliation"]);
|
|
19
|
+
|
|
20
|
+
/** Validate a being's map of defining relationships. */
|
|
21
|
+
export function checkSocialTies(note, { index } = {}) {
|
|
22
|
+
const ties = note.fm?.data?.socialTies;
|
|
23
|
+
if (ties === undefined || ties === null) return [];
|
|
24
|
+
const at = (key) => ({
|
|
25
|
+
file: note.file,
|
|
26
|
+
...positionOfFrontmatterPath(
|
|
27
|
+
note.raw ?? "",
|
|
28
|
+
key ? ["data", "socialTies", key] : ["data", "socialTies"],
|
|
29
|
+
{ key: true },
|
|
30
|
+
),
|
|
31
|
+
severity: "error",
|
|
32
|
+
});
|
|
33
|
+
if (typeof ties !== "object" || Array.isArray(ties))
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
...at(),
|
|
37
|
+
message: "data.socialTies must be a map of Address keys to relationship terms",
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
const findings = [];
|
|
41
|
+
for (const [key, term] of Object.entries(ties)) {
|
|
42
|
+
const tuple = parseAddress(
|
|
43
|
+
key,
|
|
44
|
+
{
|
|
45
|
+
package: index?.contentPackage ?? note.fm?.package,
|
|
46
|
+
system: "note",
|
|
47
|
+
types: index?.types,
|
|
48
|
+
packages: index?.packages,
|
|
49
|
+
},
|
|
50
|
+
{ declared: true },
|
|
51
|
+
);
|
|
52
|
+
if (tuple.reason) {
|
|
53
|
+
findings.push({
|
|
54
|
+
...at(key),
|
|
55
|
+
message: `data.socialTies key ${JSON.stringify(key)} is not a complete Address (${tuple.reason}); write being or affiliation as its type`,
|
|
56
|
+
});
|
|
57
|
+
} else if (!ACCEPTED.has(tuple.type)) {
|
|
58
|
+
findings.push({
|
|
59
|
+
...at(key),
|
|
60
|
+
message: `data.socialTies accepts being or affiliation, not ${tuple.type}`,
|
|
61
|
+
});
|
|
62
|
+
} else if (
|
|
63
|
+
tuple.package === (index?.contentPackage ?? note.fm?.package) &&
|
|
64
|
+
tuple.type === "being" &&
|
|
65
|
+
tuple.shortcode === note.fm?.shortcode
|
|
66
|
+
) {
|
|
67
|
+
findings.push({
|
|
68
|
+
...at(key),
|
|
69
|
+
message: `data.socialTies cannot address this being itself`,
|
|
70
|
+
});
|
|
71
|
+
} else if (index?.addressHit && !index.addressHit(renderAddress(tuple))) {
|
|
72
|
+
findings.push({
|
|
73
|
+
...at(key),
|
|
74
|
+
message: `data.socialTies target ${renderAddress(tuple)} does not resolve`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (!TERMS.has(term))
|
|
78
|
+
findings.push({
|
|
79
|
+
...at(key),
|
|
80
|
+
message: `data.socialTies value ${JSON.stringify(term)} must be one of ${SOCIAL_TIES.map(({ term: value }) => value).join(", ")}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return findings;
|
|
84
|
+
}
|
package/engine/sql-tables.mjs
CHANGED
|
@@ -14,15 +14,8 @@
|
|
|
14
14
|
/**
|
|
15
15
|
* Content tables written in SQL, queried over the content index.
|
|
16
16
|
*
|
|
17
|
-
* The
|
|
18
|
-
*
|
|
19
|
-
* is gone, and what remained was a hand-written parser and evaluator for someone
|
|
20
|
-
* else's language, kept faithful to semantics nothing checked it against.
|
|
21
|
-
*
|
|
22
|
-
* **The query is real SQL, run by DuckDB** — not a dialect maintained here. That
|
|
23
|
-
* is the whole point: a partial reimplementation would accept some valid SQL and
|
|
24
|
-
* silently misread the rest, which is worse than an unfamiliar language, because
|
|
25
|
-
* the boundary is invisible.
|
|
17
|
+
* **The query is SQL, run by DuckDB.** Its syntax and evaluation follow the
|
|
18
|
+
* database rather than a separate parser in the toolchain.
|
|
26
19
|
*
|
|
27
20
|
* **What SQL cannot say, the projection says.** Rendering a table is not a
|
|
28
21
|
* relational operation: which column links, and where a section breaks, are
|
|
@@ -273,6 +266,8 @@ export async function openNotesDatabase(records, { dir, dependencies = [], addre
|
|
|
273
266
|
};
|
|
274
267
|
},
|
|
275
268
|
async close() {
|
|
269
|
+
connection.closeSync();
|
|
270
|
+
instance.closeSync();
|
|
276
271
|
if (!dir) fs.rmSync(base, { recursive: true, force: true });
|
|
277
272
|
},
|
|
278
273
|
};
|
package/hm3/actors.mjs
CHANGED
|
@@ -170,7 +170,7 @@ function defaultActorImg(subType) {
|
|
|
170
170
|
* and `HM3.defaultPsionicsIconName` in the system's own `config.js` — so a
|
|
171
171
|
* compiled item looks like one created in the client. `weapongear` and
|
|
172
172
|
* `missilegear` need no row here: a reference spelled either resolves through
|
|
173
|
-
* `HM3_DEFAULT_ITEM_ART`'s own `weapongear` key
|
|
173
|
+
* `HM3_DEFAULT_ITEM_ART`'s own `weapongear` key, and every
|
|
174
174
|
* predefined weapon and missile in HM3's catalogue carries its own `img`.
|
|
175
175
|
*
|
|
176
176
|
* @type {Readonly<Record<string, string>>}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "22.14.
|
|
3
|
+
"version": "22.14.3",
|
|
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",
|
|
@@ -147,10 +147,10 @@
|
|
|
147
147
|
"loglevel": "^1.9.2",
|
|
148
148
|
"loglevel-plugin-prefix": "^0.8.4",
|
|
149
149
|
"markdown-it": "^15.0.0",
|
|
150
|
-
"markdownlint-cli2": "^0.23.
|
|
150
|
+
"markdownlint-cli2": "^0.23.3",
|
|
151
151
|
"pagefind": "^1.5.2",
|
|
152
152
|
"prettier": "^3.9.6",
|
|
153
|
-
"smol-toml": "^1.
|
|
153
|
+
"smol-toml": "^1.8.0",
|
|
154
154
|
"ssh2-sftp-client": "^12.1.1",
|
|
155
155
|
"typescript": "^6.0.3",
|
|
156
156
|
"unidecode": "^1.1.0",
|
package/sohl/item-fields.mjs
CHANGED
|
@@ -140,7 +140,7 @@ const DURATION_BASE = Object.freeze({
|
|
|
140
140
|
|
|
141
141
|
/** Aptitude weights per skill selector, validated as whole numbers. */
|
|
142
142
|
const SKILL_APTITUDES = Object.freeze({
|
|
143
|
-
shape: "map of skill selector
|
|
143
|
+
shape: "map of skill selector > whole number",
|
|
144
144
|
read: (_raw, { fm }) => resolveSkillAptitudes(fm, noteContext(fm, "mystery")),
|
|
145
145
|
});
|
|
146
146
|
|
|
@@ -188,7 +188,7 @@ const SKILL_UUID_ITEMS = Object.freeze({
|
|
|
188
188
|
|
|
189
189
|
/** Standings toward other affiliations, validated against the closed list. */
|
|
190
190
|
const RELATION = Object.freeze({
|
|
191
|
-
shape: "map of affiliation address
|
|
191
|
+
shape: "map of affiliation address > standing",
|
|
192
192
|
read: (_raw, { fm }) => resolveRelation(fm, noteContext(fm, "affiliation")),
|
|
193
193
|
});
|
|
194
194
|
|
package/types/config.d.mts
CHANGED
|
@@ -179,6 +179,14 @@ export type AssetSpec = {
|
|
|
179
179
|
* Destination, relative to the staged package root.
|
|
180
180
|
*/
|
|
181
181
|
to: string;
|
|
182
|
+
/**
|
|
183
|
+
* The foreign Address each file's basename claims, without its shortcode.
|
|
184
|
+
*/
|
|
185
|
+
bindsTo?: {
|
|
186
|
+
package: string;
|
|
187
|
+
system: string;
|
|
188
|
+
type: string;
|
|
189
|
+
} | undefined;
|
|
182
190
|
};
|
|
183
191
|
/**
|
|
184
192
|
* The resolved `packageBuild` section, every optional half filled in.
|
|
@@ -781,7 +781,7 @@ export type ContentBuildConfig = {
|
|
|
781
781
|
* Derived: the default art
|
|
782
782
|
* of each entry that paired one. Sparse — a
|
|
783
783
|
* type absent here has no default, and a note
|
|
784
|
-
* of it must carry `img
|
|
784
|
+
* of it must carry `img:`.
|
|
785
785
|
*/
|
|
786
786
|
itemArt: Readonly<Record<string, string>>;
|
|
787
787
|
/**
|
|
@@ -243,11 +243,9 @@ export function readCanonicalKey(key: unknown): {
|
|
|
243
243
|
* confidently they mark a value as qualified:
|
|
244
244
|
*
|
|
245
245
|
* - **`type-shortcode`** and its qualified forms — the canonical spelling.
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* - **`type/shortcode`** — resolved so that a link written before the vault
|
|
250
|
-
* migrated does not silently die. A slash is *unconditionally* a qualifier:
|
|
246
|
+
* The hyphenated form is portable across Markdown editors and renderers.
|
|
247
|
+
* - **`type/shortcode`** — an accepted qualified spelling. A slash is
|
|
248
|
+
* *unconditionally* a qualifier:
|
|
251
249
|
* nothing else uses one, so an unknown type before it is reported rather than
|
|
252
250
|
* guessed at. The split is at the **last** slash.
|
|
253
251
|
*
|
|
@@ -18,6 +18,14 @@ export function worldInvariants(index?: object): {
|
|
|
18
18
|
yearNote: object | null;
|
|
19
19
|
moonNote: object | null;
|
|
20
20
|
};
|
|
21
|
+
/** Check each authored format slot and every unescaped letter run in it. */
|
|
22
|
+
export function checkCalendarDateFormats(note: any): {
|
|
23
|
+
severity: any;
|
|
24
|
+
message: any;
|
|
25
|
+
line?: number;
|
|
26
|
+
column?: number;
|
|
27
|
+
file: any;
|
|
28
|
+
}[];
|
|
21
29
|
/**
|
|
22
30
|
* Check a `place` note's world facts.
|
|
23
31
|
*
|
|
@@ -150,6 +158,10 @@ export const CALENDAR_SUBTYPE: "calendar";
|
|
|
150
158
|
* @type {readonly string[]}
|
|
151
159
|
*/
|
|
152
160
|
export const INVARIANT_SUBTYPES: readonly string[];
|
|
161
|
+
/** Calendaria's display locations that a calendar note can format. */
|
|
162
|
+
export const CALENDAR_DATE_FORMAT_KEYS: readonly string[];
|
|
163
|
+
/** Bare date tokens Calendaria substitutes inside authored format strings. */
|
|
164
|
+
export const CALENDAR_FORMAT_TOKENS: Readonly<Set<string>>;
|
|
153
165
|
/**
|
|
154
166
|
* The `data:` keys a calendar note may write — the closed list, in authored
|
|
155
167
|
* order.
|
|
@@ -121,6 +121,17 @@ export function buildIndexRecord({ frontmatter, relPath, absPath, contentPackage
|
|
|
121
121
|
bodyLine?: number | undefined;
|
|
122
122
|
manifest?: object | undefined;
|
|
123
123
|
}): Record<string, any>;
|
|
124
|
+
/** Derive every index record belonging to one parsed note. */
|
|
125
|
+
export function indexRecordsForNote({ frontmatter, body, bodyLine, relPath, absPath, contentPackage, manifest, addressContext, }: {
|
|
126
|
+
frontmatter: any;
|
|
127
|
+
body: any;
|
|
128
|
+
bodyLine: any;
|
|
129
|
+
relPath: any;
|
|
130
|
+
absPath: any;
|
|
131
|
+
contentPackage: any;
|
|
132
|
+
manifest: any;
|
|
133
|
+
addressContext: any;
|
|
134
|
+
}): object[];
|
|
124
135
|
/**
|
|
125
136
|
* Read a content tree into index records, in the order they will be written.
|
|
126
137
|
*
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* package below would differ.
|
|
21
21
|
*
|
|
22
22
|
* An accessor rather than a hoisted constant, so that importing this module
|
|
23
|
-
* needs no configuration
|
|
23
|
+
* needs no configuration.
|
|
24
24
|
*
|
|
25
25
|
* @returns {string} The configured `contentPackage`.
|
|
26
26
|
*/
|
|
@@ -42,7 +42,7 @@ export function contentPackage(): string;
|
|
|
42
42
|
* written — fails the build if this value and the manifest's `id` ever drift.
|
|
43
43
|
*
|
|
44
44
|
* An accessor rather than a hoisted constant, so that importing this module
|
|
45
|
-
* needs no configuration
|
|
45
|
+
* needs no configuration.
|
|
46
46
|
*
|
|
47
47
|
* @returns {string} The configured `foundryPackage`.
|
|
48
48
|
*/
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* An authored `parent` with any wikilink brackets and label stripped.
|
|
3
3
|
*
|
|
4
4
|
* The specification types `parent` as an `Address`, written bare — but
|
|
5
|
-
* `[[address]]` is
|
|
6
|
-
* and Obsidian wrote that form for years. Accepting both costs one regex and
|
|
5
|
+
* `[[address]]` is also a recognizable link form. Accepting both costs one regex and
|
|
7
6
|
* removes a failure whose message would have to explain the difference.
|
|
8
7
|
*
|
|
9
8
|
* @param {string|null} value - As authored.
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Deliberately lenient about the spellings YAML makes ambiguous: `"12"` is a
|
|
5
5
|
* number, because a quoted scalar is how a number arrives from many editors,
|
|
6
|
-
* and a map authored as an empty list
|
|
7
|
-
* editor serialises an emptied map that way (#8). What it rejects is a value
|
|
6
|
+
* and a map authored as an empty list has no entries, just like `{}`. What it rejects is a value
|
|
8
7
|
* that cannot mean what the field is for — `weight: heavy`.
|
|
9
8
|
*
|
|
10
9
|
* @param {unknown} value - The authored value.
|
|
@@ -89,8 +89,7 @@ export function resolveCharges(fm: object): {
|
|
|
89
89
|
* kept — an element a sign leaves untouched still beats one another sign
|
|
90
90
|
* hinders, so it carries real weight when maps merge.
|
|
91
91
|
*
|
|
92
|
-
* An absent property, an empty map, and
|
|
93
|
-
* editor writes for a cleared map all mean the same thing — see
|
|
92
|
+
* An absent property, an empty map, and an empty list all mean the same thing — see
|
|
94
93
|
* {@link readMapEntries}.
|
|
95
94
|
*
|
|
96
95
|
* @param {object} fm - The item frontmatter.
|
|
@@ -108,8 +107,7 @@ export function resolveSkillAptitudes(fm: object, ctx?: string): Record<string,
|
|
|
108
107
|
* and be dropped silently, shipping an affiliation whose authored hostility had
|
|
109
108
|
* quietly become neutrality — so it is a build error instead.
|
|
110
109
|
*
|
|
111
|
-
* An absent property, an empty map, and
|
|
112
|
-
* editor writes for a cleared map all mean the same thing — neutral toward
|
|
110
|
+
* An absent property, an empty map, and an empty list all mean the same thing — neutral toward
|
|
113
111
|
* everyone. See {@link readMapEntries}.
|
|
114
112
|
*
|
|
115
113
|
* @param {object} fm - The item frontmatter.
|
|
@@ -72,9 +72,8 @@ export function assertSuppliedCorpus(records: readonly object[] | undefined, who
|
|
|
72
72
|
* is warned about and skipped.
|
|
73
73
|
*
|
|
74
74
|
* Directory names in `skipDirectories` are ignored wherever they appear. The
|
|
75
|
-
* walk itself knows nothing about what they mean: `Templates/` is
|
|
76
|
-
*
|
|
77
|
-
* of a content tree, so it is stated by the caller rather than hard-coded.
|
|
75
|
+
* walk itself knows nothing about what they mean: `Templates/` is authoring
|
|
76
|
+
* scaffolding rather than content, so the caller names it explicitly.
|
|
78
77
|
*
|
|
79
78
|
* @param {string} rootDir - Root of the tree to walk.
|
|
80
79
|
* @param {object} opts
|
|
@@ -319,7 +318,7 @@ export function statsForPack(packSystem: string | null | undefined, config?: obj
|
|
|
319
318
|
* Each compiler used to hoist `const STATS = buildStats()` at module scope,
|
|
320
319
|
* which read the shipped package manifest the moment the module was imported —
|
|
321
320
|
* so importing a compiler required a manifest to exist even when nothing was
|
|
322
|
-
* going to be compiled
|
|
321
|
+
* going to be compiled. Deferred to first use and memoised here, the
|
|
323
322
|
* cost and the identity are what they always were; only the moment moved.
|
|
324
323
|
*
|
|
325
324
|
* @returns {object} The default `_stats` block, shared by every compiler.
|
package/types/engine/index.d.mts
CHANGED
|
@@ -49,6 +49,7 @@ export * as assetIndex from "./asset-index.mjs";
|
|
|
49
49
|
export * as packages from "./packages.mjs";
|
|
50
50
|
export * as packagebuildIndex from "./packagebuild-index.mjs";
|
|
51
51
|
export * as siteBuild from "./site-build.mjs";
|
|
52
|
+
export * as sitePreview from "./site-preview.mjs";
|
|
52
53
|
export * as contentLint from "./content-lint.mjs";
|
|
53
54
|
export * as contentCharset from "./content-charset.mjs";
|
|
54
55
|
export * as contentIcons from "./content-icons.mjs";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* compile.
|
|
12
12
|
*
|
|
13
13
|
* An accessor rather than a hoisted constant, so that importing this module
|
|
14
|
-
* needs no configuration
|
|
14
|
+
* needs no configuration.
|
|
15
15
|
*
|
|
16
16
|
* @returns {ReadonlySet<string>} The configured item types.
|
|
17
17
|
*/
|
|
@@ -54,7 +54,7 @@ export function itemFields(type: string, system?: string): readonly object[] | u
|
|
|
54
54
|
* SoHL-owned table could never hold. Art is not looked up in
|
|
55
55
|
* `sohl/default-item-art.mjs` instead: a type was configurable while its
|
|
56
56
|
* default art was not, so a second consumer's items compiled only if every one
|
|
57
|
-
* of its notes set `img
|
|
57
|
+
* of its notes set `img:`.
|
|
58
58
|
*
|
|
59
59
|
* **Still fail-fast.** A type with neither a note-level `img:` nor paired art
|
|
60
60
|
* aborts the pack build rather than shipping a mismatched icon — the contract
|
|
@@ -36,14 +36,13 @@ export function exclusiveTagGroups(type: string, groups?: object): {
|
|
|
36
36
|
/**
|
|
37
37
|
* Whether a note carries a given tag, however the author wrote it.
|
|
38
38
|
*
|
|
39
|
-
* `tags:`
|
|
39
|
+
* `tags:` accepts common YAML forms: a single tag
|
|
40
40
|
* may be a scalar rather than a list, a value may carry the leading `#` it is
|
|
41
41
|
* written with in prose, and case and surrounding space are not significant.
|
|
42
42
|
* The spelling of the tag *itself* still is — a near miss is a near miss, and
|
|
43
43
|
* the frontmatter lint is what reports it; nothing here guesses.
|
|
44
44
|
*
|
|
45
|
-
* Reads `tags` and
|
|
46
|
-
* also accepts.
|
|
45
|
+
* Reads `tags` and the singular `tag` spelling.
|
|
47
46
|
*
|
|
48
47
|
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
49
48
|
* @param {string} tag - The tag to look for, in its declared spelling.
|
|
@@ -279,15 +278,15 @@ export type DataFieldSpec = {
|
|
|
279
278
|
* value — which is the honest answer wherever the specification's stated
|
|
280
279
|
* shape and the shape notes are authored in today disagree.
|
|
281
280
|
*/
|
|
282
|
-
kind?: "string" | "number" | "boolean" | "map" | "list" | "scalar-or-map" | "address" |
|
|
281
|
+
kind?: "string" | "number" | "boolean" | "map" | "list" | "shortcode" | "scalar-or-map" | "address" | undefined;
|
|
283
282
|
/**
|
|
284
283
|
* - Type of each list or pack-map value.
|
|
285
284
|
*/
|
|
286
|
-
entryKind?: "
|
|
285
|
+
entryKind?: "shortcode" | "address" | undefined;
|
|
287
286
|
/**
|
|
288
287
|
* - Type of each map key.
|
|
289
288
|
*/
|
|
290
|
-
keyKind?: "
|
|
289
|
+
keyKind?: "shortcode" | "address" | undefined;
|
|
291
290
|
/**
|
|
292
291
|
* - An alternative `subType:<skill-subtype>` key.
|
|
293
292
|
*/
|
|
@@ -105,7 +105,7 @@ export function configFromData(data: unknown, configPath: string): import("../co
|
|
|
105
105
|
*
|
|
106
106
|
* Every engine module that needs a configured value calls this, rather than
|
|
107
107
|
* hoisting one at import: that is what keeps the library importable without a
|
|
108
|
-
* configuration
|
|
108
|
+
* configuration. The result is memoised, so calling it in a default
|
|
109
109
|
* parameter — the usual spelling here — costs one property read per call.
|
|
110
110
|
*
|
|
111
111
|
* @returns {import("../content-config.mjs").ContentBuildConfig} The frozen configuration.
|
|
@@ -45,7 +45,7 @@ export function routerFor(config: object): ReturnType<typeof createPackRouter>;
|
|
|
45
45
|
* asks where a note's document lives.
|
|
46
46
|
*
|
|
47
47
|
* An accessor rather than a hoisted constant, so that importing this module
|
|
48
|
-
* needs no configuration
|
|
48
|
+
* needs no configuration. {@link routerFor} keeps one router per
|
|
49
49
|
* configuration object, so repeated calls return the same instance.
|
|
50
50
|
*
|
|
51
51
|
* @returns {ReturnType<typeof createPackRouter>} This repository's router.
|
|
@@ -111,7 +111,7 @@ export function bookTypstPreamble(): string;
|
|
|
111
111
|
/**
|
|
112
112
|
* The whole book, as one Typst document.
|
|
113
113
|
*
|
|
114
|
-
* **Pure, and that is the point.**
|
|
114
|
+
* **Pure, and that is the point.** The book's structural properties
|
|
115
115
|
* about structure — the outline's shape, the anchors, which links went inward,
|
|
116
116
|
* the order entries print in — is decided here from a plan and a map of bodies,
|
|
117
117
|
* with no filesystem and no compiler. {@link module:engine/pdf-build} supplies
|
|
@@ -67,7 +67,7 @@ export function runTreeFilters(nodes: object[], db: {
|
|
|
67
67
|
* The plan is an ordered list of entries — `section`, `prose`, `note` — and it
|
|
68
68
|
* is the artifact worth having. Order, depth, the outline, the table of
|
|
69
69
|
* contents, anchor uniqueness and every link destination are all readable from
|
|
70
|
-
* it, so
|
|
70
|
+
* it, so the book's structure can be asserted here, on data,
|
|
71
71
|
* without a renderer or a PDF. Only how the result *looks* needs eyes.
|
|
72
72
|
*
|
|
73
73
|
* **Notes are sorted, prose is not.** A section's entries come out in
|
|
@@ -141,9 +141,8 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
|
|
|
141
141
|
* The frontmatter a page publishes with.
|
|
142
142
|
*
|
|
143
143
|
* An authored `aliases` is retired and refused before a build reaches
|
|
144
|
-
* here, which makes this a guard rather than a working path. It
|
|
145
|
-
*
|
|
146
|
-
* the note, which is vault addressing and stays in the vault. Hugo reads
|
|
144
|
+
* here, which makes this a guard rather than a working path. It is a list of
|
|
145
|
+
* names a reader might call the note. Hugo reads
|
|
147
146
|
* `aliases` as **URL redirects**, so passing them through would publish a
|
|
148
147
|
* redirect stub at each name. They are dropped, and this build emits no
|
|
149
148
|
* redirects of its own.
|
|
@@ -228,6 +227,38 @@ export function pageFrontmatter(page: object, { decorate, webSrc, artSrc }: {
|
|
|
228
227
|
export function pageDestination(page: object, { bundle }?: {
|
|
229
228
|
bundle?: boolean | undefined;
|
|
230
229
|
}): string;
|
|
230
|
+
/** Transform one content page without writing the site mount. */
|
|
231
|
+
export function renderSitePage(page: any, { index, foreign, universe, pass, decorate, linkable, sqlTables, config, artIndex, }: {
|
|
232
|
+
index: any;
|
|
233
|
+
foreign: any;
|
|
234
|
+
universe: any;
|
|
235
|
+
pass?: {} | undefined;
|
|
236
|
+
decorate: any;
|
|
237
|
+
linkable?: ((d: any) => boolean) | undefined;
|
|
238
|
+
sqlTables: any;
|
|
239
|
+
config: any;
|
|
240
|
+
artIndex: any;
|
|
241
|
+
}): {
|
|
242
|
+
page: any;
|
|
243
|
+
body: string;
|
|
244
|
+
data: object;
|
|
245
|
+
resolved: any[];
|
|
246
|
+
tableErrors: {
|
|
247
|
+
source: string;
|
|
248
|
+
directive: string;
|
|
249
|
+
reason: string;
|
|
250
|
+
line: number;
|
|
251
|
+
column?: number;
|
|
252
|
+
}[];
|
|
253
|
+
secretErrors: {
|
|
254
|
+
file: any;
|
|
255
|
+
line: number;
|
|
256
|
+
column: number;
|
|
257
|
+
message: string;
|
|
258
|
+
}[];
|
|
259
|
+
wikiErrors: any[];
|
|
260
|
+
imageErrors: any[];
|
|
261
|
+
};
|
|
231
262
|
/**
|
|
232
263
|
* Renders and writes every page.
|
|
233
264
|
*
|
|
@@ -289,6 +320,8 @@ export function renderPages(pages: object[], options: object): {
|
|
|
289
320
|
export function resolveSitePass(name: string | undefined, options: object): {
|
|
290
321
|
beforeLinks?: Function;
|
|
291
322
|
};
|
|
323
|
+
/** The site frontmatter decoration shared by the site writer and page preview. */
|
|
324
|
+
export function sitePageDecorator(config: any, index: any): (data: any, page: any) => void;
|
|
292
325
|
/**
|
|
293
326
|
* Builds a Hugo content tree from a content tree, and reports what it found.
|
|
294
327
|
*
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Prepare saved project state once, then render live text without writing a site. */
|
|
2
|
+
export function prepareSitePreview({ config }?: {
|
|
3
|
+
config?: import("../content-config.mjs").ContentBuildConfig | undefined;
|
|
4
|
+
}): Promise<{
|
|
5
|
+
/** Render the active buffer. Other local and foreign notes remain saved. */
|
|
6
|
+
render(file: any, text: any): Promise<{
|
|
7
|
+
ok: boolean;
|
|
8
|
+
findings: {
|
|
9
|
+
file: string;
|
|
10
|
+
severity: string;
|
|
11
|
+
message: string;
|
|
12
|
+
}[];
|
|
13
|
+
markdown?: undefined;
|
|
14
|
+
frontmatter?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
findings: {
|
|
18
|
+
path: string;
|
|
19
|
+
link: string;
|
|
20
|
+
file: string;
|
|
21
|
+
severity: string;
|
|
22
|
+
}[];
|
|
23
|
+
markdown?: undefined;
|
|
24
|
+
frontmatter?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
markdown: string;
|
|
28
|
+
frontmatter: any;
|
|
29
|
+
findings: never[];
|
|
30
|
+
}>;
|
|
31
|
+
/** Re-read saved notes and dependency indexes after a save. */
|
|
32
|
+
refresh(): Promise<void>;
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Validate a being's map of defining relationships. */
|
|
2
|
+
export function checkSocialTies(note: any, { index }?: {}): {
|
|
3
|
+
message: string;
|
|
4
|
+
severity: string;
|
|
5
|
+
line?: number;
|
|
6
|
+
column?: number;
|
|
7
|
+
file: any;
|
|
8
|
+
}[];
|
|
9
|
+
export { SOCIAL_TIES };
|
|
10
|
+
import { SOCIAL_TIES } from "./social-tie-terms.mjs";
|