@heroiclands/package-build 19.0.0 → 20.2.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 +1100 -0
- package/CONTENT.md +264 -33
- package/README.md +43 -4
- package/bin/content-build.mjs +94 -3
- package/config.mjs +9 -1
- package/content-config.mjs +99 -19
- package/docs/content-format.md +394 -72
- package/e2e.mjs +297 -3
- package/engine/actor-compiler.mjs +197 -7
- package/engine/address-charset.mjs +23 -5
- package/engine/base-compiler.mjs +63 -2
- package/engine/bundles.mjs +9 -0
- package/engine/content-address.mjs +92 -1
- package/engine/content-charset.mjs +434 -0
- package/engine/content-format.mjs +102 -0
- package/engine/content-icons.mjs +388 -0
- package/engine/content-index.mjs +11 -8
- package/engine/content-links.mjs +37 -21
- package/engine/field-reference.mjs +57 -5
- package/engine/field-spec.mjs +214 -7
- package/engine/folder-notes.mjs +24 -1
- package/engine/foreign-catalog.mjs +112 -7
- package/engine/foundry-entries.mjs +14 -0
- package/engine/frontmatter-lint.mjs +377 -56
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +72 -12
- package/engine/helpers.mjs +96 -10
- package/engine/index.mjs +9 -0
- package/engine/item-compiler.mjs +37 -0
- package/engine/journals.mjs +21 -4
- package/engine/macros.mjs +8 -0
- package/engine/map-notes.mjs +7 -7
- package/engine/note-claims.mjs +208 -5
- package/engine/note-ids.mjs +25 -1
- package/engine/note-vocabulary.mjs +76 -9
- package/engine/pack-config.mjs +102 -12
- package/engine/pack-router.mjs +0 -0
- package/engine/prose-config.mjs +42 -0
- package/engine/prose-lint.mjs +126 -0
- package/engine/retired-fields.mjs +57 -16
- package/engine/runtime-only-fields.mjs +204 -0
- package/engine/scenes.mjs +12 -19
- package/engine/schema-check.mjs +23 -1
- package/engine/schema-extract.mjs +13 -0
- package/engine/site-index.mjs +17 -0
- package/engine/subtype-registry.mjs +30 -0
- package/engine/system-block.mjs +81 -3
- package/engine/web-wikilinks.mjs +33 -27
- package/engine/wikilink-syntax.mjs +7 -0
- package/engine/wikilinks.mjs +74 -16
- package/hm3/actors.mjs +63 -13
- package/package.json +2 -2
- package/sohl/actors.mjs +106 -7
- package/sohl/item-fields.mjs +203 -0
- package/sohl/note-schemas.mjs +6 -3
- package/types/config.d.mts +7 -0
- package/types/e2e.d.mts +130 -3
- package/types/engine/actor-compiler.d.mts +83 -3
- package/types/engine/address-charset.d.mts +22 -4
- package/types/engine/base-compiler.d.mts +54 -3
- package/types/engine/content-address.d.mts +64 -0
- package/types/engine/content-charset.d.mts +127 -0
- package/types/engine/content-format.d.mts +9 -0
- package/types/engine/content-icons.d.mts +151 -0
- package/types/engine/field-spec.d.mts +271 -3
- package/types/engine/folder-notes.d.mts +20 -0
- package/types/engine/foreign-catalog.d.mts +38 -2
- package/types/engine/foundry-entries.d.mts +6 -0
- package/types/engine/frontmatter-lint.d.mts +164 -30
- package/types/engine/frontmatter.d.mts +11 -11
- package/types/engine/generate.d.mts +27 -0
- package/types/engine/helpers.d.mts +45 -9
- package/types/engine/index.d.mts +3 -0
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/note-claims.d.mts +67 -0
- package/types/engine/note-ids.d.mts +14 -0
- package/types/engine/pack-config.d.mts +35 -0
- package/types/engine/prose-config.d.mts +41 -0
- package/types/engine/prose-lint.d.mts +36 -0
- package/types/engine/retired-fields.d.mts +29 -13
- package/types/engine/runtime-only-fields.d.mts +102 -0
- package/types/engine/schema-check.d.mts +10 -1
- package/types/engine/subtype-registry.d.mts +21 -0
- package/types/engine/system-block.d.mts +28 -2
- package/types/sohl/actors.d.mts +3 -3
package/content-config.mjs
CHANGED
|
@@ -69,6 +69,7 @@ import path from "node:path";
|
|
|
69
69
|
// a cycle around a consumer's config file (see `engine/pack-config.mjs`).
|
|
70
70
|
import { ADDRESS_SEGMENT_PATTERN, isAddressSegment } from "./engine/address-charset.mjs";
|
|
71
71
|
import { MAP_TYPES, PACK_BY_TYPE } from "./engine/ids.mjs";
|
|
72
|
+
import { ACTOR_TYPES } from "./engine/subtype-registry.mjs";
|
|
72
73
|
import { NOTE_VOCABULARY } from "./engine/note-vocabulary.mjs";
|
|
73
74
|
|
|
74
75
|
/**
|
|
@@ -1369,6 +1370,52 @@ function normalizeCompatibility(value, where, requireMinimum = true) {
|
|
|
1369
1370
|
* @param {unknown} value - The declared `systems:` mapping.
|
|
1370
1371
|
* @returns {Readonly<Record<string, Readonly<object>>>} Frozen; `{}` when absent.
|
|
1371
1372
|
*/
|
|
1373
|
+
/**
|
|
1374
|
+
* The **package-wide** system, or `null` where the configuration names none
|
|
1375
|
+
* (#48).
|
|
1376
|
+
*
|
|
1377
|
+
* A *system* package is its own system, which is true by construction and needs
|
|
1378
|
+
* no declaration. A *module* takes the one it requires, or the one system it
|
|
1379
|
+
* declares when there is exactly one; with several and no gate there is no
|
|
1380
|
+
* package-wide answer, and each pack carries its own.
|
|
1381
|
+
*
|
|
1382
|
+
* A lone `relationships.systems` entry is a declaration of the system as much as
|
|
1383
|
+
* a gate, so it still answers. That matters because the relationship carries
|
|
1384
|
+
* `itemCatalog` too — a separate concern the `systems:` split does not replace —
|
|
1385
|
+
* so a repository using it would otherwise have to restate its compatibility
|
|
1386
|
+
* under `systems:` purely to keep stamping, which is the duplication that split
|
|
1387
|
+
* exists to remove. Several entries have no single answer and get none.
|
|
1388
|
+
*
|
|
1389
|
+
* **Written once and read twice**, which is why it is a function rather than the
|
|
1390
|
+
* expression it used to be: the value stamped into `stats.systemId` and the
|
|
1391
|
+
* value a pack's `system:` is validated against are the same fact, and two
|
|
1392
|
+
* spellings of it would be free to disagree about exactly the case that has no
|
|
1393
|
+
* answer.
|
|
1394
|
+
*
|
|
1395
|
+
* @param {object} parts - The resolved pieces of the configuration.
|
|
1396
|
+
* @param {string} parts.packageKind - `systems` or `modules`.
|
|
1397
|
+
* @param {unknown} parts.foundryPackage - The package id.
|
|
1398
|
+
* @param {string|null} parts.requiresSystem - The declared gate, if any.
|
|
1399
|
+
* @param {Readonly<Record<string, object>>} parts.systems - The `systems:` block.
|
|
1400
|
+
* @param {readonly {id?: string}[]} parts.relationshipSystems - System
|
|
1401
|
+
* relationships.
|
|
1402
|
+
* @returns {string|null} The system id, or `null` where there is no single one.
|
|
1403
|
+
*/
|
|
1404
|
+
function packageWideSystemId({
|
|
1405
|
+
packageKind,
|
|
1406
|
+
foundryPackage,
|
|
1407
|
+
requiresSystem,
|
|
1408
|
+
systems,
|
|
1409
|
+
relationshipSystems,
|
|
1410
|
+
}) {
|
|
1411
|
+
if (packageKind === "systems") return /** @type {string} */ (foundryPackage);
|
|
1412
|
+
if (requiresSystem) return requiresSystem;
|
|
1413
|
+
const declared = Object.keys(systems);
|
|
1414
|
+
if (declared.length === 1) return declared[0];
|
|
1415
|
+
if (relationshipSystems.length === 1) return relationshipSystems[0]?.id ?? null;
|
|
1416
|
+
return null;
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1372
1419
|
function normalizeSystems(value) {
|
|
1373
1420
|
if (value === undefined || value === null) return Object.freeze({});
|
|
1374
1421
|
if (!isPlainObject(value)) fail("systems", "must be a mapping of id to spec");
|
|
@@ -1874,6 +1921,15 @@ export function defineConfig(config) {
|
|
|
1874
1921
|
const relationshipSystems = /** @type {{id?: string}[]} */ (
|
|
1875
1922
|
(isPlainObject(input.relationships) ? input.relationships.systems : null) ?? []
|
|
1876
1923
|
);
|
|
1924
|
+
// Read here as well as stamped below, so the check that a pack's `system:`
|
|
1925
|
+
// resolves to something and the value it resolves to are one statement.
|
|
1926
|
+
const packageWide = packageWideSystemId({
|
|
1927
|
+
packageKind,
|
|
1928
|
+
foundryPackage: input.foundryPackage,
|
|
1929
|
+
requiresSystem,
|
|
1930
|
+
systems,
|
|
1931
|
+
relationshipSystems,
|
|
1932
|
+
});
|
|
1877
1933
|
|
|
1878
1934
|
// A name that resolves to nothing is a build error rather than a
|
|
1879
1935
|
// fall-through, in the spirit the rest of this file already follows: a pack
|
|
@@ -1890,11 +1946,35 @@ export function defineConfig(config) {
|
|
|
1890
1946
|
}
|
|
1891
1947
|
for (const pack of packs.flatMap((p) => [p, ...p.companions])) {
|
|
1892
1948
|
if (!pack.system) continue;
|
|
1893
|
-
|
|
1949
|
+
// **A pack's `system:` must resolve to a stamp**, and there are exactly
|
|
1950
|
+
// two things it can resolve to: a `systems:` entry, which carries the
|
|
1951
|
+
// verified version `statsForPack` reads, or this package's own
|
|
1952
|
+
// package-wide system, whose stats answer for every pack of it.
|
|
1953
|
+
//
|
|
1954
|
+
// This used to be skipped entirely when `systems:` was empty or absent
|
|
1955
|
+
// — `declaredSystems.size &&` guarded it — which left the case the
|
|
1956
|
+
// comment above was written about wide open. `harn-ensemble` declares
|
|
1957
|
+
// `system: sohl` and `system: hm3` on its packs, no `systems:` block,
|
|
1958
|
+
// and no package-wide system, so every pack fell through to a
|
|
1959
|
+
// package-wide stat that is null: 2,513 compiled actors stamped
|
|
1960
|
+
// `_stats.systemId: null` in a pack that says `system: sohl` on the
|
|
1961
|
+
// line above. That is the plausible lie #43 was about, reached by the
|
|
1962
|
+
// one path this check did not cover, and the `requiresSystem` check ten
|
|
1963
|
+
// lines up already refuses its own version of it in as many words.
|
|
1964
|
+
if (!declaredSystems.has(pack.system) && pack.system !== packageWide) {
|
|
1894
1965
|
fail(
|
|
1895
1966
|
`packs.${pack.name}.system`,
|
|
1896
|
-
`names \`${pack.system}\`, which \`systems:\` does not ` +
|
|
1897
|
-
|
|
1967
|
+
`names \`${pack.system}\`, which \`systems:\` does not declare` +
|
|
1968
|
+
(declaredSystems.size ?
|
|
1969
|
+
` (declared: ${[...declaredSystems].join(", ")})`
|
|
1970
|
+
: ` — the \`systems:\` block is empty or absent`) +
|
|
1971
|
+
(packageWide ?
|
|
1972
|
+
`, and which is not this package's own system \`${packageWide}\``
|
|
1973
|
+
: `, and this package has no package-wide system either`) +
|
|
1974
|
+
`. Every document in the pack is stamped \`_stats.systemId\` ` +
|
|
1975
|
+
`and \`systemVersion\` from one of those two, so with ` +
|
|
1976
|
+
`neither it would be stamped null. Add \`systems:\` naming ` +
|
|
1977
|
+
`\`${pack.system}\` with a \`compatibility.verified\` version`,
|
|
1898
1978
|
);
|
|
1899
1979
|
}
|
|
1900
1980
|
// With a gate set, a pack for any other system could never be seen:
|
|
@@ -1953,7 +2033,15 @@ export function defineConfig(config) {
|
|
|
1953
2033
|
// holds every key any of them declares, so this stays "the registry's keys"
|
|
1954
2034
|
// rather than becoming a second list to keep in step (#1504).
|
|
1955
2035
|
const itemTypes = Object.freeze(new Set(Object.keys(itemBuilders)));
|
|
1956
|
-
|
|
2036
|
+
// Every note that compiles into a *system-bearing* document publishes its
|
|
2037
|
+
// prose as a documentation JournalEntry, and that includes actors (#337).
|
|
2038
|
+
// A being was the one such note with no `none` address — its only address
|
|
2039
|
+
// named the Actor — so nothing a prose link wrote could land on its page.
|
|
2040
|
+
// `doc` stays out for the reason that actually applies to it: its single
|
|
2041
|
+
// document *is* the prose.
|
|
2042
|
+
const docEntryTypes = Object.freeze(
|
|
2043
|
+
new Set([...itemTypes, ...ACTOR_TYPES, "macro", ...MAP_TYPES]),
|
|
2044
|
+
);
|
|
1957
2045
|
|
|
1958
2046
|
return Object.freeze({
|
|
1959
2047
|
rootDir,
|
|
@@ -1970,21 +2058,13 @@ export function defineConfig(config) {
|
|
|
1970
2058
|
// when there is exactly one; with several and no gate there is no
|
|
1971
2059
|
// package-wide answer, and each pack carries its own.
|
|
1972
2060
|
stats: normalizeStats(input.stats, {
|
|
1973
|
-
systemId:
|
|
1974
|
-
packageKind
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
// too — a separate concern the split does not replace — so
|
|
1981
|
-
// a repository using it would otherwise have to restate its
|
|
1982
|
-
// compatibility under `systems:` purely to keep stamping,
|
|
1983
|
-
// which is the duplication this whole change exists to
|
|
1984
|
-
// remove. Several entries have no single answer and get
|
|
1985
|
-
// none.
|
|
1986
|
-
: relationshipSystems.length === 1 ? (relationshipSystems[0]?.id ?? null)
|
|
1987
|
-
: null,
|
|
2061
|
+
systemId: packageWideSystemId({
|
|
2062
|
+
packageKind,
|
|
2063
|
+
foundryPackage,
|
|
2064
|
+
requiresSystem,
|
|
2065
|
+
systems,
|
|
2066
|
+
relationshipSystems,
|
|
2067
|
+
}),
|
|
1988
2068
|
// Derived here where the answer is pure data — the `verified` of
|
|
1989
2069
|
// whichever system the package-wide block takes — and supplied by
|
|
1990
2070
|
// the loader otherwise. The loader is the half that may do I/O, and
|