@heroiclands/package-build 22.21.0 → 22.23.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 +223 -0
- package/assets/styles/content-base.css +162 -0
- package/bin/content-commands.mjs +77 -17
- package/bin/package-build.mjs +15 -2
- package/ci/content-format-reference.mjs +68 -1
- package/config.mjs +26 -0
- package/content-config.mjs +153 -6
- package/docs/api.md +120 -89
- package/docs/authoring/assets.md +14 -0
- package/docs/authoring/dates-and-calendars.md +41 -3
- package/docs/authoring/frontmatter.md +2 -2
- package/docs/authoring/links-and-markup.md +325 -35
- package/docs/commands.md +12 -10
- package/docs/configuration.md +117 -14
- package/docs/content-format.md +4 -2
- package/docs/guides/book.md +5 -4
- package/docs/guides/reference-pages.md +15 -0
- package/docs/reference/format-details.md +545 -104
- package/docs/reference/note-types.md +30 -13
- package/engine/actor-compiler.mjs +23 -0
- package/engine/anchored-sections.mjs +35 -4
- package/engine/anchors.mjs +26 -30
- package/engine/art-fields.mjs +118 -0
- package/engine/art-slots.mjs +7 -1
- package/engine/asset-index.mjs +160 -10
- package/engine/asset-replacement.mjs +93 -0
- package/engine/asset-types.mjs +240 -0
- package/engine/base-compiler.mjs +139 -22
- package/engine/base-styles.mjs +149 -0
- package/engine/bundles.mjs +13 -2
- package/engine/compendiums.mjs +8 -1
- package/engine/content-blocks.mjs +410 -0
- package/engine/content-embeds.mjs +19 -0
- package/engine/content-figures.mjs +468 -0
- package/engine/content-footnotes.mjs +197 -0
- package/engine/content-format-check.mjs +15 -12
- package/engine/content-format.yaml +1 -1
- package/engine/content-images.mjs +126 -25
- package/engine/content-index.mjs +38 -12
- package/engine/content-links.mjs +14 -6
- package/engine/content-tables.mjs +45 -4
- package/engine/content-tasklists.mjs +189 -0
- package/engine/docs-checks.mjs +4 -4
- package/engine/extension-attributes.mjs +48 -2
- package/engine/field-reference.mjs +31 -10
- package/engine/field-spec.mjs +10 -8
- package/engine/foreign-catalog.mjs +143 -18
- package/engine/frontmatter-lint.mjs +120 -65
- package/engine/frontmatter.mjs +3 -3
- package/engine/heading-attributes.mjs +321 -0
- package/engine/helpers.mjs +109 -41
- package/engine/homepage.mjs +8 -8
- package/engine/index.mjs +3 -0
- package/engine/infobox-registry.mjs +4 -1
- package/engine/infobox-render.mjs +15 -3
- package/engine/infobox.mjs +129 -15
- package/engine/itinerary-scenes.mjs +4 -10
- package/engine/journals.mjs +294 -50
- package/engine/lore-events.mjs +197 -0
- package/engine/macros.mjs +1 -1
- package/engine/markdown-expressions.mjs +434 -59
- package/engine/note-dates.mjs +354 -12
- package/engine/note-frontmatter.mjs +7 -16
- package/engine/note-vocabulary.mjs +183 -42
- package/engine/page-lists.mjs +358 -0
- package/engine/pathnames.mjs +36 -0
- package/engine/pdf-build.mjs +431 -74
- package/engine/pdf-images.mjs +64 -0
- package/engine/pdf-render.mjs +563 -66
- package/engine/rank-ladder.mjs +198 -0
- package/engine/reckoning-markers.mjs +1 -1
- package/engine/retired-fields.mjs +8 -13
- package/engine/scenes.mjs +26 -7
- package/engine/site-build.mjs +166 -23
- package/engine/site-config.mjs +10 -1
- package/engine/site-index.mjs +90 -3
- package/engine/site-preview.mjs +20 -7
- package/engine/social-ties.mjs +52 -14
- package/engine/sql-tables.mjs +66 -9
- package/engine/standings.mjs +89 -6
- package/engine/system-block.mjs +56 -30
- package/engine/web-wikilinks.mjs +48 -1
- package/hm3/actors.mjs +8 -5
- package/manifest.mjs +43 -24
- package/package.json +1 -1
- package/packagebuild-metadata.jsonl +13 -13
- package/sohl/actors.mjs +22 -99
- package/sohl/item-fields.mjs +5 -5
- package/sohl/items.mjs +1 -1
- package/sohl/note-schemas.mjs +11 -21
- package/types/config.d.mts +9 -0
- package/types/content-config.d.mts +48 -1
- package/types/engine/actor-compiler.d.mts +11 -0
- package/types/engine/anchored-sections.d.mts +24 -0
- package/types/engine/anchors.d.mts +9 -4
- package/types/engine/art-fields.d.mts +64 -0
- package/types/engine/asset-index.d.mts +43 -0
- package/types/engine/asset-replacement.d.mts +22 -0
- package/types/engine/asset-types.d.mts +18 -0
- package/types/engine/base-compiler.d.mts +19 -17
- package/types/engine/base-styles.d.mts +93 -0
- package/types/engine/content-blocks.d.mts +87 -0
- package/types/engine/content-embeds.d.mts +16 -0
- package/types/engine/content-figures.d.mts +101 -0
- package/types/engine/content-footnotes.d.mts +80 -0
- package/types/engine/content-format-check.d.mts +8 -6
- package/types/engine/content-images.d.mts +78 -12
- package/types/engine/content-index.d.mts +8 -2
- package/types/engine/content-tables.d.mts +12 -4
- package/types/engine/content-tasklists.d.mts +72 -0
- package/types/engine/extension-attributes.d.mts +22 -1
- package/types/engine/field-reference.d.mts +21 -0
- package/types/engine/field-spec.d.mts +20 -16
- package/types/engine/foreign-catalog.d.mts +39 -0
- package/types/engine/frontmatter.d.mts +1 -1
- package/types/engine/heading-attributes.d.mts +179 -0
- package/types/engine/helpers.d.mts +29 -10
- package/types/engine/homepage.d.mts +7 -7
- package/types/engine/index.d.mts +1 -0
- package/types/engine/infobox-registry.d.mts +4 -1
- package/types/engine/infobox-render.d.mts +6 -1
- package/types/engine/infobox.d.mts +6 -0
- package/types/engine/journals.d.mts +41 -12
- package/types/engine/lore-events.d.mts +14 -0
- package/types/engine/markdown-expressions.d.mts +46 -2
- package/types/engine/note-dates.d.mts +64 -1
- package/types/engine/note-frontmatter.d.mts +1 -4
- package/types/engine/note-vocabulary.d.mts +82 -6
- package/types/engine/page-lists.d.mts +126 -0
- package/types/engine/pathnames.d.mts +26 -0
- package/types/engine/pdf-build.d.mts +28 -6
- package/types/engine/pdf-images.d.mts +52 -0
- package/types/engine/pdf-render.d.mts +84 -2
- package/types/engine/rank-ladder.d.mts +32 -0
- package/types/engine/retired-fields.d.mts +4 -6
- package/types/engine/site-build.d.mts +27 -4
- package/types/engine/site-config.d.mts +9 -0
- package/types/engine/site-index.d.mts +67 -1
- package/types/engine/site-preview.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +31 -7
- package/types/engine/standings.d.mts +21 -3
- package/types/engine/system-block.d.mts +37 -14
- package/types/engine/web-wikilinks.d.mts +3 -1
- package/types/hm3/actors.d.mts +21 -3
- package/types/manifest.d.mts +19 -23
- package/types/sohl/actors.d.mts +6 -7
- package/engine/content-admonitions.mjs +0 -114
- package/engine/content-captions.mjs +0 -181
- package/engine/content-secrets.mjs +0 -112
- package/types/engine/content-admonitions.d.mts +0 -24
- package/types/engine/content-captions.d.mts +0 -45
- package/types/engine/content-secrets.d.mts +0 -17
|
@@ -0,0 +1,197 @@
|
|
|
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
|
+
* Validate a `lore` note's `data.events` list, entry by entry.
|
|
16
|
+
*
|
|
17
|
+
* `data.events` is declared `kind: "list"` with a prose `shape`, the way
|
|
18
|
+
* `data.eras` already is (`engine/calendar-notes.mjs`), and checked by its own
|
|
19
|
+
* walker rather than by the generic `data:` container check, which only knows
|
|
20
|
+
* that the value is an array. Every finding here is positioned at
|
|
21
|
+
* `["data", "events", position, ...]`, so it lands on the entry that carries
|
|
22
|
+
* the fault rather than on the note.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { positionOfFrontmatterPath } from "./diagnostics.mjs";
|
|
28
|
+
import { parseNoteDate } from "./note-dates.mjs";
|
|
29
|
+
import { reckoningContext } from "./reckoning-markers.mjs";
|
|
30
|
+
|
|
31
|
+
/** Whether a value is a plain map — not `null`, not an array. */
|
|
32
|
+
function mapping(value) {
|
|
33
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Validate one `lore` note's `data.events`.
|
|
38
|
+
*
|
|
39
|
+
* Registered as the `events` field's own `check` in `note-vocabulary.mjs`, so
|
|
40
|
+
* it runs on every `lore` note regardless of `subType` — an occasion is not a
|
|
41
|
+
* calendar fact, and nothing here is scoped to `subType: calendar`.
|
|
42
|
+
*
|
|
43
|
+
* @param {object} note - The note, as the link index hands it over.
|
|
44
|
+
* @param {{index?: object}} [options]
|
|
45
|
+
* @returns {object[]} Findings, each positioned at the entry that earned it.
|
|
46
|
+
*/
|
|
47
|
+
export function checkLoreEvents(note, { index } = {}) {
|
|
48
|
+
const events = note.fm?.data?.events;
|
|
49
|
+
if (!Array.isArray(events)) return [];
|
|
50
|
+
|
|
51
|
+
const findings = [];
|
|
52
|
+
const dates = reckoningContext(index);
|
|
53
|
+
const at = (path, message) => ({
|
|
54
|
+
file: note.file,
|
|
55
|
+
...positionOfFrontmatterPath(note.raw ?? "", path),
|
|
56
|
+
severity: "error",
|
|
57
|
+
message,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
events.forEach((entry, position) => {
|
|
61
|
+
const row = mapping(entry) ? entry : {};
|
|
62
|
+
const base = ["data", "events", position];
|
|
63
|
+
|
|
64
|
+
const when = parseNoteDate(row.when, {
|
|
65
|
+
...dates,
|
|
66
|
+
allowUnknown: true,
|
|
67
|
+
allowZeroYear: true,
|
|
68
|
+
field: "when",
|
|
69
|
+
file: note.file,
|
|
70
|
+
raw: note.raw,
|
|
71
|
+
keyPath: [...base, "when"],
|
|
72
|
+
});
|
|
73
|
+
findings.push(...when.findings);
|
|
74
|
+
|
|
75
|
+
const until = parseNoteDate(row.until, {
|
|
76
|
+
...dates,
|
|
77
|
+
allowUnknown: false,
|
|
78
|
+
field: "until",
|
|
79
|
+
file: note.file,
|
|
80
|
+
raw: note.raw,
|
|
81
|
+
keyPath: [...base, "until"],
|
|
82
|
+
});
|
|
83
|
+
findings.push(...until.findings);
|
|
84
|
+
|
|
85
|
+
const recurs = row.recurs;
|
|
86
|
+
if (recurs === undefined || recurs === null) return;
|
|
87
|
+
|
|
88
|
+
if (row.when === undefined || row.when === null) {
|
|
89
|
+
findings.push(
|
|
90
|
+
at(
|
|
91
|
+
[...base, "recurs"],
|
|
92
|
+
"`recurs` needs a `when` of its own — a recurrence counts from the anchor it names",
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (when.date?.known && when.date.year === 0) {
|
|
98
|
+
findings.push(
|
|
99
|
+
at(
|
|
100
|
+
[...base, "recurs"],
|
|
101
|
+
"`recurs` is refused beside a `when` of year 0 — that date already recurs " +
|
|
102
|
+
"on that day every year, and `every` above 1 cannot be counted without " +
|
|
103
|
+
"an anchor year",
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (!mapping(recurs)) {
|
|
109
|
+
findings.push(at([...base, "recurs"], "`recurs` is a map of `every` or `on`"));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const hasEvery = Object.hasOwn(recurs, "every");
|
|
114
|
+
const hasOn = Object.hasOwn(recurs, "on");
|
|
115
|
+
if (hasEvery && hasOn) {
|
|
116
|
+
findings.push(
|
|
117
|
+
at(
|
|
118
|
+
[...base, "recurs"],
|
|
119
|
+
"`recurs` declares exactly one of `every` or `on`, not both — a period " +
|
|
120
|
+
"with exceptions is written as an enumeration",
|
|
121
|
+
),
|
|
122
|
+
);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!hasEvery && !hasOn) {
|
|
126
|
+
findings.push(
|
|
127
|
+
at(
|
|
128
|
+
[...base, "recurs"],
|
|
129
|
+
"`recurs` needs `every` or `on` — its absence is what says the occasion " +
|
|
130
|
+
"happened once",
|
|
131
|
+
),
|
|
132
|
+
);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (hasEvery) {
|
|
137
|
+
const { every } = recurs;
|
|
138
|
+
if (!(Number.isInteger(every) && every >= 1)) {
|
|
139
|
+
findings.push(
|
|
140
|
+
at(
|
|
141
|
+
[...base, "recurs", "every"],
|
|
142
|
+
`\`recurs.every\` needs a whole number of years, 1 or more, but reads ` +
|
|
143
|
+
`${JSON.stringify(every)}`,
|
|
144
|
+
),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (row.until !== undefined && row.until !== null) {
|
|
151
|
+
findings.push(
|
|
152
|
+
at(
|
|
153
|
+
[...base, "until"],
|
|
154
|
+
"`until` is refused beside `recurs.on` — the enumeration states its own " +
|
|
155
|
+
"last entry",
|
|
156
|
+
),
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const onList = recurs.on;
|
|
161
|
+
if (!Array.isArray(onList) || onList.length === 0) {
|
|
162
|
+
findings.push(at([...base, "recurs", "on"], "`recurs.on` needs a list of dates"));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let previous = when.date?.known ? when.date : null;
|
|
167
|
+
onList.forEach((onRaw, onPosition) => {
|
|
168
|
+
const onPath = [...base, "recurs", "on", onPosition];
|
|
169
|
+
const onParsed = parseNoteDate(onRaw, {
|
|
170
|
+
...dates,
|
|
171
|
+
allowUnknown: false,
|
|
172
|
+
field: "recurs.on",
|
|
173
|
+
file: note.file,
|
|
174
|
+
raw: note.raw,
|
|
175
|
+
keyPath: onPath,
|
|
176
|
+
});
|
|
177
|
+
findings.push(...onParsed.findings);
|
|
178
|
+
const onDate = onParsed.date;
|
|
179
|
+
if (onDate?.known && previous?.known) {
|
|
180
|
+
if (onDate.sort <= previous.sort) {
|
|
181
|
+
findings.push(
|
|
182
|
+
at(
|
|
183
|
+
onPath,
|
|
184
|
+
onPosition === 0 ?
|
|
185
|
+
"`recurs.on` entry is at or before `when`, so it is not a " +
|
|
186
|
+
"later occurrence"
|
|
187
|
+
: "`recurs.on` entries are not strictly increasing",
|
|
188
|
+
),
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (onDate?.known) previous = onDate;
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
return findings;
|
|
197
|
+
}
|
package/engine/macros.mjs
CHANGED