@heroiclands/package-build 22.22.0 → 22.24.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 +46 -0
- package/README.md +1 -0
- package/bin/content-commands.mjs +51 -14
- package/ci/content-format-reference.mjs +1 -1
- package/content-config.mjs +80 -2
- package/docs/api.md +85 -72
- package/docs/authoring/assets.md +29 -0
- package/docs/authoring/dates-and-calendars.md +37 -1
- package/docs/authoring/links-and-markup.md +112 -31
- package/docs/commands.md +30 -29
- package/docs/configuration.md +92 -19
- package/docs/content-format.md +1 -1
- package/docs/guides/book.md +5 -4
- package/docs/guides/module-project.md +2 -2
- package/docs/guides/site.md +41 -0
- package/docs/project-setup.md +4 -4
- package/docs/reference/format-details.md +323 -60
- package/docs/reference/note-types.md +9 -9
- package/docs/reference/theme-pages.md +496 -0
- package/engine/anchors.mjs +16 -10
- package/engine/art-fields.mjs +118 -0
- package/engine/art-slots.mjs +9 -2
- 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 +54 -2
- package/engine/bundles.mjs +13 -1
- package/engine/content-blocks.mjs +4 -4
- package/engine/content-embeds.mjs +19 -0
- package/engine/content-figures.mjs +468 -0
- package/engine/content-footnotes.mjs +10 -2
- package/engine/content-format.yaml +1 -1
- package/engine/content-images.mjs +126 -25
- package/engine/content-index.mjs +36 -10
- package/engine/field-reference.mjs +31 -10
- package/engine/field-spec.mjs +10 -8
- package/engine/foreign-catalog.mjs +145 -19
- package/engine/frontmatter-lint.mjs +73 -1
- package/engine/heading-attributes.mjs +31 -18
- package/engine/helpers.mjs +102 -33
- package/engine/infobox-registry.mjs +4 -1
- package/engine/infobox.mjs +47 -8
- package/engine/itinerary-scenes.mjs +4 -10
- package/engine/journals.mjs +264 -39
- package/engine/lore-events.mjs +197 -0
- package/engine/markdown-expressions.mjs +257 -7
- package/engine/note-dates.mjs +305 -12
- package/engine/note-vocabulary.mjs +11 -5
- package/engine/pathnames.mjs +36 -0
- package/engine/pdf-build.mjs +357 -34
- package/engine/pdf-images.mjs +64 -0
- package/engine/pdf-render.mjs +160 -36
- package/engine/scenes.mjs +16 -4
- package/engine/site-build.mjs +127 -13
- package/engine/site-config.mjs +19 -24
- package/engine/site-index.mjs +72 -1
- package/engine/site-preview.mjs +2 -0
- package/engine/system-block.mjs +44 -16
- package/hm3/actors.mjs +2 -2
- package/hugo-theme/data/banners.yaml +69 -0
- package/hugo-theme/layouts/404.html +85 -0
- package/hugo-theme/layouts/_default/baseof.html +64 -0
- package/hugo-theme/layouts/_default/list.html +139 -0
- package/hugo-theme/layouts/_default/single.html +4 -0
- package/hugo-theme/layouts/blog/list.html +54 -0
- package/hugo-theme/layouts/blog-post/single.html +36 -0
- package/hugo-theme/layouts/index.html +75 -0
- package/hugo-theme/layouts/partials/banner-url.html +117 -0
- package/hugo-theme/layouts/partials/cdn-url.html +36 -0
- package/hugo-theme/layouts/partials/draft-notice.html +41 -0
- package/hugo-theme/layouts/partials/draft-state.html +26 -0
- package/hugo-theme/layouts/partials/footer.html +29 -0
- package/hugo-theme/layouts/partials/header.html +35 -0
- package/hugo-theme/layouts/partials/hero-banner.html +86 -0
- package/hugo-theme/layouts/partials/holdings/entry.html +21 -0
- package/hugo-theme/layouts/partials/holdings/kind-groups.html +71 -0
- package/hugo-theme/layouts/partials/holdings.html +61 -0
- package/hugo-theme/layouts/partials/infobox/entry.html +15 -0
- package/hugo-theme/layouts/partials/infobox/items.html +26 -0
- package/hugo-theme/layouts/partials/infobox/section.html +56 -0
- package/hugo-theme/layouts/partials/infobox/value.html +43 -0
- package/hugo-theme/layouts/partials/infobox.html +57 -0
- package/hugo-theme/layouts/partials/page-body.html +154 -0
- package/hugo-theme/layouts/partials/place-map.html +9 -0
- package/hugo-theme/layouts/partials/related.html +121 -0
- package/hugo-theme/layouts/partials/search.html +84 -0
- package/hugo-theme/layouts/partials/site-url.html +32 -0
- package/hugo-theme/layouts/partials/tags.html +30 -0
- package/hugo-theme/layouts/partials/toc.html +28 -0
- package/hugo-theme/layouts/partials/warn-missing-banner.html +3 -0
- package/hugo-theme/layouts/shortcodes/cartouche.html +64 -0
- package/hugo-theme/layouts/shortcodes/exturl.html +12 -0
- package/hugo-theme/layouts/shortcodes/glyph.html +43 -0
- package/hugo-theme/layouts/shortcodes/pagelist.html +63 -0
- package/hugo-theme/static/css/sohl-icons.css +57 -0
- package/hugo-theme/static/css/style.css +2953 -0
- package/hugo-theme/static/fonts/game-icons-kb.woff2 +0 -0
- package/hugo-theme/static/img/banners/takheperu-hieroglyphs.svg +1 -0
- package/hugo-theme/static/img/cartouches/takheperu.svg +1 -0
- package/hugo-theme/theme.toml +11 -0
- package/manifest.mjs +30 -24
- package/package.json +2 -1
- package/packagebuild-metadata.jsonl +13 -13
- package/sohl/item-fields.mjs +4 -3
- package/types/content-config.d.mts +48 -1
- package/types/engine/anchors.d.mts +9 -4
- package/types/engine/art-fields.d.mts +64 -0
- package/types/engine/art-slots.d.mts +2 -1
- 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 +0 -17
- 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 +7 -0
- package/types/engine/content-images.d.mts +78 -12
- package/types/engine/content-index.d.mts +8 -2
- 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/heading-attributes.d.mts +13 -8
- package/types/engine/helpers.d.mts +28 -10
- package/types/engine/infobox-registry.d.mts +4 -1
- package/types/engine/infobox.d.mts +6 -0
- package/types/engine/journals.d.mts +31 -9
- package/types/engine/lore-events.d.mts +14 -0
- package/types/engine/markdown-expressions.d.mts +23 -2
- package/types/engine/note-dates.d.mts +64 -1
- 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 +12 -0
- package/types/engine/site-build.d.mts +14 -3
- package/types/engine/site-config.d.mts +9 -9
- package/types/engine/site-index.d.mts +54 -0
- package/types/engine/system-block.d.mts +26 -2
- package/types/hm3/actors.d.mts +18 -0
- package/types/manifest.d.mts +19 -23
- package/engine/content-captions.mjs +0 -230
- package/types/engine/content-captions.d.mts +0 -58
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 22.24.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
**Hero banners** — A page whose note names its own hero image shows that image, in place of the stock banner for its kind; a note naming none gets a band with no image.
|
|
8
|
+
|
|
9
|
+
**Figures** — A numbered figure, table, listing or map reads as one block, its number and caption set beneath it rather than running on as body text, and a passage set apart as an aside draws as a box.
|
|
10
|
+
|
|
11
|
+
**Pictures** — A portrait or an emblem draws at half the content column and a banner, plate or map at its full width, never wider than the size the picture was made at; a stated width still overrides the role's measure.
|
|
12
|
+
|
|
13
|
+
**Installing** — The shared Hugo theme arrives with this package, so a site declares this package alone and needs no separate theme dependency.
|
|
14
|
+
|
|
15
|
+
**Hero images** — The authoring guide states the three states of a note's hero image: a picture, a deliberate blank that declines one, and an absent key that takes the default for the note's type.
|
|
16
|
+
|
|
17
|
+
## 22.23.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
**Figures**
|
|
22
|
+
|
|
23
|
+
- A picture and the words about it are written as one block: the caption is optional, several pictures can share one, and a border is available.
|
|
24
|
+
- Prose refers to a figure by name, in its own note or in another, and reads back its number, its number and caption, or the caption alone.
|
|
25
|
+
- A figure drawn from a map counts as a Map, numbered the same way on every surface.
|
|
26
|
+
- A figure holding one picture opens as an illustrated page in Foundry, with that viewer's own pop-out and zoom.
|
|
27
|
+
|
|
28
|
+
**Pictures**
|
|
29
|
+
|
|
30
|
+
- A picture carrying no caption draws no line beneath it, on a page, in a journal or in print.
|
|
31
|
+
- A picture states what it is for, and is drawn at the size that choice gives it — never larger than it was made.
|
|
32
|
+
- A page's hero image is 1792×768, and one of any other size is refused, naming the size to cut it to.
|
|
33
|
+
|
|
34
|
+
**Art provenance**
|
|
35
|
+
|
|
36
|
+
- A record saying a file is not machine-generated is published saying so.
|
|
37
|
+
- A package may refuse generated art in its own tree.
|
|
38
|
+
- A package may declare that a dependency's art answers its own addresses, and the book draws the replacement.
|
|
39
|
+
|
|
40
|
+
**Notes**
|
|
41
|
+
|
|
42
|
+
- A lore note states the occasions it records, each with a date and an optional recurrence, and publishes the next one due.
|
|
43
|
+
- A note may write a shared field at the position it is being retired from, and the build accepts it with a warning rather than refusing the note.
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
**Item-frontmatter reference**: regenerating the page no longer renders a broken sentence for `affiliation`'s `title`, which now says plainly that a top-level key is refused outright.
|
|
48
|
+
|
|
3
49
|
## 22.22.0
|
|
4
50
|
|
|
5
51
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ The documentation lives in the Markdown files in this repository. Start with [th
|
|
|
33
33
|
| Detailed format rules and examples | [Format details](docs/reference/format-details.md) |
|
|
34
34
|
| Compendium routing and document builds | [Packs](docs/guides/packs.md) |
|
|
35
35
|
| Website build and publication | [Site](docs/guides/site.md) |
|
|
36
|
+
| What the theme draws on a page | [Theme pages](docs/reference/theme-pages.md) |
|
|
36
37
|
| PDF book build | [Book](docs/guides/book.md) |
|
|
37
38
|
| Icon generation and use | [Icons](docs/guides/icons.md) |
|
|
38
39
|
| Reference pages and content indexes | [Reference pages](docs/guides/reference-pages.md) |
|
package/bin/content-commands.mjs
CHANGED
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
import { fetchNavigation, generateHugoConfig, writeHugoConfig } from "../engine/site-config.mjs";
|
|
65
65
|
import { renderItemFieldReference, renderItemFieldsPage } from "../engine/field-reference.mjs";
|
|
66
66
|
import { checkDocLinks, checkDocIndex } from "../engine/docs-checks.mjs";
|
|
67
|
+
import { checkArtSlotSizes } from "../engine/art-fields.mjs";
|
|
67
68
|
import { lintContentTree } from "../engine/content-lint.mjs";
|
|
68
69
|
import { lintNoteStates } from "../engine/stub-lint.mjs";
|
|
69
70
|
import { lintContentCharset } from "../engine/content-charset.mjs";
|
|
@@ -109,6 +110,7 @@ import {
|
|
|
109
110
|
authoredFrontmatter,
|
|
110
111
|
emitContentIndex,
|
|
111
112
|
indexRecordsFor,
|
|
113
|
+
isAssetRecord,
|
|
112
114
|
isNoteRecord,
|
|
113
115
|
noteFile,
|
|
114
116
|
} from "../engine/content-index.mjs";
|
|
@@ -139,6 +141,7 @@ import { buildMaps, FROM_ALL, MAP_DIR } from "../engine/map-build.mjs";
|
|
|
139
141
|
import { CHART_HORIZON_DAYS } from "../engine/map-layout.mjs";
|
|
140
142
|
import { GRAPHVIZ_ENGINES } from "../engine/map-graphviz.mjs";
|
|
141
143
|
import { loadMapWorld } from "../engine/map-places.mjs";
|
|
144
|
+
import { encodeAddresses } from "../engine/address-values.mjs";
|
|
142
145
|
|
|
143
146
|
/**
|
|
144
147
|
* The packs `unpack` extracts.
|
|
@@ -1175,6 +1178,32 @@ function lintCommand() {
|
|
|
1175
1178
|
});
|
|
1176
1179
|
for (const line of states.summary) log.info(line);
|
|
1177
1180
|
|
|
1181
|
+
// Generated art, when this package declares it carries none.
|
|
1182
|
+
// `records` already holds every asset of this build, so the
|
|
1183
|
+
// check is a filter over the corpus already in hand rather
|
|
1184
|
+
// than a second enumeration of the asset trees.
|
|
1185
|
+
const generatedArt =
|
|
1186
|
+
config.forbidGeneratedArt ?
|
|
1187
|
+
records
|
|
1188
|
+
.filter(isAssetRecord)
|
|
1189
|
+
.filter((record) => record.asset.ai === true)
|
|
1190
|
+
.map((record) => ({
|
|
1191
|
+
file: path.join(config.paths.assets, record.asset.path),
|
|
1192
|
+
severity: "error",
|
|
1193
|
+
message:
|
|
1194
|
+
`\`${encodeAddresses(record.address.canonical)}\` is ` +
|
|
1195
|
+
"machine-generated art (`ai: true`), and " +
|
|
1196
|
+
"`forbidGeneratedArt` refuses it in this package",
|
|
1197
|
+
}))
|
|
1198
|
+
: [];
|
|
1199
|
+
|
|
1200
|
+
// A hero image against the size its slot is cut to, read
|
|
1201
|
+
// from the records already in hand.
|
|
1202
|
+
const artSizes = checkArtSlotSizes(records, {
|
|
1203
|
+
config,
|
|
1204
|
+
assetsBase: config.paths.assets,
|
|
1205
|
+
});
|
|
1206
|
+
|
|
1178
1207
|
const findings = [
|
|
1179
1208
|
...addresses.findings,
|
|
1180
1209
|
...frontmatter.findings,
|
|
@@ -1185,6 +1214,8 @@ function lintCommand() {
|
|
|
1185
1214
|
...images.findings,
|
|
1186
1215
|
...taskLists.findings,
|
|
1187
1216
|
...states.findings,
|
|
1217
|
+
...generatedArt,
|
|
1218
|
+
...artSizes,
|
|
1188
1219
|
];
|
|
1189
1220
|
// Only an **error** fails the run. Every finding was an error
|
|
1190
1221
|
// by then, so this changes nothing on its own —
|
|
@@ -1820,6 +1851,9 @@ function siteCommand() {
|
|
|
1820
1851
|
for (const e of result.footnoteErrors) {
|
|
1821
1852
|
emitDiagnostic({ ...e, severity: "error" });
|
|
1822
1853
|
}
|
|
1854
|
+
for (const e of result.embedErrors) {
|
|
1855
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1856
|
+
}
|
|
1823
1857
|
// Reported the way the pack build reports the very same
|
|
1824
1858
|
// finding: `file:line:column: error: message`, path first, and
|
|
1825
1859
|
// the message from the shared table, not a
|
|
@@ -1862,7 +1896,8 @@ function siteCommand() {
|
|
|
1862
1896
|
result.headingErrors.length ||
|
|
1863
1897
|
result.footnoteErrors.length ||
|
|
1864
1898
|
result.wikiErrors.length ||
|
|
1865
|
-
result.imageErrors.length
|
|
1899
|
+
result.imageErrors.length ||
|
|
1900
|
+
result.embedErrors.length
|
|
1866
1901
|
) {
|
|
1867
1902
|
process.exitCode = 1;
|
|
1868
1903
|
return;
|
|
@@ -2195,16 +2230,18 @@ async function fetchFromLocalArtifact(config, argv) {
|
|
|
2195
2230
|
|
|
2196
2231
|
/**
|
|
2197
2232
|
* `deps fetch` — fill the caches this build resolves other packages through:
|
|
2198
|
-
* the **content index** of every declared dependency, the **item catalogue
|
|
2199
|
-
* of those additionally declaring `itemCatalog: true
|
|
2200
|
-
*
|
|
2201
|
-
* menu from.
|
|
2202
|
-
*
|
|
2203
|
-
* The
|
|
2204
|
-
* *addresses
|
|
2205
|
-
*
|
|
2206
|
-
*
|
|
2207
|
-
*
|
|
2233
|
+
* the **content index** of every declared dependency, the **item catalogue
|
|
2234
|
+
* or asset archive** of those additionally declaring `itemCatalog: true` or
|
|
2235
|
+
* `assetArchive: true`, and the **site navigation** heroiclands.org
|
|
2236
|
+
* publishes, which the site build writes its menu from.
|
|
2237
|
+
*
|
|
2238
|
+
* The dependency sets differ deliberately. Citing another package's
|
|
2239
|
+
* *addresses*, embedding its *items*, and staging its *asset bytes* are
|
|
2240
|
+
* separate edges, and a package may declare any of them without the others —
|
|
2241
|
+
* `harn-ensemble` cites no foreign address and embeds 324,016 item
|
|
2242
|
+
* references. The navigation is fetched for every package, because every
|
|
2243
|
+
* package publishes a site. A relationship declaring both `itemCatalog: true`
|
|
2244
|
+
* and `assetArchive: true` is fetched once.
|
|
2208
2245
|
*
|
|
2209
2246
|
* Its own command rather than a step of `package compile` or `site`, so that
|
|
2210
2247
|
* neither reaches the network. A build that downloads silently is not
|
|
@@ -2265,7 +2302,7 @@ function depsCommand() {
|
|
|
2265
2302
|
const indexes = await fetchAllMetadata(config);
|
|
2266
2303
|
if (indexes) log.info(`Fetched ${indexes} dependency content index(es).`);
|
|
2267
2304
|
const count = await fetchAllCatalogs(config);
|
|
2268
|
-
if (count) log.info(`Fetched ${count} dependency catalogue(s).`);
|
|
2305
|
+
if (count) log.info(`Fetched ${count} dependency catalogue(s) or archive(s).`);
|
|
2269
2306
|
if (!indexes && !count) {
|
|
2270
2307
|
// Distinguished from a package declaring nothing at all: a
|
|
2271
2308
|
// relationship may still be declared, just narrowed to the
|
|
@@ -2277,8 +2314,8 @@ function depsCommand() {
|
|
|
2277
2314
|
);
|
|
2278
2315
|
log.info(
|
|
2279
2316
|
declared ?
|
|
2280
|
-
"No declared dependency needs a fetched content index
|
|
2281
|
-
"catalogue."
|
|
2317
|
+
"No declared dependency needs a fetched content index, item " +
|
|
2318
|
+
"catalogue, or asset archive."
|
|
2282
2319
|
: "This package declares no dependencies.",
|
|
2283
2320
|
);
|
|
2284
2321
|
}
|
|
@@ -137,7 +137,7 @@ const GENERATED_TABLES = [
|
|
|
137
137
|
"| ------ | ---------- | ----------------- |",
|
|
138
138
|
...Object.entries(EXPRESSION_HELPERS).map(
|
|
139
139
|
([name, { params, summary }]) =>
|
|
140
|
-
`| \`${name}\` | \`${params}\` | ${cell(summary)} |`,
|
|
140
|
+
`| \`${cell(name)}\` | \`${cell(params)}\` | ${cell(summary)} |`,
|
|
141
141
|
),
|
|
142
142
|
],
|
|
143
143
|
},
|
package/content-config.mjs
CHANGED
|
@@ -368,7 +368,8 @@ export function publishesContentPages(config) {
|
|
|
368
368
|
* @property {string} [stage] Compiled LevelDB packs.
|
|
369
369
|
* @property {string} [unpack] Where `unpack` extracts JSON back to.
|
|
370
370
|
* @property {string} [foreignCache] Where a dependency declaring
|
|
371
|
-
* `itemCatalog: true`
|
|
371
|
+
* `itemCatalog: true` or
|
|
372
|
+
* `assetArchive: true` is unpacked.
|
|
372
373
|
* Inbound, and fetched rather than
|
|
373
374
|
* committed.
|
|
374
375
|
* @property {string} [metadataCache] Where a dependency's published content
|
|
@@ -486,6 +487,15 @@ export function publishesContentPages(config) {
|
|
|
486
487
|
* package this one targets — for a system
|
|
487
488
|
* relationship, `verified` is what
|
|
488
489
|
* `_stats.systemVersion` is stamped from.
|
|
490
|
+
* @property {boolean} [itemCatalog] Whether `deps fetch` unpacks this
|
|
491
|
+
* dependency's release archive and extracts
|
|
492
|
+
* its Item packs, so the actors pass can
|
|
493
|
+
* resolve embedded items this repository
|
|
494
|
+
* does not hold. Needs a `manifest`.
|
|
495
|
+
* @property {boolean} [assetArchive] Whether `deps fetch` unpacks this
|
|
496
|
+
* dependency's release archive for its
|
|
497
|
+
* asset bytes alone, building no item
|
|
498
|
+
* catalogue from it. Needs a `manifest`.
|
|
489
499
|
* @property {boolean} [contentIndex] Whether `deps fetch` fetches this
|
|
490
500
|
* dependency's content index. Default
|
|
491
501
|
* `true`. `false` declares the dependency
|
|
@@ -494,6 +504,13 @@ export function publishesContentPages(config) {
|
|
|
494
504
|
* `itemCatalog: true` on the same entry,
|
|
495
505
|
* since a catalogue is fetched from the same
|
|
496
506
|
* index.
|
|
507
|
+
* @property {boolean} [assetReplacement] Whether this dependency's asset
|
|
508
|
+
* tree answers this package's own asset
|
|
509
|
+
* addresses ahead of its local record.
|
|
510
|
+
* Default `false`. Refuses `contentIndex:
|
|
511
|
+
* false` on the same entry, since a
|
|
512
|
+
* replacement with no fetched index to
|
|
513
|
+
* check against resolves nothing.
|
|
497
514
|
*/
|
|
498
515
|
|
|
499
516
|
/**
|
|
@@ -620,6 +637,9 @@ export function publishesContentPages(config) {
|
|
|
620
637
|
* @property {string[]} [skipDirectories] Directory names the content walk ignores
|
|
621
638
|
* wherever they appear (e.g. Obsidian's
|
|
622
639
|
* `Templates`). Default `[]`.
|
|
640
|
+
* @property {boolean} [forbidGeneratedArt] Whether `lint` refuses an asset
|
|
641
|
+
* record of this package carrying
|
|
642
|
+
* `ai: true`. Default `false`.
|
|
623
643
|
* @property {PackageBuildSection} [packageBuild] Reserved for
|
|
624
644
|
* `@heroiclands/package-build`, which
|
|
625
645
|
* validates it. Not read here.
|
|
@@ -700,6 +720,8 @@ export function publishesContentPages(config) {
|
|
|
700
720
|
* types. The one set the compilers and the
|
|
701
721
|
* link-manifest emitter both read.
|
|
702
722
|
* @property {readonly string[]} skipDirectories
|
|
723
|
+
* @property {boolean} forbidGeneratedArt Whether `lint` refuses an asset
|
|
724
|
+
* record of this package carrying `ai: true`.
|
|
703
725
|
* @property {import("./engine/content-icons.mjs").IconRegistry} icons The
|
|
704
726
|
* fonts this package ships and the names it
|
|
705
727
|
* draws from them; empty when it declares
|
|
@@ -728,6 +750,7 @@ const CONFIG_KEYS = [
|
|
|
728
750
|
"itemBuilders",
|
|
729
751
|
"paths",
|
|
730
752
|
"skipDirectories",
|
|
753
|
+
"forbidGeneratedArt",
|
|
731
754
|
"icons",
|
|
732
755
|
"packs",
|
|
733
756
|
"docs",
|
|
@@ -765,14 +788,25 @@ const PDF_FONT_KEYS = ["serif", "sans", "mono", "path"];
|
|
|
765
788
|
const EMPTY_PDF_FONTS = Object.freeze({ serif: "", sans: "", mono: "", path: "" });
|
|
766
789
|
const DOC_PAGE_KEYS = ["title", "out", "preamble", "frontmatter"];
|
|
767
790
|
const RELATIONSHIP_KINDS = ["systems", "requires", "recommends", "conflicts"];
|
|
768
|
-
|
|
791
|
+
/**
|
|
792
|
+
* Every key a declared relationship may carry.
|
|
793
|
+
*
|
|
794
|
+
* Read by the manifest writer as well as by the configuration check: the keys
|
|
795
|
+
* Foundry's own relationship schema does not name are the build's own, and the
|
|
796
|
+
* published manifest carries none of them.
|
|
797
|
+
*
|
|
798
|
+
* @type {readonly string[]}
|
|
799
|
+
*/
|
|
800
|
+
export const RELATIONSHIP_KEYS = [
|
|
769
801
|
"id",
|
|
770
802
|
"contentPackage",
|
|
771
803
|
"type",
|
|
772
804
|
"manifest",
|
|
773
805
|
"compatibility",
|
|
774
806
|
"itemCatalog",
|
|
807
|
+
"assetArchive",
|
|
775
808
|
"contentIndex",
|
|
809
|
+
"assetReplacement",
|
|
776
810
|
];
|
|
777
811
|
const AUTHOR_KEYS = ["name", "email", "url"];
|
|
778
812
|
const ITEM_BUILDER_KEYS = ["system", "img", "fields"];
|
|
@@ -2198,6 +2232,23 @@ function normalizeRelationships(value) {
|
|
|
2198
2232
|
}
|
|
2199
2233
|
spec.itemCatalog = rel.itemCatalog;
|
|
2200
2234
|
}
|
|
2235
|
+
// Opt-in, sibling to `itemCatalog`: unpack this dependency's
|
|
2236
|
+
// release archive for its asset bytes alone, building no item
|
|
2237
|
+
// catalogue from it. Buys the archive for a package with no
|
|
2238
|
+
// items of its own to extract — an asset-replacement source
|
|
2239
|
+
// ships no Item packs and has no use for `itemCatalog: true`.
|
|
2240
|
+
if (rel.assetArchive !== undefined) {
|
|
2241
|
+
if (typeof rel.assetArchive !== "boolean") {
|
|
2242
|
+
fail(`${at}.assetArchive`, "must be true or false");
|
|
2243
|
+
}
|
|
2244
|
+
if (rel.assetArchive && spec.manifest === undefined) {
|
|
2245
|
+
fail(
|
|
2246
|
+
`${at}.assetArchive`,
|
|
2247
|
+
"needs a `manifest` naming the package to fetch",
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
spec.assetArchive = rel.assetArchive;
|
|
2251
|
+
}
|
|
2201
2252
|
// Opt-out: declares the dependency for the Foundry manifest
|
|
2202
2253
|
// only, so `deps fetch` fetches no content index for it and a
|
|
2203
2254
|
// wikilink into it is refused rather than silently dead. A
|
|
@@ -2216,6 +2267,26 @@ function normalizeRelationships(value) {
|
|
|
2216
2267
|
}
|
|
2217
2268
|
spec.contentIndex = rel.contentIndex;
|
|
2218
2269
|
}
|
|
2270
|
+
// Opt-in: this dependency's asset tree answers this
|
|
2271
|
+
// package's own asset addresses ahead of its local record —
|
|
2272
|
+
// the "rewrite table" `engine/asset-replacement.mjs` reads.
|
|
2273
|
+
// A replacement with no fetched index to check against
|
|
2274
|
+
// resolves nothing, so it cannot pair with
|
|
2275
|
+
// `contentIndex: false`.
|
|
2276
|
+
if (rel.assetReplacement !== undefined) {
|
|
2277
|
+
if (typeof rel.assetReplacement !== "boolean") {
|
|
2278
|
+
fail(`${at}.assetReplacement`, "must be true or false");
|
|
2279
|
+
}
|
|
2280
|
+
if (rel.assetReplacement && rel.contentIndex === false) {
|
|
2281
|
+
fail(
|
|
2282
|
+
`${at}.assetReplacement`,
|
|
2283
|
+
"cannot be true together with `contentIndex: false` — a " +
|
|
2284
|
+
"replacement with no fetched index to check against resolves " +
|
|
2285
|
+
"nothing",
|
|
2286
|
+
);
|
|
2287
|
+
}
|
|
2288
|
+
spec.assetReplacement = rel.assetReplacement;
|
|
2289
|
+
}
|
|
2219
2290
|
return Object.freeze(spec);
|
|
2220
2291
|
}),
|
|
2221
2292
|
);
|
|
@@ -2694,6 +2765,12 @@ export function defineConfig(config) {
|
|
|
2694
2765
|
requireNonEmptyString(name, `skipDirectories[${index}]`),
|
|
2695
2766
|
);
|
|
2696
2767
|
|
|
2768
|
+
const forbidGeneratedArt = optionalBoolean(
|
|
2769
|
+
input.forbidGeneratedArt,
|
|
2770
|
+
"forbidGeneratedArt",
|
|
2771
|
+
false,
|
|
2772
|
+
);
|
|
2773
|
+
|
|
2697
2774
|
// Refused above for a documentation package, so there is nothing to read
|
|
2698
2775
|
// and nothing to derive an asset root or a package-wide system from.
|
|
2699
2776
|
const foundryPackage =
|
|
@@ -2800,6 +2877,7 @@ export function defineConfig(config) {
|
|
|
2800
2877
|
itemTypes,
|
|
2801
2878
|
docEntryTypes,
|
|
2802
2879
|
skipDirectories: Object.freeze(skipDirectories),
|
|
2880
|
+
forbidGeneratedArt,
|
|
2803
2881
|
icons: normalizeIcons(input.icons, rootDir),
|
|
2804
2882
|
packs: Object.freeze(packs),
|
|
2805
2883
|
packDirectories: Object.freeze(packDirectories),
|