@heroiclands/package-build 20.4.0 → 20.6.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 +288 -0
- package/CONTENT.md +213 -20
- package/README.md +19 -1
- package/bin/content-build.mjs +135 -32
- package/bin/package-build.mjs +46 -13
- package/content-config.mjs +345 -101
- package/docs/api.md +1352 -0
- package/docs/commands.md +1609 -0
- package/docs/configuration.md +1432 -0
- package/docs/content-format.md +16 -6
- package/docs/diagnostics.md +356 -0
- package/docs/getting-started.md +813 -0
- package/docs/project-setup.md +469 -0
- package/engine/actor-compiler.mjs +30 -27
- package/engine/address-diff.mjs +45 -41
- package/engine/base-compiler.mjs +6 -0
- package/engine/bundles.mjs +9 -0
- package/engine/content-address.mjs +9 -9
- package/engine/content-index.mjs +44 -23
- package/engine/content-links.mjs +44 -11
- package/engine/content-lint.mjs +44 -10
- package/engine/content-tables.mjs +32 -27
- package/engine/folder-notes.mjs +4 -2
- package/engine/frontmatter-lint.mjs +35 -38
- package/engine/generate.mjs +5 -0
- package/engine/helpers.mjs +86 -32
- package/engine/index.mjs +12 -2
- package/engine/journals.mjs +9 -0
- package/engine/note-claims.mjs +18 -10
- package/engine/note-schemas.mjs +0 -5
- package/engine/note-vocabulary.mjs +32 -31
- package/engine/pack-config.mjs +26 -12
- package/engine/pack-router.mjs +0 -0
- package/engine/pdf-build.mjs +464 -0
- package/engine/pdf-fonts.mjs +420 -0
- package/engine/pdf-render.mjs +876 -0
- package/engine/pdf-toc.mjs +525 -0
- package/engine/scenes.mjs +14 -5
- package/engine/schema-check.mjs +1 -1
- package/engine/site-build.mjs +21 -3
- package/engine/web-wikilinks.mjs +6 -3
- package/engine/wikilinks.mjs +2 -4
- package/hm3/actors.mjs +8 -0
- package/hm3/items.mjs +8 -0
- package/package.json +1 -1
- package/release.mjs +63 -3
- package/sohl/actors.mjs +8 -0
- package/sohl/items.mjs +8 -0
- package/sohl/note-schemas.mjs +5 -5
- package/types/content-config.d.mts +66 -15
- package/types/engine/actor-compiler.d.mts +34 -30
- package/types/engine/address-diff.d.mts +57 -3
- package/types/engine/base-compiler.d.mts +10 -2
- package/types/engine/bundles.d.mts +9 -0
- package/types/engine/content-address.d.mts +9 -9
- package/types/engine/content-index.d.mts +57 -13
- package/types/engine/content-lint.d.mts +6 -4
- package/types/engine/content-tables.d.mts +49 -18
- package/types/engine/frontmatter-lint.d.mts +3 -2
- package/types/engine/helpers.d.mts +105 -31
- package/types/engine/index.d.mts +4 -0
- package/types/engine/journals.d.mts +9 -0
- package/types/engine/note-claims.d.mts +17 -10
- package/types/engine/note-vocabulary.d.mts +23 -196
- package/types/engine/pack-config.d.mts +4 -4
- package/types/engine/pdf-build.d.mts +42 -0
- package/types/engine/pdf-fonts.d.mts +30 -0
- package/types/engine/pdf-render.d.mts +156 -0
- package/types/engine/pdf-toc.d.mts +114 -0
- package/types/engine/scenes.d.mts +10 -1
- package/types/engine/schema-check.d.mts +2 -2
- package/types/engine/site-build.d.mts +34 -6
- package/types/engine/wikilinks.d.mts +2 -3
- package/types/hm3/actors.d.mts +8 -0
- package/types/hm3/items.d.mts +8 -0
- package/types/release.d.mts +15 -4
- package/types/sohl/actors.d.mts +10 -2
- package/types/sohl/items.d.mts +8 -0
|
@@ -0,0 +1,1432 @@
|
|
|
1
|
+
## Configuration: `package-build.config.yaml`, key by key
|
|
2
|
+
|
|
3
|
+
Every repository built by `@heroiclands/package-build` declares itself in one
|
|
4
|
+
file at its root: `package-build.config.yaml` (`.yml` works identically). The
|
|
5
|
+
whole contract is `defineConfig`, exported from `content-config.mjs`: it
|
|
6
|
+
validates the object, fills every optional key with its default, and returns a
|
|
7
|
+
deeply frozen copy. It performs no I/O and knows nothing about any particular
|
|
8
|
+
package's content — the configuration is data, and the compilers read it.
|
|
9
|
+
|
|
10
|
+
The reserved `packageBuild:` section belongs to the packaging half of the
|
|
11
|
+
toolchain and is validated separately, by `resolvePackageBuildConfig` in
|
|
12
|
+
`config.mjs`. `content-config.mjs` checks only that the section is a mapping
|
|
13
|
+
and hands it back frozen; its own key-by-key reference is
|
|
14
|
+
[below](#the-packagebuild-section).
|
|
15
|
+
|
|
16
|
+
This document is a transcription of both validators. Where a rule is stated in
|
|
17
|
+
prose here, the validator states it in code; where a message is quoted, it is
|
|
18
|
+
quoted **verbatim** — search the error text you hit against this page and you
|
|
19
|
+
will find the row that produced it.
|
|
20
|
+
|
|
21
|
+
### Two ways to write it
|
|
22
|
+
|
|
23
|
+
Every configuration ends at the same `defineConfig`, but reaches it by one of
|
|
24
|
+
two routes, and three keys behave differently depending on which:
|
|
25
|
+
|
|
26
|
+
| | `package-build.config.yaml` (data) | `package-build.config.mjs` (code) |
|
|
27
|
+
| ---------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| Loaded by | `engine/pack-config.mjs`, which parses the YAML and derives three keys before calling `defineConfig` | `require()`, which loads the module and reads its default export — already the result of the file calling `defineConfig` itself |
|
|
29
|
+
| `rootDir` | Forbidden — always the directory the file sits in | Authored, typically `import.meta.dirname` |
|
|
30
|
+
| `foundryPackage` | Forbidden — always the adjacent `package.json` `name` | Authored |
|
|
31
|
+
| `itemBuilders` | A **name** (`sohl`, `hm3`) or list of names, resolved against the registries this package ships | The registry object itself — real builder functions, which only code can carry |
|
|
32
|
+
|
|
33
|
+
A file is chosen by its extension: `package-build.config.yaml`, then
|
|
34
|
+
`.yml`, then `.mjs`, resolved by walking up from the working directory. Two of
|
|
35
|
+
them in one directory is a hard error — a repository declares its build in
|
|
36
|
+
exactly one file. The `.mjs` form exists as an escape hatch for a repository
|
|
37
|
+
whose `itemBuilders` registry is its own code, not one of the two this package
|
|
38
|
+
ships; everything else about the two forms is identical, because both are
|
|
39
|
+
validated and frozen by the same `defineConfig`.
|
|
40
|
+
|
|
41
|
+
An `.mjs` configuration imports `defineConfig` from
|
|
42
|
+
`@heroiclands/package-build/content-config`, never from the package root
|
|
43
|
+
barrel — the barrel pulls in the compilers, which read this module, which
|
|
44
|
+
loads the config file, so a config reaching for the barrel closes a cycle
|
|
45
|
+
around its own evaluation.
|
|
46
|
+
|
|
47
|
+
### Quick reference
|
|
48
|
+
|
|
49
|
+
18 top-level keys. `rootDir` is not one of them — a data configuration never
|
|
50
|
+
writes it — and is documented under [Derived values](#derived-values) instead,
|
|
51
|
+
alongside `foundryPackage` and `itemBuilders`, whose data-configuration
|
|
52
|
+
behaviour is also derivation rather than ordinary authoring.
|
|
53
|
+
|
|
54
|
+
| Key | Type | Required | Default |
|
|
55
|
+
| ------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
56
|
+
| [`contentPackage`](#contentpackage) | string | yes | — |
|
|
57
|
+
| [`foundryPackage`](#foundrypackage) | string | yes (`.mjs` only — derived in YAML); refused in a `documentation` package | — |
|
|
58
|
+
| [`packageKind`](#packagekind) | `"systems"` \| `"modules"` \| `"documentation"` | yes | — |
|
|
59
|
+
| [`stats`](#stats) | object | yes; refused in a `documentation` package | — |
|
|
60
|
+
| [`itemBuilders`](#itembuilders) | object, or list of `{system, builders}` (or a name/list of names, in YAML) | no; refused in a `documentation` package | `{}` |
|
|
61
|
+
| [`paths`](#paths) | object | no | see [`paths`](#paths) |
|
|
62
|
+
| [`skipDirectories`](#skipdirectories) | string[] | no | `[]` |
|
|
63
|
+
| [`icons`](#icons) | object, or a path to a file holding one | no | empty registry |
|
|
64
|
+
| [`packs`](#packs) | array | yes, at least one entry, in a `systems` or `modules` package; refused in a `documentation` package | — |
|
|
65
|
+
| [`docs`](#docs) | object | no; refused in a `documentation` package | `{}` |
|
|
66
|
+
| [`site`](#site) | object | no | see [`site`](#site) |
|
|
67
|
+
| [`pdf`](#pdf) | object | no | `null` |
|
|
68
|
+
| [`compatibility`](#compatibility) | object | no; refused in a `documentation` package | `null` |
|
|
69
|
+
| [`relationships`](#relationships) | object | no; refused in a `documentation` package | `{}` |
|
|
70
|
+
| [`systems`](#systems) | object | no; refused in a `documentation` package | `{}` |
|
|
71
|
+
| [`requiresSystem`](#requiressystem) | string | no; refused in a `documentation` package | `null` |
|
|
72
|
+
| [`packageBuild`](#the-packagebuild-section) | object | no | `{}` |
|
|
73
|
+
| [`publish`](#publish) | object | no; **required**, with `site: content`, in a `documentation` package | `{site: "homepage", address: {prefix: ""}}` |
|
|
74
|
+
|
|
75
|
+
Any key outside this list is refused:
|
|
76
|
+
|
|
77
|
+
> `` `<key>` is not a recognized option (expected one of: rootDir, contentPackage, foundryPackage, packageKind, stats, itemBuilders, paths, skipDirectories, icons, packs, docs, site, pdf, compatibility, relationships, systems, requiresSystem, packageBuild, publish). ``
|
|
78
|
+
|
|
79
|
+
(`rootDir` appears in that list because it is a key `defineConfig` itself
|
|
80
|
+
accepts — an `.mjs` configuration authors it directly. A YAML configuration
|
|
81
|
+
never sees this particular message about it, because `engine/pack-config.mjs`
|
|
82
|
+
refuses an authored `rootDir` earlier, with its own message — see
|
|
83
|
+
[Derived values](#derived-values).)
|
|
84
|
+
|
|
85
|
+
### Derived values
|
|
86
|
+
|
|
87
|
+
Five values in the resolved configuration are never transcribed by an author
|
|
88
|
+
— they are computed from where the file sits, from the adjacent
|
|
89
|
+
`package.json`, from the package kind, or from a name naming a table this
|
|
90
|
+
package already ships. Authoring `rootDir`, `foundryPackage` or
|
|
91
|
+
`stats.systemVersion` yourself is an **error**, not an override: a
|
|
92
|
+
transcribed copy is free to drift from what it copied, which is exactly how
|
|
93
|
+
`stats.systemVersion` once sat at a stale version for four releases while
|
|
94
|
+
nothing said so. `assetRoot` has no author-facing spelling to refuse in the
|
|
95
|
+
first place — it is never a key at all, only ever a computed value.
|
|
96
|
+
|
|
97
|
+
#### `rootDir`
|
|
98
|
+
|
|
99
|
+
The configuration's own directory, always. Every configured path in `paths`
|
|
100
|
+
is resolved against it, so the build reads the same tree whatever directory
|
|
101
|
+
it was launched from.
|
|
102
|
+
|
|
103
|
+
- In a **YAML** configuration, writing `rootDir:` is refused by the loader
|
|
104
|
+
before `defineConfig` ever runs:
|
|
105
|
+
|
|
106
|
+
> ``package-build: <config file> declares `rootDir`, which a data configuration may not: it is always the directory the file sits in. An absolute path written here would be one machine's; remove the key.``
|
|
107
|
+
|
|
108
|
+
- In an **`.mjs`** configuration, `rootDir` is an ordinary required key of
|
|
109
|
+
`defineConfig` — a non-empty, absolute string, typically
|
|
110
|
+
`import.meta.dirname`. A relative or missing value is refused:
|
|
111
|
+
|
|
112
|
+
> ``package-build config: `rootDir` must be a non-empty string.``
|
|
113
|
+
|
|
114
|
+
> ``package-build config: `rootDir` must be an absolute path — it is what makes the build independent of the directory it was launched from (pass `import.meta.dirname`).``
|
|
115
|
+
|
|
116
|
+
#### `foundryPackage`
|
|
117
|
+
|
|
118
|
+
The Foundry package id — what appears as `id` in the generated
|
|
119
|
+
`system.json` / `module.json`, and the value `assetRoot` and the packaging
|
|
120
|
+
half's `packageId` are built from. `null` in the resolved configuration of a
|
|
121
|
+
`documentation` package — see [`packageKind`](#packagekind) for the refusal,
|
|
122
|
+
which applies before either loader form gets a chance to derive anything.
|
|
123
|
+
|
|
124
|
+
- In a **YAML** configuration, writing `foundryPackage:` is refused; the
|
|
125
|
+
loader reads it from the adjacent `package.json` `name` instead, verbatim,
|
|
126
|
+
with no normalisation and no legality check (every consumer is an
|
|
127
|
+
unscoped, private npm package, so the case of a scoped name never arises):
|
|
128
|
+
|
|
129
|
+
> ``package-build: <config file> declares `foundryPackage`, which a data configuration may not: it is the `name` of the `package.json` beside it. Remove the key.``
|
|
130
|
+
|
|
131
|
+
If the adjacent `package.json` cannot be read, or declares no `name`:
|
|
132
|
+
|
|
133
|
+
> `package-build: <package.json path> could not be read, and the configuration derives both the Foundry package id and the system version from it.`
|
|
134
|
+
|
|
135
|
+
> ``package-build: <package.json path> declares no `name`, which is what the Foundry package id is derived from.``
|
|
136
|
+
|
|
137
|
+
A `documentation` package derives nothing here: it has no Foundry package
|
|
138
|
+
id, so the loader never reads `package.json` `name` for one.
|
|
139
|
+
|
|
140
|
+
- In an **`.mjs`** configuration, `foundryPackage` is an ordinary required
|
|
141
|
+
key — a non-empty string, checked the same way as every other required
|
|
142
|
+
string field — for a `systems` or `modules` package:
|
|
143
|
+
|
|
144
|
+
> ``package-build config: `foundryPackage` must be a non-empty string.``
|
|
145
|
+
|
|
146
|
+
#### `assetRoot`
|
|
147
|
+
|
|
148
|
+
The served Foundry asset root a compiled document's `img:` is resolved
|
|
149
|
+
against — the one reader of it is `resolveImg`
|
|
150
|
+
(`engine/helpers.mjs`). Never a key an author writes; always computed from
|
|
151
|
+
`packageKind` and `foundryPackage`.
|
|
152
|
+
|
|
153
|
+
- For a `systems` or `modules` package, `<packageKind>/<foundryPackage>/assets`.
|
|
154
|
+
- For a `documentation` package, `null` — Foundry serves no files for a
|
|
155
|
+
package of this kind, and `documentation/null/assets` would be an address
|
|
156
|
+
that resolves nowhere. `resolveImg` refuses rather than rooting a path
|
|
157
|
+
against nothing.
|
|
158
|
+
|
|
159
|
+
#### `stats.systemVersion`
|
|
160
|
+
|
|
161
|
+
The version of the game system the packs were built against, stamped into
|
|
162
|
+
every compiled document's `_stats.systemVersion`. `stats.systemId` is
|
|
163
|
+
derived the same way, from the same block — see [`stats`](#stats) for both.
|
|
164
|
+
Both are `null` in the resolved configuration of a `documentation` package,
|
|
165
|
+
which refuses `stats` outright — see [`stats`](#stats) — and so has neither
|
|
166
|
+
to derive.
|
|
167
|
+
|
|
168
|
+
- **A system package** (`packageKind: systems`) is its own system, so its
|
|
169
|
+
`systemVersion` is its own `package.json` `version`:
|
|
170
|
+
|
|
171
|
+
> ``package-build: <package.json path> declares no `version`, which is what a system's stats.systemVersion is derived from.``
|
|
172
|
+
|
|
173
|
+
- **A module** ships content _for_ another package's system. Its own
|
|
174
|
+
`package.json` version is the module's, not the system's, so deriving from
|
|
175
|
+
it would stamp a version that never existed. The honest source is
|
|
176
|
+
`systems:` (preferred) or `relationships.systems` (the older form) — see
|
|
177
|
+
[`systems`](#systems). Declaring neither, on a module whose packs carry no
|
|
178
|
+
`system:` either, is system-agnostic on purpose and stamps no version at
|
|
179
|
+
all. Declaring one without a usable `compatibility.verified` is refused:
|
|
180
|
+
|
|
181
|
+
> ``package-build: a module's stats.systemVersion is derived from the system it declares a relationship with, and this configuration declares none usable. Add `relationships.systems` naming <system id, or "the system"> with a `compatibility.verified` version. It is not taken from this package's own `package.json` version — that is the module's version, and stamping it would claim a system version that never existed.``
|
|
182
|
+
|
|
183
|
+
- Authoring `stats.systemVersion` directly is refused by `defineConfig`
|
|
184
|
+
itself, in both configuration forms — see [`stats`](#stats) for the exact
|
|
185
|
+
message.
|
|
186
|
+
|
|
187
|
+
- **In an `.mjs` configuration**, this derivation is the author's own
|
|
188
|
+
responsibility: `defineConfig` performs no I/O, so a code configuration
|
|
189
|
+
that wants `stats.systemVersion` populated reads its own `package.json` (or
|
|
190
|
+
its own `relationships.systems`) and supplies the result under the
|
|
191
|
+
`DERIVED_SYSTEM_VERSION` symbol exported by `content-config.mjs`, the same
|
|
192
|
+
channel `engine/pack-config.mjs` uses for a YAML configuration:
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
import { defineConfig, DERIVED_SYSTEM_VERSION } from "@heroiclands/package-build/content-config";
|
|
196
|
+
|
|
197
|
+
export default defineConfig({
|
|
198
|
+
// …
|
|
199
|
+
stats: {
|
|
200
|
+
lastModifiedBy: "acmebuilder00000",
|
|
201
|
+
[DERIVED_SYSTEM_VERSION]: "1.6.3",
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
A symbol, deliberately — a string key would be a second, forgeable spelling
|
|
207
|
+
of the `stats.systemId` / `stats.systemVersion` keys `defineConfig` refuses
|
|
208
|
+
to let an author write, reachable from plain YAML. A symbol cannot be
|
|
209
|
+
written in YAML at all and does not appear in `Object.keys`, so the
|
|
210
|
+
refusal has no back door. Supplying nothing here, and declaring no
|
|
211
|
+
resolvable `systems:` entry either, leaves `stats.systemVersion` `null` —
|
|
212
|
+
`defineConfig` raises nothing for it; a document compiled that way simply
|
|
213
|
+
stamps `_stats.systemVersion: null`.
|
|
214
|
+
|
|
215
|
+
#### `itemBuilders`
|
|
216
|
+
|
|
217
|
+
Unlike the first three, authoring `itemBuilders` is not an error — it is
|
|
218
|
+
**translated**, in the YAML form only:
|
|
219
|
+
|
|
220
|
+
- In a **YAML** configuration, the value is a _name_ — `sohl`, `hm3` — or a
|
|
221
|
+
list of names, each resolved against the registries this package ships
|
|
222
|
+
(`sohl/item-builders.mjs`'s `ITEM_BUILDERS`, `hm3/item-builders.mjs`'s
|
|
223
|
+
`HM3_ITEM_BUILDERS`) before `defineConfig` ever sees the result. A name
|
|
224
|
+
this package does not ship is refused:
|
|
225
|
+
|
|
226
|
+
> ``package-build: <config file> names the `itemBuilders` registry "<name>", which this package does not ship. Known registries: sohl, hm3. To supply your own, declare it in package-build.config.mjs.``
|
|
227
|
+
|
|
228
|
+
A non-string entry — something that is not a registry name at all — is
|
|
229
|
+
refused the same way:
|
|
230
|
+
|
|
231
|
+
> ``package-build: <config file> must name its `itemBuilders` registry as a string — the registry is code, and data cannot carry it. Known registries: sohl, hm3; a registry of your own goes in package-build.config.mjs.``
|
|
232
|
+
|
|
233
|
+
- In an **`.mjs`** configuration, `itemBuilders` is the registry itself —
|
|
234
|
+
real builder functions — since only code can carry a function. See
|
|
235
|
+
[`itemBuilders`](#itembuilders-1) below for the shape both forms end at.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## The 18 keys
|
|
240
|
+
|
|
241
|
+
### `contentPackage`
|
|
242
|
+
|
|
243
|
+
**Type:** string · **Required** · no default.
|
|
244
|
+
|
|
245
|
+
The address namespace every note in this repository is published under —
|
|
246
|
+
the first segment of every canonical address (`contentPackage-system-type-shortcode`,
|
|
247
|
+
so `sohl-none-doc-gear`). Read wherever an address is built or parsed
|
|
248
|
+
(`engine/content-address.mjs` and everything downstream of it).
|
|
249
|
+
|
|
250
|
+
Two rules apply, both enforced here rather than assumed, because an address
|
|
251
|
+
is read by counting hyphen-separated segments:
|
|
252
|
+
|
|
253
|
+
- It must be **lowercase alphanumeric** — the hyphen stays purely a separator.
|
|
254
|
+
A value containing one is refused:
|
|
255
|
+
|
|
256
|
+
> ``package-build config: `contentPackage` is `harn-adventures`, which is not lowercase alphanumeric (^[a-z0-9]+$). It is the first segment of every address this package publishes (`harn-adventures-<system>-<type>-<shortcode>`), and an address is read by counting hyphen-separated segments — so anything outside that here makes those addresses unreadable rather than merely ugly. `harn-adventures` became `harnadventures`.``
|
|
257
|
+
|
|
258
|
+
- It must **not also be a note type** — the two vocabularies are disjoint,
|
|
259
|
+
because a written address may drop its leading segments and
|
|
260
|
+
`contentPackage-shortcode` has to read unambiguously as one or the other:
|
|
261
|
+
|
|
262
|
+
> ``package-build config: `contentPackage` is `macro`, which is also a note type — `macro-<shortcode>` already addresses one. A written address may omit its leading segments, so `macro-<shortcode>` reads as a type and a shortcode and nothing but the two vocabularies being disjoint says which slot the name is filling. Rename the package.``
|
|
263
|
+
|
|
264
|
+
The vocabulary checked against is the union of every note type this
|
|
265
|
+
toolchain knows about — the closed format vocabulary, every consumer's
|
|
266
|
+
configured `itemBuilders` types, `macro`, the map types, and the
|
|
267
|
+
`doc`-prefixed form of each. `sohl` colliding with itself (the system
|
|
268
|
+
package's own id is also a system id, `sohl-sohl-skill-clmb` being the
|
|
269
|
+
honest result) is structural and cannot be avoided; this check exists to
|
|
270
|
+
prevent every other collision, which can be.
|
|
271
|
+
|
|
272
|
+
An empty or non-string value is refused generically:
|
|
273
|
+
|
|
274
|
+
> ``package-build config: `contentPackage` must be a non-empty string.``
|
|
275
|
+
|
|
276
|
+
### `foundryPackage`
|
|
277
|
+
|
|
278
|
+
See [Derived values](#derived-values) — forbidden in a YAML configuration,
|
|
279
|
+
required (a non-empty string) in an `.mjs` one. Refused in either form for a
|
|
280
|
+
`documentation` package, which is not a Foundry package and has no Foundry
|
|
281
|
+
package id:
|
|
282
|
+
|
|
283
|
+
> ``package-build config: `foundryPackage` is refused in a `documentation` package, which is not a Foundry package, so it has no Foundry package id.``
|
|
284
|
+
|
|
285
|
+
### `packageKind`
|
|
286
|
+
|
|
287
|
+
**Type:** `"systems"` \| `"modules"` \| `"documentation"` · **Required** · no default.
|
|
288
|
+
|
|
289
|
+
Which kind of package this repository builds. `systems` and `modules` are the
|
|
290
|
+
two Foundry answers — also the directory Foundry installs the package under,
|
|
291
|
+
and what `assetRoot` and the packaging half's `artifact` (`system` or
|
|
292
|
+
`module`) are derived from. `documentation` is the answer "not a Foundry
|
|
293
|
+
package at all": it publishes a site and a book from its notes, installs into
|
|
294
|
+
no Foundry data directory and compiles no compendium.
|
|
295
|
+
|
|
296
|
+
> ``package-build config: `packageKind` must be one of: systems, modules, documentation.``
|
|
297
|
+
|
|
298
|
+
`compilesFoundryDocuments(config)`, exported from `content-config.mjs`
|
|
299
|
+
alongside `DOCUMENTATION_KIND` and [`publishesContentPages`](#publish), is the
|
|
300
|
+
one question every Foundry-side reader asks — the manifest writer, to decide
|
|
301
|
+
whether there is a package for Foundry to install, and the pack compilers, to
|
|
302
|
+
decide whether there is anything to compile. It returns
|
|
303
|
+
`config.packageKind !== DOCUMENTATION_KIND`.
|
|
304
|
+
|
|
305
|
+
### `stats`
|
|
306
|
+
|
|
307
|
+
**Type:** object · **Required** in a `systems` or `modules` package · refused
|
|
308
|
+
in a `documentation` package, which compiles no documents and so has no
|
|
309
|
+
`_stats` block to stamp:
|
|
310
|
+
|
|
311
|
+
> ``package-build config: `stats` is refused in a `documentation` package, which compiles no documents, so there is no `_stats` block to stamp.``
|
|
312
|
+
|
|
313
|
+
The identity stamped into every compiled document's `_stats` block.
|
|
314
|
+
`coreVersion` is **not** here — that is the top-level `compatibility.minimum`,
|
|
315
|
+
stamped from one place rather than duplicated.
|
|
316
|
+
|
|
317
|
+
| Key | Type | Required | Default |
|
|
318
|
+
| ---------------------- | ------ | ------------- | ------- |
|
|
319
|
+
| `stats.lastModifiedBy` | string | yes | — |
|
|
320
|
+
| `stats.systemId` | — | **forbidden** | derived |
|
|
321
|
+
| `stats.systemVersion` | — | **forbidden** | derived |
|
|
322
|
+
|
|
323
|
+
`stats.lastModifiedBy` is the 16-character id every compiled document is
|
|
324
|
+
stamped as authored by. An empty or missing value is refused generically:
|
|
325
|
+
|
|
326
|
+
> ``package-build config: `stats.lastModifiedBy` must be a non-empty string.``
|
|
327
|
+
|
|
328
|
+
`stats.systemId` and `stats.systemVersion` are **derived and may not be
|
|
329
|
+
authored**, in both configuration forms — `defineConfig` itself refuses them,
|
|
330
|
+
before either loader has a chance to supply its own derivation:
|
|
331
|
+
|
|
332
|
+
> ``package-build config: `stats.systemId` is derived and may not be authored. A system package is its own system; a module takes it from `requiresSystem`, or from `systems:` when it declares exactly one. Remove the key.``
|
|
333
|
+
|
|
334
|
+
> ``package-build config: `stats.systemVersion` is derived and may not be authored. It is the `compatibility.verified` of the system in `systems:`, or a system package's own `package.json` version. Remove the key.``
|
|
335
|
+
|
|
336
|
+
See [`stats.systemVersion`](#statssystemversion) under Derived values for how
|
|
337
|
+
each is actually resolved.
|
|
338
|
+
|
|
339
|
+
Any other key under `stats` is refused:
|
|
340
|
+
|
|
341
|
+
> ``package-build config: `stats.<key>` is not a recognized option (expected one of: lastModifiedBy).``
|
|
342
|
+
|
|
343
|
+
### `itemBuilders`
|
|
344
|
+
|
|
345
|
+
**Type:** object (`{type: builder}`), or a list of `{system, builders}`
|
|
346
|
+
registries — or, in YAML only, a registry **name** (`sohl`, `hm3`) or list of
|
|
347
|
+
names · **Optional** · default `{}`. Refused in a `documentation` package,
|
|
348
|
+
which compiles no items and so has no item-type registry to name:
|
|
349
|
+
|
|
350
|
+
> ``package-build config: `itemBuilders` is refused in a `documentation` package, which compiles no items, so there is no item-type registry to name.``
|
|
351
|
+
|
|
352
|
+
The consumer's item-type registry: each content `type` that compiles into an
|
|
353
|
+
Item, paired with the builder function producing its `system` block. A
|
|
354
|
+
content module that ships no items declares none.
|
|
355
|
+
|
|
356
|
+
**Single-registry form** — what almost every configuration declares. Each
|
|
357
|
+
entry is either a bare builder function, or that function paired with the
|
|
358
|
+
type's default art and the frontmatter fields it declares:
|
|
359
|
+
|
|
360
|
+
```yaml
|
|
361
|
+
itemBuilders: sohl # YAML: a name naming a shipped registry
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
```js
|
|
365
|
+
itemBuilders: { // .mjs: the registry itself
|
|
366
|
+
relic: { system: buildRelic, img: "icons/relic.svg", fields: [...] },
|
|
367
|
+
charm: buildCharm, // a bare builder — every note of the type needs its own `img:`
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
| Key (under `itemBuilders.<type>`) | Type | Required | Default |
|
|
372
|
+
| --------------------------------- | --------------------------- | -------- | --------------------- |
|
|
373
|
+
| `itemBuilders.<type>.system` | function | yes | — |
|
|
374
|
+
| `itemBuilders.<type>.img` | string | no | none (no default art) |
|
|
375
|
+
| `itemBuilders.<type>.fields` | array of field declarations | no | none |
|
|
376
|
+
|
|
377
|
+
An entry that is neither a function nor an object with a `system` builder is
|
|
378
|
+
refused:
|
|
379
|
+
|
|
380
|
+
> ``package-build config: `itemBuilders.<type>` must be a builder function, or an object with a `system` builder.``
|
|
381
|
+
|
|
382
|
+
> ``package-build config: `itemBuilders.<type>.system` must be a function.``
|
|
383
|
+
|
|
384
|
+
Each entry of `itemBuilders.<type>.fields` must be an object declaring a
|
|
385
|
+
`to`:
|
|
386
|
+
|
|
387
|
+
> ``package-build config: `itemBuilders.<type>.fields[<index>]` must be a field declaration object.``
|
|
388
|
+
|
|
389
|
+
> ``package-build config: `itemBuilders.<type>.fields[<index>].to` must be a non-empty string.``
|
|
390
|
+
|
|
391
|
+
Any other key under one entry is refused:
|
|
392
|
+
|
|
393
|
+
> ``package-build config: `itemBuilders.<type>.<key>` is not a recognized option (expected one of: system, img, fields).``
|
|
394
|
+
|
|
395
|
+
**List-of-registries form** — for a repository feeding more than one system
|
|
396
|
+
(`harn-ensemble` ships an HM3 pack, a SoHL pack, and a system-neutral one).
|
|
397
|
+
The accepted type vocabulary is the **union** of the registries' keys; a
|
|
398
|
+
type more than one registry declares keeps a builder per system rather than
|
|
399
|
+
one winning in silence, and is tracked separately as
|
|
400
|
+
`itemTypesBySeveralSystems` in the resolved configuration.
|
|
401
|
+
|
|
402
|
+
```yaml
|
|
403
|
+
itemBuilders: [sohl, hm3] # YAML
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
```js
|
|
407
|
+
itemBuilders: [
|
|
408
|
+
// .mjs
|
|
409
|
+
{ system: "sohl", builders: { skill: buildSohlSkill } },
|
|
410
|
+
{ system: "hm3", builders: { skill: buildHm3Skill } },
|
|
411
|
+
];
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
| Key (under `itemBuilders[]`) | Type | Required | Default |
|
|
415
|
+
| ---------------------------- | ---------------------------------------------- | -------- | ------- |
|
|
416
|
+
| `itemBuilders[].system` | string | yes | — |
|
|
417
|
+
| `itemBuilders[].builders` | object, same shape as the single-registry form | yes | — |
|
|
418
|
+
|
|
419
|
+
Declaring the same system twice is refused:
|
|
420
|
+
|
|
421
|
+
> ``package-build config: `itemBuilders[<index>]` declares a second registry for `<system>` — a system has one item vocabulary, so merge them at their source.``
|
|
422
|
+
|
|
423
|
+
An entry that is not `{system, builders}` is refused:
|
|
424
|
+
|
|
425
|
+
> ``package-build config: `itemBuilders[<index>]` must be `{ system, builders }` — a registry and the system it belongs to.``
|
|
426
|
+
|
|
427
|
+
Any other key on one list entry is refused:
|
|
428
|
+
|
|
429
|
+
> ``package-build config: `itemBuilders[<index>].<key>` is not a recognized option (expected one of: system, builders).``
|
|
430
|
+
|
|
431
|
+
See [`itemBuilders`](#itembuilders) under Derived values for how the YAML
|
|
432
|
+
name form resolves before reaching here.
|
|
433
|
+
|
|
434
|
+
### `paths`
|
|
435
|
+
|
|
436
|
+
**Type:** object · **Optional** · every key defaults to the conventional
|
|
437
|
+
HeroicLands layout, resolved against `rootDir`:
|
|
438
|
+
|
|
439
|
+
| Key | Default | What it is |
|
|
440
|
+
| --------------------- | ---------------------- | ------------------------------------------------------------------------------------------ |
|
|
441
|
+
| `paths.content` | `assets/content` | The content tree root. |
|
|
442
|
+
| `paths.contentIndex` | `build/content-index` | Where `content-index` writes this package's note index. Derived and disposable. |
|
|
443
|
+
| `paths.packJson` | `build/packs-json` | Build-only per-entry JSON intermediate. |
|
|
444
|
+
| `paths.stage` | `build/stage/packs` | Compiled LevelDB packs. |
|
|
445
|
+
| `paths.unpack` | `build/tmp/packs` | Where `unpack` extracts JSON back to. |
|
|
446
|
+
| `paths.foreignCache` | `build/cache/foreign` | Where a dependency declaring `itemCatalog: true` is unpacked. |
|
|
447
|
+
| `paths.metadataCache` | `build/cache/metadata` | Where a dependency's published content index is fetched to, for every declared dependency. |
|
|
448
|
+
|
|
449
|
+
Every configured path must be **relative** — an absolute one would escape
|
|
450
|
+
the repository the config anchors:
|
|
451
|
+
|
|
452
|
+
> ``package-build config: `paths.<key>` must be relative to rootDir, so a consumer's layout travels with its repository.``
|
|
453
|
+
|
|
454
|
+
An empty value is refused generically:
|
|
455
|
+
|
|
456
|
+
> ``package-build config: `paths.<key>` must be a non-empty string.``
|
|
457
|
+
|
|
458
|
+
Any other key is refused:
|
|
459
|
+
|
|
460
|
+
> ``package-build config: `paths.<key>` is not a recognized option (expected one of: content, contentIndex, packJson, stage, unpack, foreignCache, metadataCache).``
|
|
461
|
+
|
|
462
|
+
### `skipDirectories`
|
|
463
|
+
|
|
464
|
+
**Type:** string[] · **Optional** · default `[]`.
|
|
465
|
+
|
|
466
|
+
Directory names the content walk ignores wherever they appear — Obsidian's
|
|
467
|
+
`Templates`, for instance.
|
|
468
|
+
|
|
469
|
+
```yaml
|
|
470
|
+
skipDirectories: [Templates]
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
> ``package-build config: `skipDirectories` must be an array.``
|
|
474
|
+
|
|
475
|
+
> ``package-build config: `skipDirectories[<index>]` must be a non-empty string.``
|
|
476
|
+
|
|
477
|
+
### `icons`
|
|
478
|
+
|
|
479
|
+
**Type:** object (`{families, icons, defaultFamily?}`), or a string naming a
|
|
480
|
+
file holding one, relative to the configuration · **Optional** · default: an
|
|
481
|
+
empty registry (`{families: {}, defaultFamily: undefined, icons: {}}`) —
|
|
482
|
+
nothing is supplied by default, because a registry entry is a promise that a
|
|
483
|
+
glyph will render and only the package shipping the font can keep it.
|
|
484
|
+
|
|
485
|
+
```yaml
|
|
486
|
+
# inline
|
|
487
|
+
icons:
|
|
488
|
+
families:
|
|
489
|
+
fontawesome: { class: fa, styles: [solid, regular, brands], describe: Font Awesome Free }
|
|
490
|
+
icons:
|
|
491
|
+
being: { style: solid, icon: user, label: being }
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
```yaml
|
|
495
|
+
# or a path to a generated file — the shape a real package wants, since the
|
|
496
|
+
# registry is derived from what the interface actually draws
|
|
497
|
+
icons: assets/icon-registry.yaml
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
A bare string that is empty is refused:
|
|
501
|
+
|
|
502
|
+
> ``package-build config: `icons` is empty — name a file, or write the registry inline.``
|
|
503
|
+
|
|
504
|
+
A named file that cannot be read, or does not parse as YAML, or parses to
|
|
505
|
+
nothing, is refused:
|
|
506
|
+
|
|
507
|
+
> ``package-build config: `icons` names <file>, which cannot be read from <rootDir>.``
|
|
508
|
+
|
|
509
|
+
> ``package-build config: `icons` names <file>, which is not readable YAML: <parser error>.``
|
|
510
|
+
|
|
511
|
+
> ``package-build config: `icons` names <file>, which is empty.``
|
|
512
|
+
|
|
513
|
+
A value that is neither a registry nor a file path is refused:
|
|
514
|
+
|
|
515
|
+
> ``package-build config: `icons` must be a registry — `families` and `icons` — or a path to a file holding one.``
|
|
516
|
+
|
|
517
|
+
Within the registry (inline or loaded from file):
|
|
518
|
+
|
|
519
|
+
| Key | Type | Required | Default |
|
|
520
|
+
| --------------------- | -------------------------------- | -------- | ------- |
|
|
521
|
+
| `icons.families` | object (name → family) | no | `{}` |
|
|
522
|
+
| `icons.icons` | object (name → icon entry) | no | `{}` |
|
|
523
|
+
| `icons.defaultFamily` | string, naming a declared family | no | none |
|
|
524
|
+
|
|
525
|
+
> ``package-build config: `icons.families` must be a mapping of name to family.``
|
|
526
|
+
|
|
527
|
+
> ``package-build config: `icons.icons` must be a mapping of name to icon entry.``
|
|
528
|
+
|
|
529
|
+
Every icon name is checked against the charset a note may write between the
|
|
530
|
+
colons — lowercase letters, digits and hyphens, the same charset an address
|
|
531
|
+
segment uses:
|
|
532
|
+
|
|
533
|
+
> ``package-build config: `icons.icons.Bad_Name` is not a name a note can write — `:icon-…:` takes lowercase letters, digits and hyphens, the charset an address segment uses.``
|
|
534
|
+
|
|
535
|
+
`defaultFamily`, if set, must name a family the registry actually declares:
|
|
536
|
+
|
|
537
|
+
> ``package-build config: `icons.defaultFamily` names `<name>`, which is not one of the declared families.``
|
|
538
|
+
|
|
539
|
+
The registry is then checked by `engine/content-icons.mjs`'s
|
|
540
|
+
`checkIconRegistry` — elsewhere in the toolchain its findings are warnings;
|
|
541
|
+
here, because this is the table every note in the package is read against,
|
|
542
|
+
any finding it reports is a refusal, joined into one message:
|
|
543
|
+
|
|
544
|
+
> ``package-build config: `icons` <findings, semicolon-joined>.``
|
|
545
|
+
|
|
546
|
+
### `packs`
|
|
547
|
+
|
|
548
|
+
**Type:** array of pack specs · **Required, at least one entry**, in a
|
|
549
|
+
`systems` or `modules` package. Refused in a `documentation` package, which
|
|
550
|
+
compiles no compendium and so has no packs to declare:
|
|
551
|
+
|
|
552
|
+
> ``package-build config: `packs` is refused in a `documentation` package, which compiles no compendium, so there are no packs to declare.``
|
|
553
|
+
|
|
554
|
+
The compendium packs the build compiles, named exactly as declared in the
|
|
555
|
+
package manifest's `packs` array. Several packs may share a `type` — a
|
|
556
|
+
note's `pack:` frontmatter then names which one it belongs to, and at most
|
|
557
|
+
one pack of a type is marked `default: true` to receive the notes that name
|
|
558
|
+
none.
|
|
559
|
+
|
|
560
|
+
```yaml
|
|
561
|
+
packs:
|
|
562
|
+
- { name: items, type: Item }
|
|
563
|
+
- { name: journals, type: JournalEntry, label: Journals }
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
| Key (under `packs[]`) | Type | Required | Default |
|
|
567
|
+
| --------------------- | --------------------------------------------------------------------- | -------- | --------------------------------------- |
|
|
568
|
+
| `packs[].name` | string | yes | — |
|
|
569
|
+
| `packs[].type` | one of `Actor`, `Adventure`, `Item`, `JournalEntry`, `Macro`, `Scene` | yes | — |
|
|
570
|
+
| `packs[].label` | string | no | `packs[].name` |
|
|
571
|
+
| `packs[].private` | boolean | no | `false` |
|
|
572
|
+
| `packs[].companions` | array, same shape, one level only | no | `[]` |
|
|
573
|
+
| `packs[].mayBeEmpty` | boolean | no | `false` |
|
|
574
|
+
| `packs[].default` | boolean | no | `false` |
|
|
575
|
+
| `packs[].prebuilt` | string (directory) | no | `null` |
|
|
576
|
+
| `packs[].system` | string | no | `null` — falls back to `stats.systemId` |
|
|
577
|
+
|
|
578
|
+
`packs` itself:
|
|
579
|
+
|
|
580
|
+
> ``package-build config: `packs` must be an array.``
|
|
581
|
+
|
|
582
|
+
> ``package-build config: `packs` must declare at least one pack.``
|
|
583
|
+
|
|
584
|
+
Two packs (including companions, anywhere in the tree) may not share a name
|
|
585
|
+
— two packs both named `x` produce:
|
|
586
|
+
|
|
587
|
+
> ``package-build config: `packs` declares the pack `x` more than once.``
|
|
588
|
+
|
|
589
|
+
At most one pack of a given `type` may be marked default — two Item packs
|
|
590
|
+
`a` and `b` both marked `default: true` produce:
|
|
591
|
+
|
|
592
|
+
> ``package-build config: `packs` marks both `a` and `b` as the default Item pack; a note declaring no `pack:` must have one destination.``
|
|
593
|
+
|
|
594
|
+
`packs[].type` is checked against the closed set of document types this
|
|
595
|
+
toolchain compiles:
|
|
596
|
+
|
|
597
|
+
> ``package-build config: `packs[<index>].type` must be one of: Actor, Adventure, Item, JournalEntry, Macro, Scene.``
|
|
598
|
+
|
|
599
|
+
`folders` is retired — a folder is a note (`type: folder`) now, materialised
|
|
600
|
+
by the pack whose documents reference it through `packFolder`:
|
|
601
|
+
|
|
602
|
+
> ``package-build config: `packs[<index>].folders` is retired — delete it. A folder is a note (`type: folder`) now, and a pack materialises the folders its documents reference through `packFolder`, so there is no per-pack hierarchy file to name.``
|
|
603
|
+
|
|
604
|
+
A **companion** — a pack written by its parent pack's own compile pass — may
|
|
605
|
+
not declare `default` (no note is ever routed into one), and may not nest
|
|
606
|
+
further companions of its own:
|
|
607
|
+
|
|
608
|
+
> ``package-build config: `packs[<index>].companions[<index>].default` may not be declared on a companion: a companion is written by another pack's pass, so no note is ever routed into one.``
|
|
609
|
+
|
|
610
|
+
> ``package-build config: `packs[<index>].companions[<index>].companions` may not nest: a companion is written by another pack's pass, and that pass is the only level of indirection the build has.``
|
|
611
|
+
|
|
612
|
+
A **prebuilt** pack (its per-document JSON already exists) has no compile
|
|
613
|
+
pass, so it may not also be a companion, may not declare companions of its
|
|
614
|
+
own, and may not be `default`:
|
|
615
|
+
|
|
616
|
+
> ``package-build config: `packs[<index>].prebuilt` may not be declared on a companion: a companion is written by another pack's pass, and a prebuilt pack has no pass.``
|
|
617
|
+
|
|
618
|
+
> ``package-build config: `packs[<index>].companions` may not accompany `prebuilt`: a companion is written by this pack's pass, and a prebuilt pack has none.``
|
|
619
|
+
|
|
620
|
+
> ``package-build config: `packs[<index>].default` may not accompany `prebuilt`: the default pack receives notes declaring no `pack:`, and no note is routed into a prebuilt one.``
|
|
621
|
+
|
|
622
|
+
`packs[].system` — every document in a pack is stamped `_stats.systemId` and
|
|
623
|
+
`systemVersion`, and Foundry hides a whole package from any world whose
|
|
624
|
+
system `requiresSystem` does not name, so a pack's declared `system:` must
|
|
625
|
+
resolve to something real. A pack `x` naming `system: sohl` in a package
|
|
626
|
+
with no `systems:` block, whose own `foundryPackage` is `acme`, produces:
|
|
627
|
+
|
|
628
|
+
> ``package-build config: `packs.x.system` names `sohl`, which `systems:` does not declare — the `systems:` block is empty or absent, and which is not this package's own system `acme`. Every document in the pack is stamped `_stats.systemId` and `systemVersion` from one of those two, so with neither it would be stamped null. Add `systems:` naming `sohl` with a `compatibility.verified` version.``
|
|
629
|
+
|
|
630
|
+
A pack naming a `system:` other than the one `requiresSystem` names — the
|
|
631
|
+
pack could never be seen, since Foundry hides the whole package from any
|
|
632
|
+
world whose system `requiresSystem` does not name:
|
|
633
|
+
|
|
634
|
+
> ``package-build config: `packs.<name>.system` names `<system>` while `requiresSystem` is `<other>`, so this pack could never be seen — Foundry hides the whole package from any world whose system `requiresSystem` does not name. Drop `requiresSystem`, or correct the pack.``
|
|
635
|
+
|
|
636
|
+
Any other key on a pack entry is refused:
|
|
637
|
+
|
|
638
|
+
> ``package-build config: `packs[<index>].<key>` is not a recognized option (expected one of: name, type, label, private, companions, mayBeEmpty, default, prebuilt, system).``
|
|
639
|
+
|
|
640
|
+
### `docs`
|
|
641
|
+
|
|
642
|
+
**Type:** object · **Optional** · default `{}`. Refused in a `documentation`
|
|
643
|
+
package, which compiles no items and so has no item-field reference pages to
|
|
644
|
+
frame:
|
|
645
|
+
|
|
646
|
+
> ``package-build config: `docs` is refused in a `documentation` package, which compiles no items, so there are no item-field reference pages to frame.``
|
|
647
|
+
|
|
648
|
+
How this repository frames the documentation pages it generates.
|
|
649
|
+
|
|
650
|
+
| Key | Type | Required | Default |
|
|
651
|
+
| ----------------- | ------ | -------- | ------- |
|
|
652
|
+
| `docs.itemFields` | object | no | `{}` |
|
|
653
|
+
|
|
654
|
+
> ``package-build config: `docs` must be a mapping.``
|
|
655
|
+
|
|
656
|
+
> ``package-build config: `docs.<key>` is not a recognized option (expected one of: itemFields).``
|
|
657
|
+
|
|
658
|
+
`docs.itemFields` frames the item-frontmatter reference rendered by
|
|
659
|
+
`content-build docs item-fields` — the tables come from the `itemBuilders`
|
|
660
|
+
registry and are the same wherever rendered; everything here is the
|
|
661
|
+
consumer's: heading, orientation, where the page is filed.
|
|
662
|
+
|
|
663
|
+
| Key | Type | Required | Default |
|
|
664
|
+
| -------------------------- | -------- | -------- | ---------------------------------------------------------------------- |
|
|
665
|
+
| `docs.itemFields.title` | string | no | none — the page's H1 |
|
|
666
|
+
| `docs.itemFields.out` | string | no | none — without it, the page goes to stdout |
|
|
667
|
+
| `docs.itemFields.preamble` | string[] | no | none — markdown lines between the generated banner and the first table |
|
|
668
|
+
|
|
669
|
+
> ``package-build config: `docs.itemFields` must be a mapping.``
|
|
670
|
+
|
|
671
|
+
> ``package-build config: `docs.itemFields.title` must be a non-empty string.``
|
|
672
|
+
|
|
673
|
+
`preamble` is a list of lines, and a blank entry is a meaningful blank line
|
|
674
|
+
— markdown's paragraph separator — so the check is on type, not content:
|
|
675
|
+
|
|
676
|
+
> ``package-build config: `docs.itemFields.preamble` must be a list of lines — a blank entry is a blank line, which is how paragraphs are separated in markdown.``
|
|
677
|
+
|
|
678
|
+
> ``package-build config: `docs.itemFields.preamble[<index>]` must be a string.``
|
|
679
|
+
|
|
680
|
+
Any other key under `docs.itemFields` is refused:
|
|
681
|
+
|
|
682
|
+
> ``package-build config: `docs.itemFields.<key>` is not a recognized option (expected one of: title, out, preamble).``
|
|
683
|
+
|
|
684
|
+
### `site`
|
|
685
|
+
|
|
686
|
+
**Type:** object · **Optional** · every key defaults to nothing published:
|
|
687
|
+
|
|
688
|
+
| Key | Type | Default |
|
|
689
|
+
| ----------------------- | -------- | ------- |
|
|
690
|
+
| `site.out` | string | `""` |
|
|
691
|
+
| `site.base` | string | `""` |
|
|
692
|
+
| `site.packages` | string[] | `[]` |
|
|
693
|
+
| `site.sections` | object | `{}` |
|
|
694
|
+
| `site.readmeSections` | object | `{}` |
|
|
695
|
+
| `site.landing` | object | `null` |
|
|
696
|
+
| `site.trees` | array | `[]` |
|
|
697
|
+
| `site.pass` | string | `""` |
|
|
698
|
+
| `site.passOptions` | object | `{}` |
|
|
699
|
+
| `site.backfillSections` | boolean | `false` |
|
|
700
|
+
|
|
701
|
+
How much of a package reaches the web at all is **not** here — it is
|
|
702
|
+
[`publish.site`](#publish). `site` is framing: where the Hugo tree is
|
|
703
|
+
written, what a section is called, which extra trees are published beside
|
|
704
|
+
the content, which named pass bundle supplies the repository's own body
|
|
705
|
+
rewrites.
|
|
706
|
+
|
|
707
|
+
> ``package-build config: `site` must be a mapping.``
|
|
708
|
+
|
|
709
|
+
> ``package-build config: `site.<key>` is not a recognized option (expected one of: out, base, packages, sections, readmeSections, landing, trees, pass, passOptions, backfillSections).``
|
|
710
|
+
|
|
711
|
+
`site.out` is the output root, resolved by `engine/site-build.mjs`; unset,
|
|
712
|
+
it is refused **at build time** rather than by `defineConfig` (an unset
|
|
713
|
+
value would otherwise resolve to `rootDir` itself, and the tree the build
|
|
714
|
+
wipes on every run would be the working tree):
|
|
715
|
+
|
|
716
|
+
> `site.out is not set, so there is nowhere to write the site. Refusing to continue: the output directory is wiped on every run, and an unset one resolves to the repository root.`
|
|
717
|
+
|
|
718
|
+
`site.packages` names which content packages' notes the site walks, beyond
|
|
719
|
+
this one's own; `site.pass` names a repository's own body-rewrite bundle
|
|
720
|
+
(the one part of the site contract that is code, exactly as `itemBuilders`
|
|
721
|
+
names a registry):
|
|
722
|
+
|
|
723
|
+
> ``package-build config: `site.packages` must be a list.``
|
|
724
|
+
|
|
725
|
+
> ``package-build config: `site.packages[<index>]` must be a non-empty string.``
|
|
726
|
+
|
|
727
|
+
`site.trees` are the extra trees published beside the content, each naming
|
|
728
|
+
where it comes from and which section it publishes into:
|
|
729
|
+
|
|
730
|
+
| Key (under `site.trees[]`) | Type | Required |
|
|
731
|
+
| -------------------------- | ------ | -------- |
|
|
732
|
+
| `site.trees[].from` | string | yes |
|
|
733
|
+
| `site.trees[].section` | string | yes |
|
|
734
|
+
|
|
735
|
+
> ``package-build config: `site.trees` must be a list.``
|
|
736
|
+
|
|
737
|
+
> ``package-build config: `site.trees[<index>]` must be a mapping.``
|
|
738
|
+
|
|
739
|
+
> ``package-build config: `site.trees[<index>].from` must be a non-empty string.``
|
|
740
|
+
|
|
741
|
+
> ``package-build config: `site.trees[<index>].<key>` is not a recognized option (expected one of: from, section).``
|
|
742
|
+
|
|
743
|
+
`site.sections` (and `site.readmeSections`, the same shape) is a closed
|
|
744
|
+
vocabulary — a section's _only_ place to speak, since it exists solely as
|
|
745
|
+
the generated `_index.md` this build writes for it:
|
|
746
|
+
|
|
747
|
+
| Key (under `site.sections.<name>`) | Type | Required | Default |
|
|
748
|
+
| ---------------------------------- | -------------------------- | -------- | ------- |
|
|
749
|
+
| `site.sections.<name>.title` | string | yes | — |
|
|
750
|
+
| `site.sections.<name>.banner` | string | no | none |
|
|
751
|
+
| `site.sections.<name>.description` | string | no | none |
|
|
752
|
+
| `site.sections.<name>.listType` | string, an address segment | no | none |
|
|
753
|
+
| `site.sections.<name>.listSubType` | string, an address segment | no | none |
|
|
754
|
+
|
|
755
|
+
> ``package-build config: `site.sections.<name>` must be a mapping.``
|
|
756
|
+
|
|
757
|
+
> ``package-build config: `site.sections.<name>.title` must be a non-empty string.``
|
|
758
|
+
|
|
759
|
+
`listType` / `listSubType` say what the section **lists** — a content type
|
|
760
|
+
and subType, which are address segments and therefore checked against
|
|
761
|
+
`^[a-z0-9]+$`, deliberately distinct from the section's own name (a URL
|
|
762
|
+
this site chose; `user-guide` is the section, `userguide` the subType):
|
|
763
|
+
|
|
764
|
+
> ``package-build config: `site.sections.<name>.listType` is `Not Ok`, which is not lowercase alphanumeric. It names a content type or subType, and those are address segments (^[a-z0-9]+$) — not the section's own name, which is a URL this site chose and need not match (`user-guide` is the section, `userguide` the subType). A value no page carries selects nothing and leaves the landing empty.``
|
|
765
|
+
|
|
766
|
+
`listSubType` alone, without `listType`, names no query — a subType only
|
|
767
|
+
distinguishes _within_ a type:
|
|
768
|
+
|
|
769
|
+
> ``package-build config: `site.sections.<name>.listSubType` is declared without a `listType`. A subType tells pages apart only within a type — `rules`, `userguide` and `reference` are all `doc` — so on its own it names no query for a layout to run.``
|
|
770
|
+
|
|
771
|
+
Any other key on a section entry is refused:
|
|
772
|
+
|
|
773
|
+
> ``package-build config: `site.sections.<name>.<key>` is not a recognized option (expected one of: title, banner, description, listType, listSubType).``
|
|
774
|
+
|
|
775
|
+
`site.landing` is different from a section entry — it is the mount's own
|
|
776
|
+
landing page frontmatter, passed through verbatim to Hugo rather than
|
|
777
|
+
validated field by field, since its vocabulary is the theme's and not this
|
|
778
|
+
package's:
|
|
779
|
+
|
|
780
|
+
> ``package-build config: `site.landing` must be a mapping.``
|
|
781
|
+
|
|
782
|
+
`site.passOptions` and `site.backfillSections` have no further shape of
|
|
783
|
+
their own — `passOptions` is passed to the resolved `site.pass` bundle
|
|
784
|
+
unchanged, and `backfillSections` is a plain boolean:
|
|
785
|
+
|
|
786
|
+
> ``package-build config: `site.backfillSections` must be a boolean.``
|
|
787
|
+
|
|
788
|
+
### `pdf`
|
|
789
|
+
|
|
790
|
+
**Type:** object · **Optional** · default `null` (no book is built).
|
|
791
|
+
|
|
792
|
+
The content tree published as a book — a **selection**, not a rendering of
|
|
793
|
+
everything: `pdf.document` names the tree that says which notes the volume
|
|
794
|
+
carries and in what order, parsed by `engine/pdf-toc.mjs`'s
|
|
795
|
+
`parseDocumentTree` and not validated here. Whether a book is built at all
|
|
796
|
+
is [`publish.site`](#publish), the same switch that gates the website —
|
|
797
|
+
`content` builds one, `homepage` does not, so a package cannot end up with
|
|
798
|
+
two switches that disagree about whether it publishes its content tree.
|
|
799
|
+
|
|
800
|
+
```yaml
|
|
801
|
+
pdf:
|
|
802
|
+
title: The Hârn Ensemble
|
|
803
|
+
document: book.yaml
|
|
804
|
+
fonts:
|
|
805
|
+
serif: Libertinus Serif
|
|
806
|
+
mono: DejaVu Sans Mono
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
| Key | Type | Required | Default |
|
|
810
|
+
| --------------- | --------------------------- | -------- | ---------------------- |
|
|
811
|
+
| `pdf.title` | string | yes | — |
|
|
812
|
+
| `pdf.document` | string (path) | yes | — |
|
|
813
|
+
| `pdf.subtitle` | string | no | `""` |
|
|
814
|
+
| `pdf.out` | string | no | `""` |
|
|
815
|
+
| `pdf.front` | string[] (markdown files) | no | `[]` |
|
|
816
|
+
| `pdf.fonts` | object | no | all empty |
|
|
817
|
+
| `pdf.iconFonts` | object (family → font file) | no | `{}` |
|
|
818
|
+
| `pdf.binary` | string | no | `""` — found on `PATH` |
|
|
819
|
+
|
|
820
|
+
`pdf.title` and `pdf.document` are required **together** — a document with
|
|
821
|
+
no title produces a file whose name and cover say nothing about what a
|
|
822
|
+
reader downloaded, and a title with no document has nothing to print:
|
|
823
|
+
|
|
824
|
+
> ``package-build config: `pdf.title` must be a non-empty string.``
|
|
825
|
+
|
|
826
|
+
> ``package-build config: `pdf.document` must be a non-empty string.``
|
|
827
|
+
|
|
828
|
+
> ``package-build config: `pdf` must be a mapping.``
|
|
829
|
+
|
|
830
|
+
> ``package-build config: `pdf.front` must be a list of markdown files.``
|
|
831
|
+
|
|
832
|
+
`pdf.fonts` names font **families**, not files — the renderer asks the font
|
|
833
|
+
stack for a family by name:
|
|
834
|
+
|
|
835
|
+
| Key (under `pdf.fonts`) | Type | Required | Default |
|
|
836
|
+
| ----------------------- | ------------- | -------- | ---------------------------------------------------------------- |
|
|
837
|
+
| `pdf.fonts.serif` | string | no | `""` |
|
|
838
|
+
| `pdf.fonts.sans` | string | no | `""` |
|
|
839
|
+
| `pdf.fonts.mono` | string | no | `""` |
|
|
840
|
+
| `pdf.fonts.path` | string (path) | no | `""` — where the renderer may look beyond the system's own fonts |
|
|
841
|
+
|
|
842
|
+
> ``package-build config: `pdf.fonts` must be a mapping.``
|
|
843
|
+
|
|
844
|
+
> ``package-build config: `pdf.fonts.<key>` is not a recognized option (expected one of: serif, sans, mono, path).``
|
|
845
|
+
|
|
846
|
+
`pdf.iconFonts` maps an icon family to the **font file** carrying its
|
|
847
|
+
glyphs — a file rather than a codepoint, since the font's own tables are
|
|
848
|
+
the only trustworthy source of which glyph a name resolves to:
|
|
849
|
+
|
|
850
|
+
> ``package-build config: `pdf.iconFonts` must be a mapping of icon family to font file.``
|
|
851
|
+
|
|
852
|
+
`pdf.binary` names the Typst binary when it is not simply `typst` on
|
|
853
|
+
`PATH` — bundling a native compiler would put a platform-specific artefact
|
|
854
|
+
in the dependency tree of every repository, most of which do not build
|
|
855
|
+
books.
|
|
856
|
+
|
|
857
|
+
Any other key on `pdf` is refused:
|
|
858
|
+
|
|
859
|
+
> ``package-build config: `pdf.<key>` is not a recognized option (expected one of: title, subtitle, document, out, front, fonts, iconFonts, binary).``
|
|
860
|
+
|
|
861
|
+
### `compatibility`
|
|
862
|
+
|
|
863
|
+
**Type:** object · **Optional** · default `null`. Refused in a
|
|
864
|
+
`documentation` package, which installs into no Foundry data directory and so
|
|
865
|
+
has no Foundry core range to support:
|
|
866
|
+
|
|
867
|
+
> ``package-build config: `compatibility` is refused in a `documentation` package, which installs into no Foundry data directory, so there is no Foundry core range to support.``
|
|
868
|
+
|
|
869
|
+
The **Foundry core** version range this package supports — not to be
|
|
870
|
+
confused with `relationships.systems[].compatibility` or
|
|
871
|
+
`systems.<id>.compatibility`, which are a _game system's_ range. Same key
|
|
872
|
+
name, different subject. `compatibility.minimum` is stamped into every
|
|
873
|
+
compiled document as `_stats.coreVersion`, so a document never claims to
|
|
874
|
+
predate the migrations that would rewrite it; `compatibility.verified`
|
|
875
|
+
names the newest build the full suite has actually passed, never an
|
|
876
|
+
aspiration.
|
|
877
|
+
|
|
878
|
+
```yaml
|
|
879
|
+
compatibility: { minimum: "14.359", verified: "14.364" }
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
| Key | Type | Required | Default |
|
|
883
|
+
| ------------------------ | ------ | -------------------------------------- | ------- |
|
|
884
|
+
| `compatibility.minimum` | string | yes, once `compatibility:` is declared | — |
|
|
885
|
+
| `compatibility.verified` | string | no | none |
|
|
886
|
+
|
|
887
|
+
> ``package-build config: `compatibility` must be a mapping.``
|
|
888
|
+
|
|
889
|
+
> ``package-build config: `compatibility.minimum` must be a non-empty string.``
|
|
890
|
+
|
|
891
|
+
> ``package-build config: `compatibility.<key>` is not a recognized option (expected one of: minimum, verified).``
|
|
892
|
+
|
|
893
|
+
`compatibility` itself is optional at this validation layer — absent for a
|
|
894
|
+
content-only consumer, which has none to invent — but a repository that
|
|
895
|
+
compiles any pack needs one in practice: reading the floor throws, at
|
|
896
|
+
compile time rather than at configuration time, without it:
|
|
897
|
+
|
|
898
|
+
> ``package-build: the configuration declares no `compatibility.minimum`, so compiled documents have no honest core version to stamp. Declare it at the top level of package-build.config.yaml.``
|
|
899
|
+
|
|
900
|
+
### `relationships`
|
|
901
|
+
|
|
902
|
+
**Type:** object · **Optional** · default `{}`. Refused in a `documentation`
|
|
903
|
+
package, which is not a Foundry package and so stands in no relationship to
|
|
904
|
+
one:
|
|
905
|
+
|
|
906
|
+
> ``package-build config: `relationships` is refused in a `documentation` package, which is not a Foundry package, so it stands in no relationship to one.``
|
|
907
|
+
|
|
908
|
+
What this package declares about other packages, in Foundry's own shape.
|
|
909
|
+
Passed through to the shipped manifest, and read here for one derivation: a
|
|
910
|
+
module's `_stats.systemVersion` can come from the `verified` field of the
|
|
911
|
+
system relationship it declares — see [`stats.systemVersion`](#statssystemversion).
|
|
912
|
+
|
|
913
|
+
| Key | Type | Required |
|
|
914
|
+
| -------------------------- | ----- | -------- |
|
|
915
|
+
| `relationships.systems` | array | no |
|
|
916
|
+
| `relationships.requires` | array | no |
|
|
917
|
+
| `relationships.recommends` | array | no |
|
|
918
|
+
| `relationships.conflicts` | array | no |
|
|
919
|
+
|
|
920
|
+
> ``package-build config: `relationships` must be a mapping.``
|
|
921
|
+
|
|
922
|
+
> ``package-build config: `relationships.<kind>` must be a list.``
|
|
923
|
+
|
|
924
|
+
> ``package-build config: `relationships.<kind>` is not a recognized option (expected one of: systems, requires, recommends, conflicts).``
|
|
925
|
+
|
|
926
|
+
Each entry, in any of the four lists:
|
|
927
|
+
|
|
928
|
+
| Key (under `relationships.<kind>[]`) | Type | Required | Default |
|
|
929
|
+
| --------------------------------------- | ------------------------------- | -------- | ------- |
|
|
930
|
+
| `relationships.systems[].id` | string | yes | — |
|
|
931
|
+
| `relationships.systems[].type` | string | no | none |
|
|
932
|
+
| `relationships.systems[].manifest` | string | no | none |
|
|
933
|
+
| `relationships.systems[].compatibility` | object, `{minimum?, verified?}` | no | none |
|
|
934
|
+
| `relationships.systems[].itemCatalog` | boolean | no | `false` |
|
|
935
|
+
|
|
936
|
+
(the same four keys apply under `requires[]`, `recommends[]` and
|
|
937
|
+
`conflicts[]`.)
|
|
938
|
+
|
|
939
|
+
> ``package-build config: `relationships.<kind>[<index>]` must be a mapping.``
|
|
940
|
+
|
|
941
|
+
> ``package-build config: `relationships.<kind>[<index>].id` must be a non-empty string.``
|
|
942
|
+
|
|
943
|
+
> ``package-build config: `relationships.<kind>[<index>].<key>` is not a recognized option (expected one of: id, type, manifest, compatibility, itemCatalog).``
|
|
944
|
+
|
|
945
|
+
`itemCatalog` opts into extracting the named package's Item packs so the
|
|
946
|
+
actors pass can resolve embedded items this repository does not hold — off
|
|
947
|
+
by default, since depending on a package is not the same as needing its
|
|
948
|
+
item catalogue at build time. It requires a `manifest`:
|
|
949
|
+
|
|
950
|
+
> ``package-build config: `relationships.<kind>[<index>].itemCatalog` must be true or false.``
|
|
951
|
+
|
|
952
|
+
> ``package-build config: `relationships.<kind>[<index>].itemCatalog` needs a `manifest` naming the package to fetch.``
|
|
953
|
+
|
|
954
|
+
### `systems`
|
|
955
|
+
|
|
956
|
+
**Type:** object (`{id: spec}`) · **Optional** · default `{}`. Refused in a
|
|
957
|
+
`documentation` package, which compiles no documents and so ships content for
|
|
958
|
+
no game system:
|
|
959
|
+
|
|
960
|
+
> ``package-build config: `systems` is refused in a `documentation` package, which compiles no documents, so it ships content for no game system.``
|
|
961
|
+
|
|
962
|
+
The systems this package can stamp content against — **declaration only**,
|
|
963
|
+
not a restriction. Declaring a system here does not narrow which worlds can
|
|
964
|
+
load the package; only [`requiresSystem`](#requiressystem) does that. A
|
|
965
|
+
repository shipping content for two systems declares both here; a system
|
|
966
|
+
package needs no entry, since it is its own system by construction.
|
|
967
|
+
|
|
968
|
+
```yaml
|
|
969
|
+
systems:
|
|
970
|
+
sohl:
|
|
971
|
+
compatibility: { verified: "1.6.3" }
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
| Key (under `systems.<id>`) | Type | Required | Default |
|
|
975
|
+
| ------------------------------------- | ------ | -------- | ------- |
|
|
976
|
+
| `systems.<id>.manifest` | string | no | `null` |
|
|
977
|
+
| `systems.<id>.compatibility` | object | yes | — |
|
|
978
|
+
| `systems.<id>.compatibility.minimum` | string | no | `null` |
|
|
979
|
+
| `systems.<id>.compatibility.verified` | string | yes | — |
|
|
980
|
+
|
|
981
|
+
`compatibility.verified` is required here — unlike the top-level
|
|
982
|
+
`compatibility` block, where `minimum` is the required half — because this
|
|
983
|
+
is the value a pack actually **stamps**; a declaration that cannot answer
|
|
984
|
+
"which version was this built against" is the gap `systems:` exists to
|
|
985
|
+
close.
|
|
986
|
+
|
|
987
|
+
> ``package-build config: `systems` must be a mapping of id to spec.``
|
|
988
|
+
|
|
989
|
+
> ``package-build config: `systems` declares an empty system id.``
|
|
990
|
+
|
|
991
|
+
> ``package-build config: `systems.<id>` must be a mapping.``
|
|
992
|
+
|
|
993
|
+
> ``package-build config: `systems.<id>.compatibility` must be a mapping.``
|
|
994
|
+
|
|
995
|
+
> ``package-build config: `systems.<id>.compatibility.verified` must be a non-empty string.``
|
|
996
|
+
|
|
997
|
+
> ``package-build config: `systems.<id>.<key>` is not a recognized option (expected one of: manifest, compatibility).``
|
|
998
|
+
|
|
999
|
+
> ``package-build config: `systems.<id>.compatibility.<key>` is not a recognized option (expected one of: minimum, verified).``
|
|
1000
|
+
|
|
1001
|
+
### `requiresSystem`
|
|
1002
|
+
|
|
1003
|
+
**Type:** string · **Optional** · default `null`. Refused in a
|
|
1004
|
+
`documentation` package, which compiles no documents and so has no game
|
|
1005
|
+
system to gate its packs on:
|
|
1006
|
+
|
|
1007
|
+
> ``package-build config: `requiresSystem` is refused in a `documentation` package, which compiles no documents, so there is no game system to gate its packs on.``
|
|
1008
|
+
|
|
1009
|
+
The one system this package refuses to load without — the **gate** half of
|
|
1010
|
+
the systems split. Naming one here emits `relationships.systems` for it,
|
|
1011
|
+
which Foundry's `supportsSystem` reads, making the package unavailable
|
|
1012
|
+
under any other system. Omitted, no relationship is emitted and each pack
|
|
1013
|
+
stamps whatever its own `system:` names.
|
|
1014
|
+
|
|
1015
|
+
It must name a system `systems:` actually declares. With no `systems:`
|
|
1016
|
+
block at all:
|
|
1017
|
+
|
|
1018
|
+
> ``package-build config: `requiresSystem` names `sohl`, which `systems:` does not declare — the `systems:` block is empty or absent.``
|
|
1019
|
+
|
|
1020
|
+
With one, naming what it does declare instead:
|
|
1021
|
+
|
|
1022
|
+
> ``package-build config: `requiresSystem` names `<name>`, which `systems:` does not declare. Declared: <list>.``
|
|
1023
|
+
|
|
1024
|
+
> ``package-build config: `requiresSystem` must be a non-empty string.``
|
|
1025
|
+
|
|
1026
|
+
### `packageBuild`
|
|
1027
|
+
|
|
1028
|
+
Reserved for `@heroiclands/package-build`'s own packaging half — see
|
|
1029
|
+
[The `packageBuild` section](#the-packagebuild-section) below for its full
|
|
1030
|
+
key-by-key reference. `content-config.mjs` checks only that the value is a
|
|
1031
|
+
mapping:
|
|
1032
|
+
|
|
1033
|
+
> ``package-build config: `packageBuild` must be a mapping — it is the section @heroiclands/package-build reads, and that package validates what is inside it.``
|
|
1034
|
+
|
|
1035
|
+
### `publish`
|
|
1036
|
+
|
|
1037
|
+
**Type:** object · **Optional** for a `systems` or `modules` package, default
|
|
1038
|
+
`{site: "homepage", address: {prefix: ""}}`. **Required** for a
|
|
1039
|
+
`documentation` package, with `site: content` — publishing the content tree is
|
|
1040
|
+
the whole of what that kind does:
|
|
1041
|
+
|
|
1042
|
+
> ``package-build config: `publish` is required in a `documentation` package: publishing the content tree is the whole of what it does. Write `publish: {site: content}`.``
|
|
1043
|
+
|
|
1044
|
+
> ``package-build config: `publish.site` must be `content` in a `documentation` package — `homepage` fences the content surfaces off, and a package that compiles nothing and publishes nothing from its tree would produce a single authored page and no book.``
|
|
1045
|
+
|
|
1046
|
+
Publishing switches — how much of this package reaches the web, and where
|
|
1047
|
+
its content tree's addresses mount inside the package.
|
|
1048
|
+
|
|
1049
|
+
| Key | Type | Required | Default |
|
|
1050
|
+
| ------------------------ | --------------------------- | -------- | -------------- |
|
|
1051
|
+
| `publish.site` | `"homepage"` \| `"content"` | no | `"homepage"` |
|
|
1052
|
+
| `publish.address` | object | no | `{prefix: ""}` |
|
|
1053
|
+
| `publish.address.prefix` | string | no | `""` |
|
|
1054
|
+
|
|
1055
|
+
> ``package-build config: `publish` must be an object.``
|
|
1056
|
+
|
|
1057
|
+
> ``package-build config: `publish.<key>` is not a recognized option (expected one of: site, address).``
|
|
1058
|
+
|
|
1059
|
+
Every HeroicLands package publishes at least an authored homepage at
|
|
1060
|
+
`https://www.heroiclands.org/<contentPackage>/` — there is no value meaning
|
|
1061
|
+
_no web presence at all_. `homepage` is the floor: the authored homepage
|
|
1062
|
+
and nothing else, no content-tree walk, no `site.sections` / `site.trees` /
|
|
1063
|
+
`site.landing` output. `content` is the homepage plus every page the
|
|
1064
|
+
content tree publishes. `publishesContentPages(config)`, exported from
|
|
1065
|
+
`content-config.mjs` alongside [`compilesFoundryDocuments`](#packagekind),
|
|
1066
|
+
answers the one question every reader of the mode actually asks — the site
|
|
1067
|
+
build, to decide whether to walk the tree at all, and the content index, to
|
|
1068
|
+
decide whether an entry carries a web `path`. It returns
|
|
1069
|
+
`config.publish.site === "content"`.
|
|
1070
|
+
|
|
1071
|
+
This was a boolean before `5.0.0`, and both spellings are refused rather
|
|
1072
|
+
than silently mapped, because a value reinterpreted reads to its author as
|
|
1073
|
+
though it still means what it said:
|
|
1074
|
+
|
|
1075
|
+
> ``package-build config: `publish.site` is no longer a boolean — write `site: content`. Every package publishes an authored homepage at /<contentPackage>/, so no value means "no web presence": `homepage` publishes that page and nothing else, and `content` publishes it plus every page the content tree compiles to.``
|
|
1076
|
+
|
|
1077
|
+
> ``package-build config: `publish.site` must be one of homepage, content (got "public").``
|
|
1078
|
+
|
|
1079
|
+
`publish.address.prefix` is where the content tree mounts _inside the
|
|
1080
|
+
package_ — `"kb/"` for a repository whose knowledgebase is one surface
|
|
1081
|
+
among several, `""` for one whose site is nothing but its content. It must
|
|
1082
|
+
end in a slash when set (a missing one would silently fuse the prefix to
|
|
1083
|
+
the first section) and must not begin with one (which would make the
|
|
1084
|
+
recorded address package-absolute):
|
|
1085
|
+
|
|
1086
|
+
> ``package-build config: `publish.address` must be an object.``
|
|
1087
|
+
|
|
1088
|
+
> ``package-build config: `publish.address.prefix` must end in a slash when it is set.``
|
|
1089
|
+
|
|
1090
|
+
> ``package-build config: `publish.address.prefix` must not begin with a slash.``
|
|
1091
|
+
|
|
1092
|
+
`publish.address.landing` is **retired** — it named which note addressed a
|
|
1093
|
+
whole section rather than a page within one, and there are no sections to
|
|
1094
|
+
address:
|
|
1095
|
+
|
|
1096
|
+
> ``package-build config: `publish.address.landing` is a retired option — delete it. It named which note addressed a whole section rather than a page within one, and there are no sections to address: a section is a Hugo content directory the note format does not carry, so no note lands one and every page is addressed `<type>-<shortcode>`. Nothing replaces it.``
|
|
1097
|
+
|
|
1098
|
+
Any other key under `publish.address` is refused:
|
|
1099
|
+
|
|
1100
|
+
> ``package-build config: `publish.address.<key>` is not a recognized option (expected one of: prefix).``
|
|
1101
|
+
|
|
1102
|
+
---
|
|
1103
|
+
|
|
1104
|
+
## The `packageBuild` section
|
|
1105
|
+
|
|
1106
|
+
Validated by `resolvePackageBuildConfig` in `config.mjs`, not by
|
|
1107
|
+
`content-config.mjs`. The two halves split by **input** — the content half
|
|
1108
|
+
reads the content tree, this one reads `lang/`, `styles/`, `src/`, the
|
|
1109
|
+
assets and the manifest template — and neither validates the other's keys.
|
|
1110
|
+
`packageBuild` is an ordinary section of the one configuration file; the
|
|
1111
|
+
split exists only to stop one key being checked twice against two
|
|
1112
|
+
disagreeing ideas of what it means.
|
|
1113
|
+
|
|
1114
|
+
```yaml
|
|
1115
|
+
packageBuild:
|
|
1116
|
+
assets:
|
|
1117
|
+
- { from: lang, to: lang }
|
|
1118
|
+
- { from: assets/icons, to: assets/icons }
|
|
1119
|
+
assetTransform: ./utils/svg-theme.mjs
|
|
1120
|
+
stageDir: build/stage
|
|
1121
|
+
clean:
|
|
1122
|
+
extra: [site/content, site/public]
|
|
1123
|
+
lang:
|
|
1124
|
+
sources: lang/*.json
|
|
1125
|
+
deploy:
|
|
1126
|
+
envPrefix: SOHL
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
| Key | Type | Required | Default |
|
|
1130
|
+
| ------------------------------------------------------------------------------------------ | ------------------------------------------- | -------- | --------------------------------- |
|
|
1131
|
+
| [`packageBuild.stageDir`](#packagebuildstagedir-and-packagebuildassets) | string | no | `build/stage` |
|
|
1132
|
+
| [`packageBuild.assets`](#packagebuildstagedir-and-packagebuildassets) | array | no | `[]` |
|
|
1133
|
+
| [`packageBuild.assetTransform`](#packagebuildassettransform-and-packagebuildmanifestflags) | string (path to a module) | no | `null` |
|
|
1134
|
+
| [`packageBuild.manifest`](#packagebuildmanifest) | object, pass-through | no | `{}` |
|
|
1135
|
+
| [`packageBuild.manifestFlags`](#packagebuildassettransform-and-packagebuildmanifestflags) | string (path to a module) | no | `null` |
|
|
1136
|
+
| [`packageBuild.schema`](#packagebuildschema) | object (`{documentType: {from, registry}}`) | no | `[]` |
|
|
1137
|
+
| [`packageBuild.clean`](#packagebuildclean) | object | no | `{extra: []}` |
|
|
1138
|
+
| [`packageBuild.lang`](#packagebuildlang) | object | no | see below |
|
|
1139
|
+
| [`packageBuild.deploy`](#packagebuilddeploy) | object | no | `{envPrefix: "SOHL"}` |
|
|
1140
|
+
| [`packageBuild.release`](#packagebuildrelease) | object | no | `{artifact: <from packageKind>}` |
|
|
1141
|
+
| [`packageBuild.bundle`](#packagebuildbundle) | object | no | `{entry: "<foundryPackage>.mjs"}` |
|
|
1142
|
+
| [`packageBuild.container`](#packagebuildcontainer) | object | no | see below |
|
|
1143
|
+
| [`packageBuild.e2e`](#packagebuilde2e) | object | no | see below |
|
|
1144
|
+
|
|
1145
|
+
> ``package-build config: `packageBuild.<key>` is not a recognised key (expected one of: stageDir, assets, assetTransform, manifest, manifestFlags, schema, clean, lang, deploy, release, bundle, container, e2e).``
|
|
1146
|
+
|
|
1147
|
+
### `packageBuild.stageDir` and `packageBuild.assets`
|
|
1148
|
+
|
|
1149
|
+
`stageDir` is where the package is assembled before it is zipped or
|
|
1150
|
+
deployed — every asset destination is relative to it, so a repository's
|
|
1151
|
+
table says `lang`, not `build/stage/lang`.
|
|
1152
|
+
|
|
1153
|
+
`assets` is the table of staging copies: source path in the repository,
|
|
1154
|
+
destination under the staged package root.
|
|
1155
|
+
|
|
1156
|
+
| Key | Type | Required |
|
|
1157
|
+
| ---------------------------- | ------ | -------- |
|
|
1158
|
+
| `packageBuild.assets[].from` | string | yes |
|
|
1159
|
+
| `packageBuild.assets[].to` | string | yes |
|
|
1160
|
+
|
|
1161
|
+
> ``package-build config: `packageBuild.stageDir` must be a non-empty string.``
|
|
1162
|
+
|
|
1163
|
+
> ``package-build config: `packageBuild.assets` must be a list.``
|
|
1164
|
+
|
|
1165
|
+
> ``package-build config: `packageBuild.assets[<index>]` must be a mapping.``
|
|
1166
|
+
|
|
1167
|
+
> ``package-build config: `packageBuild.assets[<index>].from` must be a non-empty string.``
|
|
1168
|
+
|
|
1169
|
+
> ``package-build config: `packageBuild.assets[<index>].<key>` is not a recognised key (expected one of: from, to).``
|
|
1170
|
+
|
|
1171
|
+
### `packageBuild.assetTransform` and `packageBuild.manifestFlags`
|
|
1172
|
+
|
|
1173
|
+
Both name a module, resolved against `rootDir`: `assetTransform` exports a
|
|
1174
|
+
`transform` a repository needs beyond verbatim asset copying, and
|
|
1175
|
+
`manifestFlags` exports a `flags` function for namespaced manifest flags a
|
|
1176
|
+
repository has to compute. Neither declares anything, both default to
|
|
1177
|
+
`null`:
|
|
1178
|
+
|
|
1179
|
+
> ``package-build config: `packageBuild.assetTransform` must be a non-empty string.``
|
|
1180
|
+
|
|
1181
|
+
> ``package-build config: `packageBuild.manifestFlags` must be a non-empty string.``
|
|
1182
|
+
|
|
1183
|
+
### `packageBuild.manifest`
|
|
1184
|
+
|
|
1185
|
+
Everything declared here is emitted into the generated manifest unchanged —
|
|
1186
|
+
**deliberately not key-checked**, so a key Foundry adds in a later version
|
|
1187
|
+
can be declared without waiting on a release of this package. The one rule
|
|
1188
|
+
that has a wrong answer rather than an unknown one: a key the build
|
|
1189
|
+
**derives** must not also be authored, since the authored value would be
|
|
1190
|
+
silently overwritten and the two would be free to disagree with nothing to
|
|
1191
|
+
say so.
|
|
1192
|
+
|
|
1193
|
+
| Forbidden key | Derived from |
|
|
1194
|
+
| ------------------------------------- | ---------------------------------------------------------------- |
|
|
1195
|
+
| `packageBuild.manifest.id` | `foundryPackage`, itself derived from `package.json` `name` |
|
|
1196
|
+
| `packageBuild.manifest.version` | `package.json` `version` |
|
|
1197
|
+
| `packageBuild.manifest.url` | `package.json` `repository` |
|
|
1198
|
+
| `packageBuild.manifest.bugs` | `package.json` `repository` |
|
|
1199
|
+
| `packageBuild.manifest.manifest` | `package.json` `repository` and the release tag |
|
|
1200
|
+
| `packageBuild.manifest.download` | `package.json` `repository` and the release tag |
|
|
1201
|
+
| `packageBuild.manifest.compatibility` | the top level of `package-build.config.yaml` |
|
|
1202
|
+
| `packageBuild.manifest.relationships` | the top level of `package-build.config.yaml` |
|
|
1203
|
+
| `packageBuild.manifest.packs` | the `packs` list at the top level of `package-build.config.yaml` |
|
|
1204
|
+
|
|
1205
|
+
> ``package-build config: `packageBuild.manifest.version` is derived from package.json `version` and must not be declared — it would be overwritten, and the two would disagree with nothing to say so.``
|
|
1206
|
+
|
|
1207
|
+
> ``package-build config: `packageBuild.manifest` must be a mapping.``
|
|
1208
|
+
|
|
1209
|
+
### `packageBuild.schema`
|
|
1210
|
+
|
|
1211
|
+
Registers the DataModel bindings `package-build schema` reads. The document
|
|
1212
|
+
type is the key, so a package that models only Items declares only that
|
|
1213
|
+
entry:
|
|
1214
|
+
|
|
1215
|
+
```yaml
|
|
1216
|
+
packageBuild:
|
|
1217
|
+
schema:
|
|
1218
|
+
Item: { from: module/data/item-models.mjs, registry: ITEM_DM_DEF }
|
|
1219
|
+
```
|
|
1220
|
+
|
|
1221
|
+
| Key (under `packageBuild.schema.<DocumentType>`) | Type | Required |
|
|
1222
|
+
| ------------------------------------------------ | ----------------------------- | -------- |
|
|
1223
|
+
| `packageBuild.schema.<DocumentType>.from` | string (path to a module) | yes |
|
|
1224
|
+
| `packageBuild.schema.<DocumentType>.registry` | string (the exported binding) | yes |
|
|
1225
|
+
|
|
1226
|
+
> ``package-build config: `packageBuild.schema` must be a mapping.``
|
|
1227
|
+
|
|
1228
|
+
> ``package-build config: `packageBuild.schema.<DocumentType>` must be a mapping.``
|
|
1229
|
+
|
|
1230
|
+
> ``package-build config: `packageBuild.schema.<DocumentType>.from` must be a non-empty string.``
|
|
1231
|
+
|
|
1232
|
+
### `packageBuild.clean`
|
|
1233
|
+
|
|
1234
|
+
| Key | Type | Required | Default |
|
|
1235
|
+
| -------------------------- | -------- | -------- | ------- |
|
|
1236
|
+
| `packageBuild.clean.extra` | string[] | no | `[]` |
|
|
1237
|
+
|
|
1238
|
+
Directories to remove beyond the conventional build artifacts.
|
|
1239
|
+
|
|
1240
|
+
> ``package-build config: `packageBuild.clean` must be a mapping.``
|
|
1241
|
+
|
|
1242
|
+
> ``package-build config: `packageBuild.clean.extra` must be a list.``
|
|
1243
|
+
|
|
1244
|
+
> ``package-build config: `packageBuild.clean.extra[<index>]` must be a non-empty string.``
|
|
1245
|
+
|
|
1246
|
+
### `packageBuild.lang`
|
|
1247
|
+
|
|
1248
|
+
Localization coverage settings, read by the `lang` checks.
|
|
1249
|
+
|
|
1250
|
+
| Key | Type | Required | Default |
|
|
1251
|
+
| ------------------------------ | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
1252
|
+
| `packageBuild.lang.sources` | string or string[] (glob) | no | `lang/*.json` |
|
|
1253
|
+
| `packageBuild.lang.help` | string | no | `null` — extra guidance printed after a failure |
|
|
1254
|
+
| `packageBuild.lang.primary` | string | no | `lang/en.json` — the file coverage is measured against |
|
|
1255
|
+
| `packageBuild.lang.scripts` | string or string[] (glob) | no | `src/**/*.{ts,mjs}` |
|
|
1256
|
+
| `packageBuild.lang.templates` | string or string[] (glob) | no | `templates/**/*.hbs` |
|
|
1257
|
+
| `packageBuild.lang.keyRoots` | string or string[] (glob) | no | `null` — derived from the primary file's own keys unless a repository references a root the file does not yet declare |
|
|
1258
|
+
| `packageBuild.lang.references` | string (path to a module) | no | `null` — a module exporting a `references` function |
|
|
1259
|
+
| `packageBuild.lang.retained` | array of `{prefix, reason}` | no | `[]` — key prefixes exempt from the unreferenced advisory |
|
|
1260
|
+
| `packageBuild.lang.allow` | array of `{literal, reason}` | no | `[]` — template literals that are deliberately not localization keys |
|
|
1261
|
+
|
|
1262
|
+
> ``package-build config: `packageBuild.lang` must be a mapping.``
|
|
1263
|
+
|
|
1264
|
+
Each `retained` / `allow` entry states its own reason, which is what keeps
|
|
1265
|
+
the escape hatch from becoming a place unexplained exceptions accumulate:
|
|
1266
|
+
|
|
1267
|
+
> ``package-build config: `packageBuild.lang.retained[<index>]` must be a mapping.``
|
|
1268
|
+
|
|
1269
|
+
> ``package-build config: `packageBuild.lang.retained[<index>].reason` must be a non-empty string.``
|
|
1270
|
+
|
|
1271
|
+
> ``package-build config: `packageBuild.lang.retained[<index>].<key>` is not a recognised key (expected one of: prefix, reason).``
|
|
1272
|
+
|
|
1273
|
+
### `packageBuild.deploy`
|
|
1274
|
+
|
|
1275
|
+
| Key | Type | Required | Default |
|
|
1276
|
+
| ------------------------------- | ------ | -------- | ------- |
|
|
1277
|
+
| `packageBuild.deploy.envPrefix` | string | no | `SOHL` |
|
|
1278
|
+
|
|
1279
|
+
Prefix of the deploy environment variables.
|
|
1280
|
+
|
|
1281
|
+
> ``package-build config: `packageBuild.deploy` must be a mapping.``
|
|
1282
|
+
|
|
1283
|
+
> ``package-build config: `packageBuild.deploy.envPrefix` must be a non-empty string.``
|
|
1284
|
+
|
|
1285
|
+
### `packageBuild.release`
|
|
1286
|
+
|
|
1287
|
+
| Key | Type | Required | Default |
|
|
1288
|
+
| ------------------------------- | ------ | -------- | ------------------------------------------------------------------------ |
|
|
1289
|
+
| `packageBuild.release.artifact` | string | no | `system` for `packageKind: systems`, `module` for `packageKind: modules` |
|
|
1290
|
+
|
|
1291
|
+
Foundry installs a system from `system.json` and a module from
|
|
1292
|
+
`module.json`; the kind already decides which, so this is stated only when
|
|
1293
|
+
a repository genuinely needs the other answer.
|
|
1294
|
+
|
|
1295
|
+
> ``package-build config: `packageBuild.release` must be a mapping.``
|
|
1296
|
+
|
|
1297
|
+
> ``package-build config: `packageBuild.release.artifact` must be a non-empty string.``
|
|
1298
|
+
|
|
1299
|
+
### `packageBuild.bundle`
|
|
1300
|
+
|
|
1301
|
+
| Key | Type | Required | Default |
|
|
1302
|
+
| --------------------------- | ------ | -------- | ---------------------- |
|
|
1303
|
+
| `packageBuild.bundle.entry` | string | no | `<foundryPackage>.mjs` |
|
|
1304
|
+
|
|
1305
|
+
The bundle file Foundry loads, as the manifest spells it. Named after the
|
|
1306
|
+
package by convention; stated only when a repository's bundler emits
|
|
1307
|
+
something else. Deliberately not read back out of the generated manifest —
|
|
1308
|
+
that would let the check agree with itself by construction.
|
|
1309
|
+
|
|
1310
|
+
> ``package-build config: `packageBuild.bundle` must be a mapping.``
|
|
1311
|
+
|
|
1312
|
+
> ``package-build config: `packageBuild.bundle.entry` must be a non-empty string.``
|
|
1313
|
+
|
|
1314
|
+
### `packageBuild.container`
|
|
1315
|
+
|
|
1316
|
+
| Key | Type | Required | Default |
|
|
1317
|
+
| ------------------------------- | ------------------------------------------------- | -------- | --------------------------------- |
|
|
1318
|
+
| `packageBuild.container.image` | string | no | `null` — override for every stage |
|
|
1319
|
+
| `packageBuild.container.name` | string, matching `/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/` | no | `null` — named after the package |
|
|
1320
|
+
| `packageBuild.container.stages` | object (`{stage: spec}`) | no | `{}` |
|
|
1321
|
+
|
|
1322
|
+
`name` is checked against what `docker run` accepts, since the stage is
|
|
1323
|
+
appended to it and a rejected name would otherwise surface as a failure to
|
|
1324
|
+
create a container whose name was never written down:
|
|
1325
|
+
|
|
1326
|
+
> ``package-build config: `packageBuild.container.name` must be a container name docker accepts — a letter or digit, then letters, digits, underscores, periods or hyphens.``
|
|
1327
|
+
|
|
1328
|
+
> ``package-build config: `packageBuild.container` must be a mapping.``
|
|
1329
|
+
|
|
1330
|
+
> ``package-build config: `packageBuild.container.stages` must be a mapping.``
|
|
1331
|
+
|
|
1332
|
+
`packageBuild.container.stages.<name>` is for a stage that is genuinely
|
|
1333
|
+
one repository's own — an older Foundry serving a previous generation of
|
|
1334
|
+
the package. The four every HeroicLands package deploys to (dev, qa, prod,
|
|
1335
|
+
test) need no entry:
|
|
1336
|
+
|
|
1337
|
+
| Key (under `packageBuild.container.stages.<name>`) | Type | Required | Default |
|
|
1338
|
+
| -------------------------------------------------- | ----------------------------------- | -------- | ------- |
|
|
1339
|
+
| `packageBuild.container.stages.<name>.port` | number | no | `null` |
|
|
1340
|
+
| `packageBuild.container.stages.<name>.world` | string (`""` forces no auto-launch) | no | `null` |
|
|
1341
|
+
| `packageBuild.container.stages.<name>.version` | string | no | `null` |
|
|
1342
|
+
|
|
1343
|
+
> ``package-build config: `packageBuild.container.stages.<name>` must be a mapping.``
|
|
1344
|
+
|
|
1345
|
+
> ``package-build config: `packageBuild.container.stages.<name>.port` must be a number.``
|
|
1346
|
+
|
|
1347
|
+
> ``package-build config: `packageBuild.container.stages.<name>.world` must be a string ("" forces no auto-launch).``
|
|
1348
|
+
|
|
1349
|
+
### `packageBuild.e2e`
|
|
1350
|
+
|
|
1351
|
+
The Cypress suite a repository runs against the served world — the one
|
|
1352
|
+
thing the harness does not own, since what runs against a standing world is
|
|
1353
|
+
entirely the repository's.
|
|
1354
|
+
|
|
1355
|
+
| Key | Type | Required | Default |
|
|
1356
|
+
| ---------------------------- | -------------------------------------- | -------- | ------- |
|
|
1357
|
+
| `packageBuild.e2e.stage` | string | no | `test` |
|
|
1358
|
+
| `packageBuild.e2e.suite` | object | no | `null` |
|
|
1359
|
+
| `packageBuild.e2e.results` | string or string[] (glob) | no | `[]` |
|
|
1360
|
+
| `packageBuild.e2e.build` | object (`{target: spec}`) | no | `{}` |
|
|
1361
|
+
| `packageBuild.e2e.world` | object | no | `{}` |
|
|
1362
|
+
| `packageBuild.e2e.gm` | object | no | `{}` |
|
|
1363
|
+
| `packageBuild.e2e.documents` | object (collection → source directory) | no | `{}` |
|
|
1364
|
+
|
|
1365
|
+
> ``package-build config: `packageBuild.e2e` must be a mapping.``
|
|
1366
|
+
|
|
1367
|
+
`packageBuild.e2e.suite`:
|
|
1368
|
+
|
|
1369
|
+
| Key | Type | Required |
|
|
1370
|
+
| ----------------------------- | -------------------------------- | -------- |
|
|
1371
|
+
| `packageBuild.e2e.suite.run` | string[] (program and arguments) | yes |
|
|
1372
|
+
| `packageBuild.e2e.suite.open` | string[] | no |
|
|
1373
|
+
|
|
1374
|
+
> ``package-build config: `packageBuild.e2e.suite` must be a mapping.``
|
|
1375
|
+
|
|
1376
|
+
> ``package-build config: `packageBuild.e2e.suite.run` must be a non-empty list naming a program to run.``
|
|
1377
|
+
|
|
1378
|
+
`packageBuild.e2e.build.<name>` — a bare string is the script name; the
|
|
1379
|
+
mapping form adds `recreate`, for a target that writes something Foundry
|
|
1380
|
+
reads only at world launch (the manifest), where deploying it into a
|
|
1381
|
+
running world deploys a file nothing will look at:
|
|
1382
|
+
|
|
1383
|
+
| Key | Type | Required | Default |
|
|
1384
|
+
| ---------------------------------------- | ------- | ------------------ | ------- |
|
|
1385
|
+
| `packageBuild.e2e.build.<name>.script` | string | yes (mapping form) | — |
|
|
1386
|
+
| `packageBuild.e2e.build.<name>.recreate` | boolean | no | `false` |
|
|
1387
|
+
|
|
1388
|
+
> ``package-build config: `packageBuild.e2e.build.<name>` must be a script name or a mapping.``
|
|
1389
|
+
|
|
1390
|
+
> ``package-build config: `packageBuild.e2e.build.<name>.recreate` must be a boolean.``
|
|
1391
|
+
|
|
1392
|
+
`packageBuild.e2e.world` — declared world identity:
|
|
1393
|
+
|
|
1394
|
+
| Key | Type |
|
|
1395
|
+
| ------------------------------------ | ------ |
|
|
1396
|
+
| `packageBuild.e2e.world.id` | string |
|
|
1397
|
+
| `packageBuild.e2e.world.title` | string |
|
|
1398
|
+
| `packageBuild.e2e.world.description` | string |
|
|
1399
|
+
|
|
1400
|
+
`packageBuild.e2e.gm` — declared GM credentials:
|
|
1401
|
+
|
|
1402
|
+
| Key | Type |
|
|
1403
|
+
| ------------------------------ | ------ |
|
|
1404
|
+
| `packageBuild.e2e.gm.name` | string |
|
|
1405
|
+
| `packageBuild.e2e.gm.password` | string |
|
|
1406
|
+
|
|
1407
|
+
Every value in both mappings must be a non-empty string:
|
|
1408
|
+
|
|
1409
|
+
> ``package-build config: `packageBuild.e2e.world.<key>` must be a non-empty string.``
|
|
1410
|
+
|
|
1411
|
+
`packageBuild.e2e.documents` is a mapping too, but an **open** one — unlike
|
|
1412
|
+
`world` and `gm`, it declares no fixed key list, since a collection name is
|
|
1413
|
+
the repository's own. Every value must still be a non-empty string, naming
|
|
1414
|
+
the source directory:
|
|
1415
|
+
|
|
1416
|
+
> ``package-build config: `packageBuild.e2e.documents.<key>` must be a non-empty string.``
|
|
1417
|
+
|
|
1418
|
+
---
|
|
1419
|
+
|
|
1420
|
+
## Every retired or forbidden key, in one place
|
|
1421
|
+
|
|
1422
|
+
| Key | Why |
|
|
1423
|
+
| ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1424
|
+
| `publish.address.landing` | Retired — named a whole-section landing, and there are no sections to address. |
|
|
1425
|
+
| `packs[].folders` | Retired — a folder is a note (`type: folder`), materialised by the pack whose documents reference it. |
|
|
1426
|
+
| `rootDir` | Forbidden in a YAML configuration — always the file's own directory. |
|
|
1427
|
+
| `foundryPackage` | Forbidden in a YAML configuration — always the adjacent `package.json` `name`. |
|
|
1428
|
+
| `stats.systemId` | Forbidden in every configuration — derived from `packageKind`, `requiresSystem` or a lone declared system. |
|
|
1429
|
+
| `stats.systemVersion` | Forbidden in every configuration — derived from `package.json` (a system) or `systems:` / `relationships.systems` (a module). |
|
|
1430
|
+
| `packageBuild.manifest.id`, `.version`, `.url`, `.bugs`, `.manifest`, `.download`, `.compatibility`, `.relationships`, `.packs` | Forbidden — each is derived from `package.json` or the top level of `package-build.config.yaml`; see [`packageBuild.manifest`](#packagebuildmanifest). |
|
|
1431
|
+
| `publish.site: true` / `publish.site: false` | Refused rather than mapped — write `homepage` or `content`. |
|
|
1432
|
+
| `packs`, `itemBuilders`, `docs`, `compatibility`, `relationships`, `systems`, `requiresSystem`, `stats`, `foundryPackage` | Forbidden in a `documentation` package — each describes a Foundry package this kind is not; see the key's own section for its located refusal message. |
|