@heroiclands/package-build 6.1.0 → 8.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 +840 -0
- package/CONTENT.md +21 -1
- package/bin/content-build.mjs +105 -10
- package/bin/package-build.mjs +114 -1
- package/config.mjs +62 -3
- package/content-config.mjs +254 -22
- package/engine/base-compiler.mjs +25 -0
- package/engine/content-links.mjs +132 -27
- package/engine/diagnostics.mjs +61 -1
- package/engine/foreign-catalog.mjs +47 -0
- package/engine/generate.mjs +10 -5
- package/engine/helpers.mjs +38 -0
- package/engine/journals.mjs +8 -1
- package/engine/macros.mjs +2 -0
- package/engine/pack-config.mjs +143 -13
- package/engine/prose-lint.mjs +10 -2
- package/engine/scenes.mjs +2 -2
- package/engine/schema-check.mjs +332 -0
- package/engine/schema-extract.mjs +611 -0
- package/engine/web-wikilinks.mjs +13 -4
- package/engine/wikilink-syntax.mjs +25 -0
- package/engine/wikilinks.mjs +6 -3
- package/manifest.mjs +37 -2
- package/package.json +5 -3
- package/sohl/actors.mjs +23 -10
- package/sohl/item-fields.mjs +0 -35
- package/sohl/items.mjs +1 -1
- package/types/content-config.d.mts +14 -0
- package/types/engine/base-compiler.d.mts +18 -1
- package/types/engine/content-links.d.mts +11 -3
- package/types/engine/diagnostics.d.mts +33 -1
- package/types/engine/foreign-catalog.d.mts +15 -0
- package/types/engine/generate.d.mts +3 -2
- package/types/engine/helpers.d.mts +29 -3
- package/types/engine/journals.d.mts +7 -1
- package/types/engine/pack-config.d.mts +22 -0
- package/types/engine/prose-lint.d.mts +10 -2
- package/types/engine/schema-check.d.mts +176 -0
- package/types/engine/schema-extract.d.mts +61 -0
- package/types/engine/wikilink-syntax.d.mts +24 -0
- package/types/sohl/actors.d.mts +3 -3
package/engine/wikilinks.mjs
CHANGED
|
@@ -93,7 +93,7 @@ import { hasDocEntry, itemDocEntryId } from "./item-docs.mjs";
|
|
|
93
93
|
import { replaceOutsideCode } from "./code-fences.mjs";
|
|
94
94
|
// The syntax lives in `./wikilink-syntax.mjs`, so the web resolver and this
|
|
95
95
|
// one cannot disagree about what counts as a link.
|
|
96
|
-
import { WIKILINK, parseWikilink } from "./wikilink-syntax.mjs";
|
|
96
|
+
import { authoredLabel, WIKILINK, parseWikilink } from "./wikilink-syntax.mjs";
|
|
97
97
|
|
|
98
98
|
export { ITEM_PACK, PACK_BY_TYPE, packForType };
|
|
99
99
|
|
|
@@ -498,8 +498,11 @@ export function convertWikilinks(markdown, { type, id, pack, docPack, index }) {
|
|
|
498
498
|
const { labelled } = parsed;
|
|
499
499
|
let target = parsed.target;
|
|
500
500
|
// An unlabelled link shows its interior verbatim, anchor included;
|
|
501
|
-
// a labelled one shows its label.
|
|
502
|
-
|
|
501
|
+
// a labelled one shows its label. An *empty* label is not a label
|
|
502
|
+
// — `[[x|]]` means "show the target's name" — and that reading
|
|
503
|
+
// comes from {@link authoredLabel} so the web resolver cannot draw
|
|
504
|
+
// the line somewhere else (#113).
|
|
505
|
+
let text = labelled ? (authoredLabel(parsed) ?? "") : parsed.inner;
|
|
503
506
|
const slug = parsed.anchor || null;
|
|
504
507
|
|
|
505
508
|
// Resolve the document: same-page (empty target), type-shortcode, or alias.
|
package/manifest.mjs
CHANGED
|
@@ -430,8 +430,43 @@ export function buildManifest({ config, packageJson, artifact, flags }) {
|
|
|
430
430
|
...releaseUrls({ repoUrl, version: packageJson.version, artifact }),
|
|
431
431
|
};
|
|
432
432
|
if (config.compatibility) derived.compatibility = config.compatibility;
|
|
433
|
-
|
|
434
|
-
|
|
433
|
+
|
|
434
|
+
// `requiresSystem` is the gate half of the declare/require split (#48). It
|
|
435
|
+
// emits the `relationships.systems` entry Foundry's `supportsSystem` reads,
|
|
436
|
+
// reusing the `systems:` declaration rather than restating it — a second
|
|
437
|
+
// transcription is free to disagree with what it copied, which is how
|
|
438
|
+
// `stats.systemVersion` came to sit at `0.6.0` for four releases.
|
|
439
|
+
//
|
|
440
|
+
// Declaring a system emits nothing on its own. That is the point: a module
|
|
441
|
+
// shipping content for two systems names both under `systems:`, stamps each
|
|
442
|
+
// pack accordingly, and stays loadable everywhere because it requires
|
|
443
|
+
// neither.
|
|
444
|
+
const relationships = { ...(config.relationships ?? {}) };
|
|
445
|
+
if (config.requiresSystem) {
|
|
446
|
+
const declaredSystem = config.systems?.[config.requiresSystem];
|
|
447
|
+
const entry = {
|
|
448
|
+
id: config.requiresSystem,
|
|
449
|
+
type: "system",
|
|
450
|
+
...(declaredSystem?.manifest ?
|
|
451
|
+
{ manifest: declaredSystem.manifest }
|
|
452
|
+
: {}),
|
|
453
|
+
...(declaredSystem?.compatibility ?
|
|
454
|
+
{
|
|
455
|
+
compatibility: Object.fromEntries(
|
|
456
|
+
Object.entries(declaredSystem.compatibility).filter(
|
|
457
|
+
([, v]) => v != null,
|
|
458
|
+
),
|
|
459
|
+
),
|
|
460
|
+
}
|
|
461
|
+
: {}),
|
|
462
|
+
};
|
|
463
|
+
// An explicit `relationships.systems` still wins, so a repository
|
|
464
|
+
// mid-migration is never told two different things about itself.
|
|
465
|
+
relationships.systems =
|
|
466
|
+
relationships.systems?.length ? relationships.systems : [entry];
|
|
467
|
+
}
|
|
468
|
+
if (Object.keys(relationships).length) {
|
|
469
|
+
derived.relationships = publishedRelationships(relationships);
|
|
435
470
|
}
|
|
436
471
|
|
|
437
472
|
const merged = { ...declared, ...derived };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
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",
|
|
@@ -122,12 +122,12 @@
|
|
|
122
122
|
"classic-level": "^3.0.0",
|
|
123
123
|
"dotenv": "^17.2.3",
|
|
124
124
|
"fflate": "^0.8.3",
|
|
125
|
-
"glob": "^
|
|
125
|
+
"glob": "^13.0.6",
|
|
126
126
|
"gray-matter": "^4.0.3",
|
|
127
127
|
"handlebars": "^4.7.9",
|
|
128
128
|
"loglevel": "^1.9.2",
|
|
129
129
|
"loglevel-plugin-prefix": "^0.8.4",
|
|
130
|
-
"markdown-it": "^
|
|
130
|
+
"markdown-it": "^15.0.0",
|
|
131
131
|
"markdownlint-cli2": "^0.23.2",
|
|
132
132
|
"prettier": "^3.9.6",
|
|
133
133
|
"ssh2-sftp-client": "^12.1.1",
|
|
@@ -148,7 +148,9 @@
|
|
|
148
148
|
"build:types": "tsc -p tsconfig.dts.json",
|
|
149
149
|
"format": "prettier --write .",
|
|
150
150
|
"format:check": "prettier --check .",
|
|
151
|
+
"lint": "npm run format:check && npm run lint:markdown",
|
|
151
152
|
"lint:markdown": "node bin/content-build.mjs markdown",
|
|
153
|
+
"lint:markdown:fix": "node bin/content-build.mjs markdown --fix",
|
|
152
154
|
"changeset": "changeset",
|
|
153
155
|
"changeset:check": "changeset status --since=origin/main",
|
|
154
156
|
"changeset:version": "changeset version && npm install --package-lock-only",
|
package/sohl/actors.mjs
CHANGED
|
@@ -327,20 +327,33 @@ export class Actors extends BasePackCompiler {
|
|
|
327
327
|
itemsSourceDirs;
|
|
328
328
|
foreignSourceDirs;
|
|
329
329
|
|
|
330
|
-
constructor({ itemsSourceDirs, foreignSourceDirs = [], ...options }) {
|
|
330
|
+
constructor({ itemsSourceDirs = [], foreignSourceDirs = [], ...options }) {
|
|
331
331
|
super(options);
|
|
332
332
|
// Where the items passes wrote their JSON. Stated by the caller rather
|
|
333
333
|
// than assumed to be this pack's sibling: the packs' locations are
|
|
334
334
|
// configuration, and a consumer may put them anywhere (#1508). Every
|
|
335
335
|
// Item pack, because a repository may ship more than one (#1566).
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
336
|
+
//
|
|
337
|
+
// **Optional, and empty is a legitimate package (#49).** This used to
|
|
338
|
+
// throw unless at least one Item pack was declared, which asked a
|
|
339
|
+
// package to declare the very thing it may exist not to have. An Item
|
|
340
|
+
// pack is system-bound by construction — Foundry requires `system` on
|
|
341
|
+
// Item packs — so a deliberately system-agnostic module could satisfy
|
|
342
|
+
// the guard only by naming a system. `harn-ensemble` is the case:
|
|
343
|
+
// 2,512 beings whose embedded items address the `sohl` and `hm3`
|
|
344
|
+
// catalogues, and five affiliation notes of its own.
|
|
345
|
+
//
|
|
346
|
+
// The guard also did not test what it claimed. It counted *declared
|
|
347
|
+
// directories*, not resolvable items, so an empty Item pack satisfied
|
|
348
|
+
// it while a being naming a missing item still failed later. The
|
|
349
|
+
// condition actually cared about is checked where it can be reported
|
|
350
|
+
// precisely: {@link Actors#resolveEmbedded} already errors per
|
|
351
|
+
// unresolved `(type, shortcode)`, naming the being. A package whose
|
|
352
|
+
// beings embed nothing, or whose every address resolves against a
|
|
353
|
+
// dependency catalogue through `foreignSourceDirs`, now compiles with
|
|
354
|
+
// no Item pack at all — and one that is genuinely missing an item
|
|
355
|
+
// still fails, saying which item and which actor rather than which
|
|
356
|
+
// pack is absent.
|
|
344
357
|
Object.defineProperty(this, "itemsSourceDirs", {
|
|
345
358
|
value: Object.freeze([...itemsSourceDirs]),
|
|
346
359
|
writable: false,
|
|
@@ -641,7 +654,7 @@ export class Actors extends BasePackCompiler {
|
|
|
641
654
|
// `sohl.archetype` (required nullable number) drives
|
|
642
655
|
// `flags.sohl.docArchetype` (#640 / archetype contract #604).
|
|
643
656
|
flags: withArchetypeFlag(fm, fm.flags, ctx),
|
|
644
|
-
_stats:
|
|
657
|
+
_stats: this.stats,
|
|
645
658
|
_key: `!actors!${id}`,
|
|
646
659
|
};
|
|
647
660
|
}
|
package/sohl/item-fields.mjs
CHANGED
|
@@ -311,11 +311,6 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
311
311
|
value: false,
|
|
312
312
|
describe: "Whether it is currently dormant. Play state.",
|
|
313
313
|
},
|
|
314
|
-
{
|
|
315
|
-
to: "isTreated",
|
|
316
|
-
value: false,
|
|
317
|
-
describe: "Whether it has been treated. Play state.",
|
|
318
|
-
},
|
|
319
314
|
{
|
|
320
315
|
name: "levelBase",
|
|
321
316
|
to: "levelBase",
|
|
@@ -633,22 +628,6 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
633
628
|
required: true,
|
|
634
629
|
describe: "What kind of projectile it is.",
|
|
635
630
|
},
|
|
636
|
-
{
|
|
637
|
-
name: "impact.overrideDice",
|
|
638
|
-
to: "impactBase.overrideDice",
|
|
639
|
-
shape: "boolean",
|
|
640
|
-
read: (raw, { fm }) => Boolean(raw ?? impactDie(fm) > 0),
|
|
641
|
-
describe:
|
|
642
|
-
"Whether the projectile's dice replace the launching weapon's. Defaults to true when the projectile declares a die.",
|
|
643
|
-
},
|
|
644
|
-
{
|
|
645
|
-
name: "impact.overrideModifier",
|
|
646
|
-
to: "impactBase.overrideModifier",
|
|
647
|
-
shape: "boolean",
|
|
648
|
-
read: (raw) => Boolean(raw ?? false),
|
|
649
|
-
describe:
|
|
650
|
-
"Whether the projectile's modifier replaces the launching weapon's.",
|
|
651
|
-
},
|
|
652
631
|
{
|
|
653
632
|
to: "impactBase.numDice",
|
|
654
633
|
value: (fm) => (impactDie(fm) > 0 ? 1 : 0),
|
|
@@ -781,20 +760,6 @@ export const ITEM_FIELDS = Object.freeze({
|
|
|
781
760
|
describe:
|
|
782
761
|
"How the injury was inflicted. Unset on a descriptive condition.",
|
|
783
762
|
},
|
|
784
|
-
{
|
|
785
|
-
name: "isTreated",
|
|
786
|
-
to: "isTreated",
|
|
787
|
-
...BOOLEAN,
|
|
788
|
-
default: false,
|
|
789
|
-
describe: "Whether it has been treated.",
|
|
790
|
-
},
|
|
791
|
-
{
|
|
792
|
-
name: "isBleeding",
|
|
793
|
-
to: "isBleeding",
|
|
794
|
-
...BOOLEAN,
|
|
795
|
-
default: false,
|
|
796
|
-
describe: "Whether it is bleeding.",
|
|
797
|
-
},
|
|
798
763
|
{
|
|
799
764
|
name: "bodyLocationCode",
|
|
800
765
|
to: "bodyLocationCode",
|
package/sohl/items.mjs
CHANGED
|
@@ -167,7 +167,7 @@ export class Items extends BasePackCompiler {
|
|
|
167
167
|
// `sohl.archetype` (required nullable number) drives
|
|
168
168
|
// `flags.sohl.docArchetype` (#640 / archetype contract #604).
|
|
169
169
|
flags: withArchetypeFlag(fm, fm.flags, `item "${name}"`),
|
|
170
|
-
_stats:
|
|
170
|
+
_stats: this.stats,
|
|
171
171
|
ownership: { default: 0 },
|
|
172
172
|
folder,
|
|
173
173
|
_key: `!items!${id}`,
|
|
@@ -131,6 +131,20 @@ export const DEFAULT_ADDRESS_SCHEME: Readonly<{
|
|
|
131
131
|
* @satisfies {readonly SiteMode[]}
|
|
132
132
|
*/
|
|
133
133
|
export const SITE_MODES: readonly ["homepage", "content"];
|
|
134
|
+
/**
|
|
135
|
+
* How the loader hands {@link defineConfig} the system version it resolved.
|
|
136
|
+
*
|
|
137
|
+
* A **Symbol**, deliberately. `stats.systemVersion` is refused from an authored
|
|
138
|
+
* configuration (#48), but the value still has to reach here from the loader —
|
|
139
|
+
* which is the half that may do I/O, and which reads a system package's version
|
|
140
|
+
* out of the adjacent `package.json`. A string key would be a second spelling of
|
|
141
|
+
* the refused one, forgeable from YAML and reachable by `rejectUnknownKeys`; a
|
|
142
|
+
* symbol key cannot be written in YAML at all and does not appear in
|
|
143
|
+
* `Object.keys`, so the refusal has no back door.
|
|
144
|
+
*
|
|
145
|
+
* @type {symbol}
|
|
146
|
+
*/
|
|
147
|
+
export const DERIVED_SYSTEM_VERSION: symbol;
|
|
134
148
|
/**
|
|
135
149
|
* How much of a package reaches the web.
|
|
136
150
|
*
|
|
@@ -92,7 +92,7 @@ export class BasePackCompiler {
|
|
|
92
92
|
* @param {boolean} [options.routingReporter] - Whether this pass reports a
|
|
93
93
|
* note of its type that routes nowhere.
|
|
94
94
|
*/
|
|
95
|
-
constructor({ contentBase, dest, folderResolver, packName, docType, router, routingReporter, }?: {
|
|
95
|
+
constructor({ contentBase, dest, folderResolver, packName, packSystem, docType, router, routingReporter, }?: {
|
|
96
96
|
contentBase: string;
|
|
97
97
|
dest: string;
|
|
98
98
|
folderResolver?: ((path: string | null) => string | null) | undefined;
|
|
@@ -153,6 +153,22 @@ export class BasePackCompiler {
|
|
|
153
153
|
* @type {number}
|
|
154
154
|
*/
|
|
155
155
|
unresolvedLinks: number;
|
|
156
|
+
packSystem: any;
|
|
157
|
+
/**
|
|
158
|
+
* The `_stats` block every entry this pass emits is stamped with (#48).
|
|
159
|
+
*
|
|
160
|
+
* Per pack rather than per package, because a module may ship the same
|
|
161
|
+
* content for two systems — `harn-ensemble` has an `actors-hm3` pack and an
|
|
162
|
+
* `actors-sohl` pack — and those documents were built against different
|
|
163
|
+
* system versions. A single global block stamped both identically.
|
|
164
|
+
*
|
|
165
|
+
* Memoised on the instance: one pass, one pack, one system, so the block is
|
|
166
|
+
* constant for the life of the compiler. The previous module-level memo
|
|
167
|
+
* could not be, because it was shared across passes for different packs.
|
|
168
|
+
*
|
|
169
|
+
* @returns {object} The block, built once per compiler.
|
|
170
|
+
*/
|
|
171
|
+
get stats(): object;
|
|
156
172
|
/**
|
|
157
173
|
* Whether this pass's pack is the one a claimed note belongs in.
|
|
158
174
|
*
|
|
@@ -326,6 +342,7 @@ export class BasePackCompiler {
|
|
|
326
342
|
bodyLine: number | undefined;
|
|
327
343
|
bodyColumn: number | undefined;
|
|
328
344
|
} | undefined;
|
|
345
|
+
#private;
|
|
329
346
|
}
|
|
330
347
|
/**
|
|
331
348
|
* The tallies one pass accumulates while walking the tree.
|
|
@@ -46,9 +46,17 @@ export function buildLinkIndex(contentBase: string, { manifestDir, skipDirectori
|
|
|
46
46
|
* and what replaced it, so this is a fact rather than a guess — and it is
|
|
47
47
|
* exactly the SoHL defect.
|
|
48
48
|
* - A **hardcoded absolute URL** into this package's own prefix, or into one a
|
|
49
|
-
* vendored manifest names.
|
|
50
|
-
*
|
|
51
|
-
*
|
|
49
|
+
* vendored manifest names. Every one of them has a better form to write, which
|
|
50
|
+
* is why every one is reported — including a bare `/<package>/`, which names
|
|
51
|
+
* another package's landing (#87).
|
|
52
|
+
*
|
|
53
|
+
* That last case was exempt until the better form was identified, on the
|
|
54
|
+
* reasoning that a landing is in no link manifest so nothing could resolve it.
|
|
55
|
+
* True, and beside the point: it does not need resolving. A landing's address
|
|
56
|
+
* *is* its package prefix, so `/<package>/` is the absolute URL with the host
|
|
57
|
+
* struck off — host-free, emitted verbatim, and needing no index, which is
|
|
58
|
+
* what lets it hold in homepage-only mode where the tree is never walked. The
|
|
59
|
+
* form was already accepted here; nothing had ever named it as the one to use.
|
|
52
60
|
* - A **root-relative `url:`**, which the theme's `relURL` prefixes a second
|
|
53
61
|
* time. `href:` means "already resolved, use verbatim", so the same leading
|
|
54
62
|
* slash is correct there and is not reported.
|
|
@@ -169,12 +169,44 @@ export function positionOfLiteral(text: string, needle: string, occurrence?: num
|
|
|
169
169
|
* resolves to nothing — yields `{}`, so a caller spreads the result and the
|
|
170
170
|
* position is dropped rather than guessed.
|
|
171
171
|
*
|
|
172
|
+
* **`key: true` addresses the declaration rather than the value.** A finding
|
|
173
|
+
* about a *value* — this pack name is not in `packs[]` — belongs on the value,
|
|
174
|
+
* which is the default. A finding that names a **field** — `\`site.sections.x\`
|
|
175
|
+
* is not a recognized option` — sends the reader to look for that field, so the
|
|
176
|
+
* position should be the field's own, and in a flow mapping
|
|
177
|
+
* (`{ title: X, banner: Y }`) the two are different columns on one line. The
|
|
178
|
+
* key's node is found through the same parse, so this stays one locator rather
|
|
179
|
+
* than a second one free to disagree with it.
|
|
180
|
+
*
|
|
172
181
|
* @param {string} text - The document's contents.
|
|
173
182
|
* @param {ReadonlyArray<string|number>} keyPath - Path to the node: map keys as
|
|
174
183
|
* strings, sequence entries as numbers.
|
|
184
|
+
* @param {object} [opts]
|
|
185
|
+
* @param {boolean} [opts.key=false] - Report where the last segment is
|
|
186
|
+
* *declared* rather than where its value sits. Ignored for a sequence entry,
|
|
187
|
+
* which has no key.
|
|
175
188
|
* @returns {{line?: number, column?: number}} Spreadable position fields.
|
|
176
189
|
*/
|
|
177
|
-
export function positionOfYamlPath(text: string, keyPath: ReadonlyArray<string | number
|
|
190
|
+
export function positionOfYamlPath(text: string, keyPath: ReadonlyArray<string | number>, { key }?: {
|
|
191
|
+
key?: boolean | undefined;
|
|
192
|
+
}): {
|
|
178
193
|
line?: number;
|
|
179
194
|
column?: number;
|
|
180
195
|
};
|
|
196
|
+
/**
|
|
197
|
+
* The YAML key path a **dotted field path** addresses.
|
|
198
|
+
*
|
|
199
|
+
* Configuration checks report the offending key as the path a reader would
|
|
200
|
+
* write it — `packs[1].name`, `site.sections.affliction.title` — because that
|
|
201
|
+
* is what the message has to say. {@link positionOfYamlPath} addresses a node
|
|
202
|
+
* by segments instead, so this is the one translation between them: `.`
|
|
203
|
+
* separates map keys, and a bracketed suffix is a sequence index.
|
|
204
|
+
*
|
|
205
|
+
* A path this cannot parse yields `[]`, which {@link positionOfYamlPath} in
|
|
206
|
+
* turn resolves to no position — dropped rather than guessed, as everything
|
|
207
|
+
* else here is.
|
|
208
|
+
*
|
|
209
|
+
* @param {string} field - The dotted path, as a diagnostic spells it.
|
|
210
|
+
* @returns {Array<string|number>} Its segments, sequence indices as numbers.
|
|
211
|
+
*/
|
|
212
|
+
export function yamlKeyPath(field: string): Array<string | number>;
|
|
@@ -23,6 +23,15 @@ export function itemCatalogRelationships(config: object): Array<{
|
|
|
23
23
|
* @returns {string} The directory.
|
|
24
24
|
*/
|
|
25
25
|
export function catalogDir(config: object, id: string, version: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Where a cached dependency's published schema sits, if it shipped one.
|
|
28
|
+
*
|
|
29
|
+
* @param {object} config - The resolved configuration.
|
|
30
|
+
* @param {string} id - The dependency's package id.
|
|
31
|
+
* @param {string} version - Its resolved version.
|
|
32
|
+
* @returns {string} The path, whether or not it exists.
|
|
33
|
+
*/
|
|
34
|
+
export function cachedSchemaPath(config: object, id: string, version: string): string;
|
|
26
35
|
/**
|
|
27
36
|
* Write an unzipped archive's entries under `dest`.
|
|
28
37
|
*
|
|
@@ -101,3 +110,9 @@ export function fetchAllCatalogs(config: object): Promise<number>;
|
|
|
101
110
|
* @returns {string[]} Every cached dependency's item directories.
|
|
102
111
|
*/
|
|
103
112
|
export function foreignItemCatalogDirs(config: object): string[];
|
|
113
|
+
/**
|
|
114
|
+
* The file a system publishes its `system` field sets as (#60).
|
|
115
|
+
*
|
|
116
|
+
* @type {string}
|
|
117
|
+
*/
|
|
118
|
+
export const SCHEMA_ARTIFACT_FILE: string;
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
* @param {object} [config] - The resolved build configuration. Defaults to this
|
|
14
14
|
* repository's.
|
|
15
15
|
* @returns {string[]} Each Item pack's JSON directory. Empty when the
|
|
16
|
-
* repository ships no items at all
|
|
17
|
-
*
|
|
16
|
+
* repository ships no items at all, which is a legitimate package: the actors
|
|
17
|
+
* pass accepts an empty list and reports an item it cannot resolve per
|
|
18
|
+
* `(type, shortcode)` instead, naming the being (#49).
|
|
18
19
|
*/
|
|
19
20
|
export function itemPackJsonDirs(config?: object): string[];
|
|
20
21
|
/**
|
|
@@ -19,7 +19,7 @@ export function parseMarkdownFile(filePath: any): {
|
|
|
19
19
|
} | {
|
|
20
20
|
frontmatter: any;
|
|
21
21
|
body: string;
|
|
22
|
-
description:
|
|
22
|
+
description: string;
|
|
23
23
|
bodyLine: number;
|
|
24
24
|
bodyColumn: number;
|
|
25
25
|
};
|
|
@@ -56,7 +56,7 @@ export function walkMarkdownTree(rootDir: string, { skipDirectories }?: {
|
|
|
56
56
|
absPath: string;
|
|
57
57
|
frontmatter: any;
|
|
58
58
|
body: string;
|
|
59
|
-
description:
|
|
59
|
+
description: string;
|
|
60
60
|
bodyLine: number;
|
|
61
61
|
bodyColumn: number;
|
|
62
62
|
}, void, unknown>;
|
|
@@ -190,6 +190,32 @@ export function buildStats(systemVersion?: string, config?: {
|
|
|
190
190
|
packageManifest: string;
|
|
191
191
|
};
|
|
192
192
|
}): object;
|
|
193
|
+
/**
|
|
194
|
+
* The `_stats` block for one pack, stamped with the system that pack is for
|
|
195
|
+
* (#48).
|
|
196
|
+
*
|
|
197
|
+
* **`systemId` travels with `systemVersion`.** They are one decision, so where
|
|
198
|
+
* one is omitted both are. Stamping a per-pack version against a package-wide
|
|
199
|
+
* id would emit `systemId: sohl, systemVersion: 1.6.3` on HM3 documents — a
|
|
200
|
+
* *plausible lie*, which is worse than the missing value #43 fixed, because
|
|
201
|
+
* nothing about it looks wrong.
|
|
202
|
+
*
|
|
203
|
+
* Resolution, in order:
|
|
204
|
+
*
|
|
205
|
+
* 1. The pack's own `system:`, looked up in the `systems:` block. That is the
|
|
206
|
+
* case a module shipping for two systems needs, and the one no
|
|
207
|
+
* package-wide value could express.
|
|
208
|
+
* 2. Failing that, the package-wide `stats` — a package whose packs are all for
|
|
209
|
+
* one system, which is every package that worked before this existed.
|
|
210
|
+
*
|
|
211
|
+
* A pack naming a system is validated against `systems:` at configuration time,
|
|
212
|
+
* so an unresolvable name never reaches here.
|
|
213
|
+
*
|
|
214
|
+
* @param {string|null|undefined} packSystem - The pack's declared `system:`.
|
|
215
|
+
* @param {object} [config] - The resolved configuration.
|
|
216
|
+
* @returns {object} The `_stats` block for that pack.
|
|
217
|
+
*/
|
|
218
|
+
export function statsForPack(packSystem: string | null | undefined, config?: object): object;
|
|
193
219
|
/**
|
|
194
220
|
* The `_stats` block every compiler stamps on an entry it emits, built once.
|
|
195
221
|
*
|
|
@@ -342,7 +368,7 @@ export function folderFilename(name: any, id: any): string;
|
|
|
342
368
|
* pack, `"JournalEntry"` for the journals pack.
|
|
343
369
|
*/
|
|
344
370
|
export function writeFolderDocs(folders: any, stats: any, destDir: any, documentType: any): void;
|
|
345
|
-
export const md:
|
|
371
|
+
export const md: import("markdown-it").MarkdownIt;
|
|
346
372
|
export { slugify } from "./content-slug.mjs";
|
|
347
373
|
export { makeId } from "./ids.mjs";
|
|
348
374
|
export { getFrontmatter, sohlField, resolveCharges, resolveSkillAptitudes, resolveRelation, requireSubType, parseValueDesc } from "./frontmatter.mjs";
|
|
@@ -93,15 +93,21 @@ export function buildPages(rawPages: Array<object>, entryId: string, noteName: s
|
|
|
93
93
|
* heading; see {@link splitPages}.
|
|
94
94
|
* @param {string|null} [params.folder] - The folder id, or `null`.
|
|
95
95
|
* @param {object} [params.flags] - Document flags.
|
|
96
|
+
* @param {object} [params.stats] - The `_stats` block to stamp. Passed by the
|
|
97
|
+
* caller because it is a property of the *pack* being written, not of the
|
|
98
|
+
* entry: a module may ship the same content for two systems, and each pack's
|
|
99
|
+
* documents record the system version they were built against (#48). A
|
|
100
|
+
* caller with no pack in hand gets the package-wide block.
|
|
96
101
|
* @returns {object} The JournalEntry document, keyed for the pack.
|
|
97
102
|
*/
|
|
98
|
-
export function buildJournalEntry({ id, name, markdown, leadName, folder, flags, }: {
|
|
103
|
+
export function buildJournalEntry({ id, name, markdown, leadName, folder, flags, stats, }: {
|
|
99
104
|
id: string;
|
|
100
105
|
name: string;
|
|
101
106
|
markdown: string;
|
|
102
107
|
leadName?: string | undefined;
|
|
103
108
|
folder?: string | null | undefined;
|
|
104
109
|
flags?: object | undefined;
|
|
110
|
+
stats?: object | undefined;
|
|
105
111
|
}): object;
|
|
106
112
|
export class Journals extends BasePackCompiler {
|
|
107
113
|
/**
|
|
@@ -14,6 +14,28 @@
|
|
|
14
14
|
* {@link CONFIG_FILENAMES}.
|
|
15
15
|
*/
|
|
16
16
|
export function findConfigFile(from: string): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Attach the position of the key a configuration error names.
|
|
19
|
+
*
|
|
20
|
+
* Eighty-one checks across `content-config.mjs` and `config.mjs` report through
|
|
21
|
+
* one `fail()`, which knows the offending key's dotted path and nothing
|
|
22
|
+
* about where it was written. Locating one of them and not the rest would be
|
|
23
|
+
* worse than locating none — a reader would learn that some configuration
|
|
24
|
+
* errors carry a position and could not predict which — so the path rides on
|
|
25
|
+
* the error and every one of them is located here, at the boundary that knows
|
|
26
|
+
* which file was read (#95).
|
|
27
|
+
*
|
|
28
|
+
* The message keeps its body and gains the `file:line:column: error: ` prefix
|
|
29
|
+
* every other finding in this build already uses, so nothing a reader has today
|
|
30
|
+
* is lost. `located` marks it done, so an error crossing two boundaries is
|
|
31
|
+
* decorated once; the fields are also left on the error, for a caller that
|
|
32
|
+
* wants to re-render it.
|
|
33
|
+
*
|
|
34
|
+
* @param {unknown} err - What was thrown.
|
|
35
|
+
* @param {string} [configPath] - The configuration file that was read.
|
|
36
|
+
* @returns {unknown} The same error, decorated when it named a field.
|
|
37
|
+
*/
|
|
38
|
+
export function locateConfigError(err: unknown, configPath?: string): unknown;
|
|
17
39
|
/**
|
|
18
40
|
* Turn a parsed YAML configuration into the frozen one the engine reads.
|
|
19
41
|
*
|
|
@@ -36,8 +36,16 @@ export function checkFormatting(root: string, opts?: {
|
|
|
36
36
|
*
|
|
37
37
|
* {@link MARKDOWNLINT_CONFIG} is passed as markdownlint's `optionsDefault`,
|
|
38
38
|
* which is precisely the "shipped default, consumer overrides" behaviour the
|
|
39
|
-
* command promises: a
|
|
40
|
-
* and a
|
|
39
|
+
* command promises: a repository with no configuration of its own gets these
|
|
40
|
+
* rules, and a `.markdownlint-cli2.jsonc` found in the tree overrides them.
|
|
41
|
+
*
|
|
42
|
+
* The override is **key by key, and each key wholesale** — which is not the same
|
|
43
|
+
* as "replaces it", and the difference is the one worth stating. A consumer file
|
|
44
|
+
* declaring only `ignores` keeps this rule set intact, including `default: false`
|
|
45
|
+
* and every per-rule option; but its `ignores` *replaces*
|
|
46
|
+
* {@link MARKDOWN_IGNORES} rather than extending it, so such a file must restate
|
|
47
|
+
* every shared entry it still wants. Omitting `CHANGELOG.md` there silently
|
|
48
|
+
* starts linting a generated file.
|
|
41
49
|
*
|
|
42
50
|
* @param {string} root - Repository to lint.
|
|
43
51
|
* @param {object} [opts]
|