@heroiclands/package-build 22.0.3 → 22.1.1
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 +66 -0
- package/CONTENT.md +56 -18
- package/README.md +1 -1
- package/bin/content-build.mjs +67 -23
- package/bin/package-build.mjs +3 -2
- package/config.mjs +52 -1
- package/content-config.mjs +264 -8
- package/docs/api.md +33 -30
- package/docs/commands.md +68 -32
- package/docs/configuration.md +276 -62
- package/docs/getting-started.md +15 -4
- package/docs/project-setup.md +45 -20
- package/engine/content-links.mjs +19 -9
- package/engine/helpers.mjs +2 -1
- package/engine/metadata-index.mjs +32 -0
- package/engine/note-vocabulary.mjs +20 -0
- package/engine/pack-config.mjs +21 -2
- package/engine/site-build.mjs +29 -55
- package/engine/site-config.mjs +503 -0
- package/engine/site-index.mjs +10 -1
- package/engine/web-wikilinks.mjs +16 -6
- package/engine/wikilink-syntax.mjs +10 -0
- package/engine/wikilinks.mjs +34 -7
- package/manifest.mjs +12 -7
- package/package.json +2 -1
- package/stage.mjs +4 -3
- package/types/config.d.mts +24 -0
- package/types/content-config.d.mts +64 -0
- package/types/engine/content-links.d.mts +3 -2
- package/types/engine/metadata-index.d.mts +22 -0
- package/types/engine/note-vocabulary.d.mts +12 -0
- package/types/engine/site-build.d.mts +8 -26
- package/types/engine/site-config.d.mts +236 -0
- package/types/engine/site-index.d.mts +6 -1
- package/types/engine/web-wikilinks.d.mts +9 -5
- package/types/engine/wikilink-syntax.d.mts +3 -0
- package/types/engine/wikilinks.d.mts +16 -5
- package/types/manifest.d.mts +4 -4
- package/types/stage.d.mts +4 -3
package/docs/configuration.md
CHANGED
|
@@ -28,6 +28,8 @@ two routes, and three keys behave differently depending on which:
|
|
|
28
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
29
|
| `rootDir` | Forbidden — always the directory the file sits in | Authored, typically `import.meta.dirname` |
|
|
30
30
|
| `foundryPackage` | Forbidden — always the adjacent `package.json` `name` | Authored |
|
|
31
|
+
| `homepage` | Forbidden — always the adjacent `package.json` `homepage` | Authored |
|
|
32
|
+
| `author` | Forbidden — always the adjacent `package.json` `author` | Authored |
|
|
31
33
|
| `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
34
|
|
|
33
35
|
A file is chosen by its extension: `package-build.config.yaml`, then
|
|
@@ -46,15 +48,18 @@ around its own evaluation.
|
|
|
46
48
|
|
|
47
49
|
### Quick reference
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
20 top-level keys. `rootDir` is not one of them — a data configuration never
|
|
50
52
|
writes it — and is documented under [Derived values](#derived-values) instead,
|
|
51
|
-
alongside `foundryPackage` and `itemBuilders`, whose
|
|
52
|
-
behaviour is also derivation rather than ordinary
|
|
53
|
+
alongside `foundryPackage`, `homepage`, `author` and `itemBuilders`, whose
|
|
54
|
+
data-configuration behaviour is also derivation rather than ordinary
|
|
55
|
+
authoring.
|
|
53
56
|
|
|
54
57
|
| Key | Type | Required | Default |
|
|
55
58
|
| ------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
56
59
|
| [`contentPackage`](#contentpackage) | string | yes | — |
|
|
57
60
|
| [`foundryPackage`](#foundrypackage) | string | yes (`.mjs` only — derived in YAML); refused in a `documentation` package | — |
|
|
61
|
+
| [`homepage`](#homepage) | string | no (`.mjs` only — derived in YAML) | `null` |
|
|
62
|
+
| [`author`](#author) | string, or `{name, email?, url?}` | no (`.mjs` only — derived in YAML) | `null` |
|
|
58
63
|
| [`packageKind`](#packagekind) | `"systems"` \| `"modules"` \| `"documentation"` | yes | — |
|
|
59
64
|
| [`stats`](#stats) | object | yes; refused in a `documentation` package | — |
|
|
60
65
|
| [`itemBuilders`](#itembuilders) | object, or list of `{system, builders}` (or a name/list of names, in YAML) | no; refused in a `documentation` package | `{}` |
|
|
@@ -74,7 +79,7 @@ behaviour is also derivation rather than ordinary authoring.
|
|
|
74
79
|
|
|
75
80
|
Any key outside this list is refused:
|
|
76
81
|
|
|
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). ``
|
|
82
|
+
> `` `<key>` is not a recognized option (expected one of: rootDir, contentPackage, foundryPackage, homepage, author, packageKind, stats, itemBuilders, paths, skipDirectories, icons, packs, docs, site, pdf, compatibility, relationships, systems, requiresSystem, packageBuild, publish). ``
|
|
78
83
|
|
|
79
84
|
(`rootDir` appears in that list because it is a key `defineConfig` itself
|
|
80
85
|
accepts — an `.mjs` configuration authors it directly. A YAML configuration
|
|
@@ -84,11 +89,11 @@ refuses an authored `rootDir` earlier, with its own message — see
|
|
|
84
89
|
|
|
85
90
|
### Derived values
|
|
86
91
|
|
|
87
|
-
|
|
92
|
+
Seven values in the resolved configuration are never transcribed by an author
|
|
88
93
|
— they are computed from where the file sits, from the adjacent
|
|
89
94
|
`package.json`, from the package kind, or from a name naming a table this
|
|
90
|
-
package already ships. Authoring `rootDir`, `foundryPackage`
|
|
91
|
-
`stats.systemVersion` yourself is an **error**, not an override: a
|
|
95
|
+
package already ships. Authoring `rootDir`, `foundryPackage`, `homepage`,
|
|
96
|
+
`author` or `stats.systemVersion` yourself is an **error**, not an override: a
|
|
92
97
|
transcribed copy is free to drift from what it copied, which is exactly how
|
|
93
98
|
`stats.systemVersion` once sat at a stale version for four releases while
|
|
94
99
|
nothing said so. `assetRoot` has no author-facing spelling to refuse in the
|
|
@@ -130,7 +135,7 @@ which applies before either loader form gets a chance to derive anything.
|
|
|
130
135
|
|
|
131
136
|
If the adjacent `package.json` cannot be read, or declares no `name`:
|
|
132
137
|
|
|
133
|
-
> `package-build: <package.json path> could not be read, and the configuration derives
|
|
138
|
+
> `package-build: <package.json path> could not be read, and the configuration derives its Foundry package id, system version, homepage and author from it.`
|
|
134
139
|
|
|
135
140
|
> ``package-build: <package.json path> declares no `name`, which is what the Foundry package id is derived from.``
|
|
136
141
|
|
|
@@ -143,6 +148,54 @@ which applies before either loader form gets a chance to derive anything.
|
|
|
143
148
|
|
|
144
149
|
> ``package-build config: `foundryPackage` must be a non-empty string.``
|
|
145
150
|
|
|
151
|
+
#### `homepage`
|
|
152
|
+
|
|
153
|
+
The address a package's site is served at — read by the generated Hugo
|
|
154
|
+
configuration for `baseURL`, independently of the Foundry manifest's own
|
|
155
|
+
`url`, which derives from `contentPackage` instead (see
|
|
156
|
+
[`packageBuild.manifest`](#packagebuildmanifest)). `null` when the package
|
|
157
|
+
declares none.
|
|
158
|
+
|
|
159
|
+
- In a **YAML** configuration, writing `homepage:` is refused; the loader
|
|
160
|
+
reads it from the adjacent `package.json` `homepage` instead, verbatim:
|
|
161
|
+
|
|
162
|
+
> ``package-build: <config file> declares `homepage`, which a data configuration may not: it is `package.json`'s own `homepage`. Remove the key.``
|
|
163
|
+
|
|
164
|
+
- In an **`.mjs`** configuration, `homepage` is an ordinary optional key — a
|
|
165
|
+
non-empty string when declared:
|
|
166
|
+
|
|
167
|
+
> ``package-build config: `homepage` must be a non-empty string.``
|
|
168
|
+
|
|
169
|
+
`homepage` is not itself checked against `contentPackage` by `defineConfig`.
|
|
170
|
+
`checkHomepage` in `config.mjs` is the check: `homepage` is required
|
|
171
|
+
unconditionally — every package publishes a site — and must be an absolute
|
|
172
|
+
URL whose path ends `/<contentPackage>/`. `content-build site` makes it
|
|
173
|
+
before the generated `baseURL` is written, so a missing or mismatched
|
|
174
|
+
`homepage` is a finding on every site build:
|
|
175
|
+
|
|
176
|
+
> ``package-build config: `homepage` is not declared in `package.json`, and every package needs one to build its site's `baseURL` from. Add `https://www.heroiclands.org/<contentPackage>/`.``
|
|
177
|
+
|
|
178
|
+
> ``package-build config: `homepage` is `https://www.heroiclands.org/harn-ensemble`, but `contentPackage` is `harnensemble` — a package's site is served at `https://www.heroiclands.org/harnensemble/`, so `package.json`'s `homepage` must end `/harnensemble/`.``
|
|
179
|
+
|
|
180
|
+
#### `author`
|
|
181
|
+
|
|
182
|
+
The package's byline, normalised from either of npm's `author` forms — a
|
|
183
|
+
string (`"Name <email> (url)"`, with the email and the URL both optional) or
|
|
184
|
+
an object (`{name, email?, url?}`) — to the object form. `null` when the
|
|
185
|
+
package declares none.
|
|
186
|
+
|
|
187
|
+
- In a **YAML** configuration, writing `author:` is refused; the loader reads
|
|
188
|
+
it from the adjacent `package.json` `author` instead:
|
|
189
|
+
|
|
190
|
+
> ``package-build: <config file> declares `author`, which a data configuration may not: it is `package.json`'s own `author`. Remove the key.``
|
|
191
|
+
|
|
192
|
+
- In an **`.mjs`** configuration, `author` is an ordinary optional key, in
|
|
193
|
+
either form:
|
|
194
|
+
|
|
195
|
+
> ``package-build config: `author` must be `"Name"`, `"Name <email>"`, `"Name (url)"` or `"Name <email> (url)"` — npm's own `author` forms.``
|
|
196
|
+
|
|
197
|
+
> ``package-build config: `author` must be a string or an object with `name`, `email` and `url`.``
|
|
198
|
+
|
|
146
199
|
#### `assetRoot`
|
|
147
200
|
|
|
148
201
|
The served Foundry asset root a compiled document's `img:` is resolved
|
|
@@ -236,7 +289,7 @@ Unlike the first three, authoring `itemBuilders` is not an error — it is
|
|
|
236
289
|
|
|
237
290
|
---
|
|
238
291
|
|
|
239
|
-
## The
|
|
292
|
+
## The 20 keys
|
|
240
293
|
|
|
241
294
|
### `contentPackage`
|
|
242
295
|
|
|
@@ -282,6 +335,16 @@ package id:
|
|
|
282
335
|
|
|
283
336
|
> ``package-build config: `foundryPackage` is refused in a `documentation` package, which is not a Foundry package, so it has no Foundry package id.``
|
|
284
337
|
|
|
338
|
+
### `homepage`
|
|
339
|
+
|
|
340
|
+
See [Derived values](#derived-values) — forbidden in a YAML configuration,
|
|
341
|
+
optional (a non-empty string) in an `.mjs` one.
|
|
342
|
+
|
|
343
|
+
### `author`
|
|
344
|
+
|
|
345
|
+
See [Derived values](#derived-values) — forbidden in a YAML configuration,
|
|
346
|
+
optional (either of npm's forms) in an `.mjs` one.
|
|
347
|
+
|
|
285
348
|
### `packageKind`
|
|
286
349
|
|
|
287
350
|
**Type:** `"systems"` \| `"modules"` \| `"documentation"` · **Required** · no default.
|
|
@@ -436,16 +499,17 @@ name form resolves before reaching here.
|
|
|
436
499
|
**Type:** object · **Optional** · every key defaults to the conventional
|
|
437
500
|
HeroicLands layout, resolved against `rootDir`:
|
|
438
501
|
|
|
439
|
-
| Key
|
|
440
|
-
|
|
|
441
|
-
| `paths.content`
|
|
442
|
-
| `paths.assets`
|
|
443
|
-
| `paths.contentIndex`
|
|
444
|
-
| `paths.packJson`
|
|
445
|
-
| `paths.stage`
|
|
446
|
-
| `paths.unpack`
|
|
447
|
-
| `paths.foreignCache`
|
|
448
|
-
| `paths.metadataCache`
|
|
502
|
+
| Key | Default | What it is |
|
|
503
|
+
| ----------------------- | ------------------------ | ----------------------------------------------------------------------------------------------- |
|
|
504
|
+
| `paths.content` | `assets/content` | The content tree root. |
|
|
505
|
+
| `paths.assets` | `assets` | The asset roots' parent, holding `icons/`, `images/` and `audio/`. |
|
|
506
|
+
| `paths.contentIndex` | `build/content-index` | Where `content-index` writes this package's note index. Derived and disposable. |
|
|
507
|
+
| `paths.packJson` | `build/packs-json` | Build-only per-entry JSON intermediate. |
|
|
508
|
+
| `paths.stage` | `build/stage/packs` | Compiled LevelDB packs. |
|
|
509
|
+
| `paths.unpack` | `build/tmp/packs` | Where `unpack` extracts JSON back to. |
|
|
510
|
+
| `paths.foreignCache` | `build/cache/foreign` | Where a dependency declaring `itemCatalog: true` is unpacked. |
|
|
511
|
+
| `paths.metadataCache` | `build/cache/metadata` | Where a dependency's published content index is fetched to, for every declared dependency. |
|
|
512
|
+
| `paths.navigationCache` | `build/cache/navigation` | Where the site navigation heroiclands.org publishes is fetched to, for the generated Hugo menu. |
|
|
449
513
|
|
|
450
514
|
Every configured path must be **relative** — an absolute one would escape
|
|
451
515
|
the repository the config anchors:
|
|
@@ -458,7 +522,7 @@ An empty value is refused generically:
|
|
|
458
522
|
|
|
459
523
|
Any other key is refused:
|
|
460
524
|
|
|
461
|
-
> ``package-build config: `paths.<key>` is not a recognized option (expected one of: content, assets, contentIndex, packJson, stage, unpack, foreignCache, metadataCache).``
|
|
525
|
+
> ``package-build config: `paths.<key>` is not a recognized option (expected one of: content, assets, contentIndex, packJson, stage, unpack, foreignCache, metadataCache, navigationCache).``
|
|
462
526
|
|
|
463
527
|
### `skipDirectories`
|
|
464
528
|
|
|
@@ -688,36 +752,40 @@ Any other key under `docs.itemFields` is refused:
|
|
|
688
752
|
|
|
689
753
|
**Type:** object · **Optional** · every key defaults to nothing published:
|
|
690
754
|
|
|
691
|
-
| Key | Type | Default
|
|
692
|
-
| ----------------------- | -------- |
|
|
693
|
-
| `site.
|
|
694
|
-
| `site.
|
|
695
|
-
| `site.
|
|
696
|
-
| `site.
|
|
697
|
-
| `site.
|
|
698
|
-
| `site.
|
|
699
|
-
| `site.
|
|
700
|
-
| `site.
|
|
701
|
-
| `site.
|
|
702
|
-
| `site.
|
|
703
|
-
| `site.
|
|
755
|
+
| Key | Type | Default |
|
|
756
|
+
| ----------------------- | -------- | --------------------- |
|
|
757
|
+
| `site.base` | string | `""` |
|
|
758
|
+
| `site.assets` | string | `""` |
|
|
759
|
+
| `site.packages` | string[] | `[]` |
|
|
760
|
+
| `site.sections` | object | `{}` |
|
|
761
|
+
| `site.readmeSections` | object | `{}` |
|
|
762
|
+
| `site.landing` | object | `null` |
|
|
763
|
+
| `site.trees` | array | `[]` |
|
|
764
|
+
| `site.pass` | string | `""` |
|
|
765
|
+
| `site.passOptions` | object | `{}` |
|
|
766
|
+
| `site.backfillSections` | boolean | `false` |
|
|
767
|
+
| `site.list` | object | `{shortcodes: false}` |
|
|
768
|
+
| `site.notfound` | object | `null` |
|
|
769
|
+
| `site.hugo` | object | `{}` |
|
|
704
770
|
|
|
705
771
|
How much of a package reaches the web at all is **not** here — it is
|
|
706
|
-
[`publish.site`](#publish). `site` is framing:
|
|
707
|
-
|
|
708
|
-
the
|
|
709
|
-
|
|
772
|
+
[`publish.site`](#publish). `site` is framing: what a section is called,
|
|
773
|
+
which extra trees are published beside the content, which named pass bundle
|
|
774
|
+
supplies the repository's own body rewrites, and the residue of the
|
|
775
|
+
[generated Hugo configuration](#the-generated-hugo-configuration) that is
|
|
776
|
+
genuinely this repository's own.
|
|
710
777
|
|
|
711
|
-
|
|
778
|
+
Where the Hugo tree is written is not a choice. `content-build site` writes
|
|
779
|
+
the whole Hugo source tree under `build/hugo/` — the generated `hugo.toml`,
|
|
780
|
+
the content mount at `build/hugo/content/`, Hugo's own cache — as a sibling
|
|
781
|
+
of the deployment root `build/site/`, so nothing Hugo reads lands in what is
|
|
782
|
+
published. A `site.out` is refused by name:
|
|
712
783
|
|
|
713
|
-
> ``package-build config: `site
|
|
784
|
+
> ``package-build config: `site.out` is retired — the site build writes its content mount at `build/hugo/content`, beside the generated `hugo.toml`, and the location is not configurable. Remove the key.``
|
|
714
785
|
|
|
715
|
-
`site
|
|
716
|
-
it is refused **at build time** rather than by `defineConfig` (an unset
|
|
717
|
-
value would otherwise resolve to `rootDir` itself, and the tree the build
|
|
718
|
-
wipes on every run would be the working tree):
|
|
786
|
+
> ``package-build config: `site` must be a mapping.``
|
|
719
787
|
|
|
720
|
-
> `site
|
|
788
|
+
> ``package-build config: `site.<key>` is not a recognized option (expected one of: base, assets, packages, sections, readmeSections, landing, trees, pass, passOptions, backfillSections, list, notfound, hugo).``
|
|
721
789
|
|
|
722
790
|
`site.assets` is the host every package's imagery is served from, and it is
|
|
723
791
|
the one address in this file that is not this repository's own. A note names
|
|
@@ -730,11 +798,10 @@ Absolute, and the trailing slash is trimmed:
|
|
|
730
798
|
|
|
731
799
|
> ``package-build config: `site.assets` must be an absolute `http://` or `https://` address — it is the host every package's imagery is served from, and a relative value resolves against whichever page happens to carry the image.``
|
|
732
800
|
|
|
733
|
-
The
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
page,
|
|
737
|
-
relative.
|
|
801
|
+
The generated Hugo configuration carries the same host as
|
|
802
|
+
`params.cdnBaseURL`, which the theme resolves a relative asset path against.
|
|
803
|
+
The two are one value read by two readers: the toolchain emits it into a
|
|
804
|
+
page, and the theme joins it onto anything the toolchain left relative.
|
|
738
805
|
|
|
739
806
|
`site.packages` names which content packages' notes the site walks, beyond
|
|
740
807
|
this one's own; `site.pass` names a repository's own body-rewrite bundle
|
|
@@ -806,6 +873,132 @@ unchanged, and `backfillSections` is a plain boolean:
|
|
|
806
873
|
|
|
807
874
|
> ``package-build config: `site.backfillSections` must be a boolean.``
|
|
808
875
|
|
|
876
|
+
`site.list` is how a listing page renders, written into the generated Hugo
|
|
877
|
+
configuration as `params.list`:
|
|
878
|
+
|
|
879
|
+
| Key | Type | Required | Default |
|
|
880
|
+
| ---------------------- | ------- | -------- | ------- |
|
|
881
|
+
| `site.list.shortcodes` | boolean | no | `false` |
|
|
882
|
+
|
|
883
|
+
> ``package-build config: `site.list` must be a mapping.``
|
|
884
|
+
|
|
885
|
+
> ``package-build config: `site.list.shortcodes` must be a boolean.``
|
|
886
|
+
|
|
887
|
+
> ``package-build config: `site.list.<key>` is not a recognized option (expected one of: shortcodes).``
|
|
888
|
+
|
|
889
|
+
`site.notfound` is the wording of the "page not found" page, written into
|
|
890
|
+
the generated Hugo configuration as `params.notfound`. The theme renders
|
|
891
|
+
the page for every site; what a repository supplies is the tagline, the
|
|
892
|
+
noun the body prose calls the site, and the routes back. `tagline` and
|
|
893
|
+
`sitenoun` are required once the block is present — a block declaring only
|
|
894
|
+
links would render the theme's generic wording above this site's routes,
|
|
895
|
+
which reads as two sites:
|
|
896
|
+
|
|
897
|
+
| Key | Type | Required | Default |
|
|
898
|
+
| ----------------------------- | ------ | -------- | ----------------------------------------------------------------------- |
|
|
899
|
+
| `site.notfound.tagline` | string | yes | — |
|
|
900
|
+
| `site.notfound.sitenoun` | string | yes | — |
|
|
901
|
+
| `site.notfound.heroimage` | string | no | none — the theme's default banner, resolved against `params.cdnBaseURL` |
|
|
902
|
+
| `site.notfound.links` | array | no | none — no list of routes back |
|
|
903
|
+
| `site.notfound.links[].title` | string | yes | — |
|
|
904
|
+
| `site.notfound.links[].url` | string | yes | — site-relative (`/`, `/polity/`) or absolute |
|
|
905
|
+
| `site.notfound.links[].text` | string | yes | — |
|
|
906
|
+
|
|
907
|
+
```yaml
|
|
908
|
+
site:
|
|
909
|
+
notfound:
|
|
910
|
+
tagline: This module has one page, and it is not at
|
|
911
|
+
sitenoun: module
|
|
912
|
+
heroimage: images/banners/tapestry-of-dreams.webp
|
|
913
|
+
links:
|
|
914
|
+
- title: Thalorna
|
|
915
|
+
url: https://www.heroiclands.org/thalorna/
|
|
916
|
+
text: The setting whose artwork this module replaces.
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
> ``package-build config: `site.notfound` must be a mapping.``
|
|
920
|
+
|
|
921
|
+
> ``package-build config: `site.notfound.tagline` must be a non-empty string.``
|
|
922
|
+
|
|
923
|
+
> ``package-build config: `site.notfound.links` must be a list.``
|
|
924
|
+
|
|
925
|
+
> ``package-build config: `site.notfound.links[<index>].url` must be a non-empty string.``
|
|
926
|
+
|
|
927
|
+
> ``package-build config: `site.notfound.<key>` is not a recognized option (expected one of: tagline, sitenoun, heroimage, links).``
|
|
928
|
+
|
|
929
|
+
> ``package-build config: `site.notfound.links[<index>].<key>` is not a recognized option (expected one of: title, url, text).``
|
|
930
|
+
|
|
931
|
+
`site.hugo` is a mapping deep-merged over the generated Hugo configuration,
|
|
932
|
+
last — the escape hatch for the one key nobody anticipated. A repository
|
|
933
|
+
whose homepage reproduces a notice whose bare URLs must stand unedited turns
|
|
934
|
+
Goldmark's autolinker off:
|
|
935
|
+
|
|
936
|
+
```yaml
|
|
937
|
+
site:
|
|
938
|
+
hugo:
|
|
939
|
+
markup:
|
|
940
|
+
goldmark:
|
|
941
|
+
extensions:
|
|
942
|
+
linkify: false
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
Objects merge; an array or a scalar replaces what the generator wrote. Every
|
|
946
|
+
key the generator writes is refused here, naming its source — see
|
|
947
|
+
[the generated Hugo configuration](#the-generated-hugo-configuration) — so
|
|
948
|
+
the block cannot grow into a second configuration file:
|
|
949
|
+
|
|
950
|
+
> ``package-build config: `site.hugo` must be a mapping.``
|
|
951
|
+
|
|
952
|
+
> ``package-build config: `site.hugo.baseURL` is derived from package.json `homepage` and must not be declared — it would be overwritten, and the two would disagree with nothing to say so.``
|
|
953
|
+
|
|
954
|
+
### The generated Hugo configuration
|
|
955
|
+
|
|
956
|
+
`content-build site` writes `build/hugo/hugo.toml` on every run. Every value
|
|
957
|
+
in it has one source, and that source is where it is edited:
|
|
958
|
+
|
|
959
|
+
| Key | Derived from |
|
|
960
|
+
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
961
|
+
| `baseURL` | `package.json` `homepage`, checked by `checkHomepage` — an absolute URL ending `/<contentPackage>/` |
|
|
962
|
+
| `title` | `packageBuild.manifest.title`, which is required |
|
|
963
|
+
| `locale` | the organisation's locale, `en-us`, in `engine/site-config.mjs` |
|
|
964
|
+
| `publishDir` | `contentPackage`, under the deployment root `build/site` — written relative to `build/hugo/`, so `../site/<contentPackage>` |
|
|
965
|
+
| `contentDir` | the fixed content mount, `build/hugo/content` — written as `content` |
|
|
966
|
+
| `themesDir` | where `@heroiclands/hugo-theme` is installed, resolved the way Node resolves a package and written relative to `build/hugo/` |
|
|
967
|
+
| `theme` | the installed `@heroiclands/hugo-theme`, so `hugo-theme` |
|
|
968
|
+
| `disableKinds` | whether any note in the tree carries `tags:`, which the site walk discovers: `["taxonomy", "term", "RSS"]` when none does, `["RSS"]` when at least one does |
|
|
969
|
+
| `taxonomies` | the same fact — written as `{ tag = "tags" }` when at least one note carries `tags:`, absent otherwise |
|
|
970
|
+
| `outputs` | the same fact — written as `{ taxonomy = ["HTML"], term = ["HTML"] }` when at least one note carries `tags:`, absent otherwise |
|
|
971
|
+
| `params.description` | `package.json` `description`; absent when the package declares none |
|
|
972
|
+
| `params.author` | `package.json` `author`, its `name`; absent when the package declares none |
|
|
973
|
+
| `params.cdnBaseURL` | `site.assets`; absent when unset |
|
|
974
|
+
| `params.brand` | the organisation's brand links — `logo`, `licenseURL`, `discordURL` — in `engine/site-config.mjs` |
|
|
975
|
+
| `params.list` | `site.list` |
|
|
976
|
+
| `params.notfound` | `site.notfound`; absent when undeclared |
|
|
977
|
+
| `markup.goldmark.renderer.unsafe` | the toolchain, whose pages carry raw HTML — a `<figure>` for every image, a `<span>` marking an unresolved link |
|
|
978
|
+
| `menu` | the navigation `content-build deps fetch` caches from `https://www.heroiclands.org/nav.json`, entry for entry, a dropdown's entries as `parent` entries |
|
|
979
|
+
|
|
980
|
+
The site build reads the navigation from the cache only. A cold cache is an
|
|
981
|
+
error naming the command that fills it:
|
|
982
|
+
|
|
983
|
+
> `the site navigation has not been fetched. Run `content-build deps fetch` first.`
|
|
984
|
+
|
|
985
|
+
A missing theme names the package to install:
|
|
986
|
+
|
|
987
|
+
> `@heroiclands/hugo-theme is not installed anywhere above <rootDir> — add it to `devDependencies`and run`npm ci``
|
|
988
|
+
|
|
989
|
+
And a site's title reads from the manifest's, so a configuration declaring
|
|
990
|
+
none fails the site build:
|
|
991
|
+
|
|
992
|
+
> ``package-build config: `packageBuild.manifest.title` is not declared, and the site's `title` reads from it.``
|
|
993
|
+
|
|
994
|
+
Nothing else is emitted. A site whose notes carry no `tags:` publishes no
|
|
995
|
+
taxonomy pages — `[taxonomies]` and `[outputs]` go unwritten, and Hugo's
|
|
996
|
+
defaults never apply because `taxonomy` and `term` are disabled kinds. A site
|
|
997
|
+
with at least one tagged note publishes `/tags/` and a page per tag: Hugo's
|
|
998
|
+
own default taxonomy pair also declares `category`, so `[taxonomies]` names
|
|
999
|
+
only `tag`, and `[outputs]` restricts both to `HTML` so neither produces a
|
|
1000
|
+
feed. Every other key is `site.hugo`'s to add.
|
|
1001
|
+
|
|
809
1002
|
### `pdf`
|
|
810
1003
|
|
|
811
1004
|
**Type:** object · **Optional** · default `null` (no book is built).
|
|
@@ -962,6 +1155,7 @@ Each entry, in any of the four lists:
|
|
|
962
1155
|
| `relationships.systems[].manifest` | string | no | none |
|
|
963
1156
|
| `relationships.systems[].compatibility` | object, `{minimum?, verified?}` | no | none |
|
|
964
1157
|
| `relationships.systems[].itemCatalog` | boolean | no | `false` |
|
|
1158
|
+
| `relationships.systems[].contentIndex` | boolean | no | `true` |
|
|
965
1159
|
|
|
966
1160
|
(the same keys apply under `requires[]`, `recommends[]` and
|
|
967
1161
|
`conflicts[]`.)
|
|
@@ -970,7 +1164,7 @@ Each entry, in any of the four lists:
|
|
|
970
1164
|
|
|
971
1165
|
> ``package-build config: `relationships.<kind>[<index>].id` must be a non-empty string.``
|
|
972
1166
|
|
|
973
|
-
> ``package-build config: `relationships.<kind>[<index>].<key>` is not a recognized option (expected one of: id, contentPackage, type, manifest, compatibility, itemCatalog).``
|
|
1167
|
+
> ``package-build config: `relationships.<kind>[<index>].<key>` is not a recognized option (expected one of: id, contentPackage, type, manifest, compatibility, itemCatalog, contentIndex).``
|
|
974
1168
|
|
|
975
1169
|
`contentPackage` names what the other package's _content_ is called, where
|
|
976
1170
|
that differs from its Foundry id. A note addresses a file by the content
|
|
@@ -989,6 +1183,20 @@ item catalogue at build time. It requires a `manifest`:
|
|
|
989
1183
|
|
|
990
1184
|
> ``package-build config: `relationships.<kind>[<index>].itemCatalog` needs a `manifest` naming the package to fetch.``
|
|
991
1185
|
|
|
1186
|
+
`contentIndex` and `itemCatalog` are the two edges a relationship may declare,
|
|
1187
|
+
and a package may have either without the other. `itemCatalog` says a
|
|
1188
|
+
dependency supplies _items_; `contentIndex`, `true` by default, says
|
|
1189
|
+
`deps fetch` fetches its published note index and this tree may cite its
|
|
1190
|
+
addresses by wikilink. Declaring `contentIndex: false` narrows the
|
|
1191
|
+
relationship to the Foundry manifest only — a dependency Foundry installs but
|
|
1192
|
+
this tree never cites — so `deps fetch` fetches nothing for it and a wikilink
|
|
1193
|
+
into it fails, naming the key, rather than resolving against a stale
|
|
1194
|
+
declaration or an index nobody fetched:
|
|
1195
|
+
|
|
1196
|
+
> ``package-build config: `relationships.<kind>[<index>].contentIndex` must be true or false.``
|
|
1197
|
+
|
|
1198
|
+
> ``package-build config: `relationships.<kind>[<index>].contentIndex` cannot be false together with `itemCatalog: true` — a catalogue is fetched from the same index.``
|
|
1199
|
+
|
|
992
1200
|
### `systems`
|
|
993
1201
|
|
|
994
1202
|
**Type:** object (`{id: spec}`) · **Optional** · default `{}`. Refused in a
|
|
@@ -1157,7 +1365,7 @@ packageBuild:
|
|
|
1157
1365
|
assetTransform: ./utils/svg-theme.mjs
|
|
1158
1366
|
stageDir: build/stage
|
|
1159
1367
|
clean:
|
|
1160
|
-
extra: [
|
|
1368
|
+
extra: [coverage]
|
|
1161
1369
|
lang:
|
|
1162
1370
|
sources: lang/*.json
|
|
1163
1371
|
deploy:
|
|
@@ -1232,6 +1440,7 @@ say so.
|
|
|
1232
1440
|
| ------------------------------------- | ---------------------------------------------------------------- |
|
|
1233
1441
|
| `packageBuild.manifest.id` | `foundryPackage`, itself derived from `package.json` `name` |
|
|
1234
1442
|
| `packageBuild.manifest.version` | `package.json` `version` |
|
|
1443
|
+
| `packageBuild.manifest.description` | `package.json` `description` |
|
|
1235
1444
|
| `packageBuild.manifest.url` | `package.json` `repository` |
|
|
1236
1445
|
| `packageBuild.manifest.bugs` | `package.json` `repository` |
|
|
1237
1446
|
| `packageBuild.manifest.manifest` | `package.json` `repository` and the release tag |
|
|
@@ -1242,6 +1451,8 @@ say so.
|
|
|
1242
1451
|
|
|
1243
1452
|
> ``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.``
|
|
1244
1453
|
|
|
1454
|
+
> ``package-build config: `packageBuild.manifest.description` is derived from package.json `description` and must not be declared — it would be overwritten, and the two would disagree with nothing to say so.``
|
|
1455
|
+
|
|
1245
1456
|
> ``package-build config: `packageBuild.manifest` must be a mapping.``
|
|
1246
1457
|
|
|
1247
1458
|
### `packageBuild.schema`
|
|
@@ -1457,14 +1668,17 @@ the source directory:
|
|
|
1457
1668
|
|
|
1458
1669
|
## Every retired or forbidden key, in one place
|
|
1459
1670
|
|
|
1460
|
-
| Key
|
|
1461
|
-
|
|
|
1462
|
-
| `publish.address.landing`
|
|
1463
|
-
| `packs[].folders`
|
|
1464
|
-
| `rootDir`
|
|
1465
|
-
| `foundryPackage`
|
|
1466
|
-
| `
|
|
1467
|
-
| `stats.
|
|
1468
|
-
| `
|
|
1469
|
-
| `
|
|
1470
|
-
| `
|
|
1671
|
+
| Key | Why |
|
|
1672
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1673
|
+
| `publish.address.landing` | Retired — named a whole-section landing, and there are no sections to address. |
|
|
1674
|
+
| `packs[].folders` | Retired — a folder is a note (`type: folder`), materialised by the pack whose documents reference it. |
|
|
1675
|
+
| `rootDir` | Forbidden in a YAML configuration — always the file's own directory. |
|
|
1676
|
+
| `foundryPackage` | Forbidden in a YAML configuration — always the adjacent `package.json` `name`. |
|
|
1677
|
+
| `homepage`, `author` | Forbidden in a YAML configuration — always the adjacent `package.json`'s own `homepage` and `author`. |
|
|
1678
|
+
| `stats.systemId` | Forbidden in every configuration — derived from `packageKind`, `requiresSystem` or a lone declared system. |
|
|
1679
|
+
| `stats.systemVersion` | Forbidden in every configuration — derived from `package.json` (a system) or `systems:` / `relationships.systems` (a module). |
|
|
1680
|
+
| `packageBuild.manifest.id`, `.version`, `.description`, `.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). |
|
|
1681
|
+
| `site.out` | Retired — the site build writes its content mount at `build/hugo/content`, beside the generated `hugo.toml`. |
|
|
1682
|
+
| `site.hugo.baseURL`, `.title`, `.locale`, `.publishDir`, `.contentDir`, `.themesDir`, `.theme`, `.disableKinds`, `.taxonomies`, `.outputs`, `.params.description`, `.params.author`, `.params.cdnBaseURL`, `.params.brand`, `.params.list`, `.params.notfound`, `.markup.goldmark.renderer.unsafe`, `.menu` | Forbidden — each is written by the site build from a source it names; see [the generated Hugo configuration](#the-generated-hugo-configuration). |
|
|
1683
|
+
| `publish.site: true` / `publish.site: false` | Refused rather than mapped — write `homepage` or `content`. |
|
|
1684
|
+
| `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. |
|
package/docs/getting-started.md
CHANGED
|
@@ -769,10 +769,21 @@ for.
|
|
|
769
769
|
Four capabilities are configuration away, and each has its own guide material.
|
|
770
770
|
None of them is needed to build a package.
|
|
771
771
|
|
|
772
|
-
**A website.**
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
772
|
+
**A website.** Every package publishes one — at the least, the homepage note
|
|
773
|
+
from step 5 — at `https://www.heroiclands.org/<contentPackage>/`. Add that
|
|
774
|
+
address to `package.json` as `homepage`, with a `description` and an `author`
|
|
775
|
+
beside it; add `@heroiclands/hugo-theme` under `devDependencies`; and add a
|
|
776
|
+
`packageBuild.manifest.title`. Then `content-build deps fetch` caches the
|
|
777
|
+
organisation's navigation, and `content-build site` writes the whole Hugo
|
|
778
|
+
source tree under `build/hugo/` — the configuration generated from those
|
|
779
|
+
values, and the content mount — for `hugo --source build/hugo` to render
|
|
780
|
+
into `build/site/<contentPackage>/`. There is no Hugo configuration to
|
|
781
|
+
write: the file is generated on every run, and what is genuinely the
|
|
782
|
+
package's own — the wording of its "page not found" page — goes in the
|
|
783
|
+
`site:` block as `site.notfound`. Set `publish.site: content` and name the
|
|
784
|
+
sections under `site.sections`, and the same command publishes the content
|
|
785
|
+
tree's every page beside the homepage. [`project-setup.md`](project-setup.md)
|
|
786
|
+
gives the npm scripts.
|
|
776
787
|
|
|
777
788
|
**Another package's content.** Declare a dependency under `relationships`, and
|
|
778
789
|
`content-build deps fetch` caches that release's published content index so
|
package/docs/project-setup.md
CHANGED
|
@@ -123,9 +123,10 @@ wrong-case import passes locally and fails there.
|
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
`clean` removes the conventional build directories plus anything named in
|
|
126
|
-
`packageBuild.clean.extra` — a
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
`packageBuild.clean.extra` — a coverage directory, say. Everything the site
|
|
127
|
+
build writes is under `build/`, so a site needs no entry. `distclean`
|
|
128
|
+
additionally removes `node_modules`. Both exit 0 whether or not there was
|
|
129
|
+
anything to remove.
|
|
129
130
|
|
|
130
131
|
### `lint:*` — the checks, one per question
|
|
131
132
|
|
|
@@ -239,12 +240,36 @@ changesets does not touch the lockfile.
|
|
|
239
240
|
|
|
240
241
|
### The site scripts
|
|
241
242
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
243
|
+
Every package publishes a website — at the least, its homepage — so every
|
|
244
|
+
package carries this group:
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
"build:site": "run-s build:site-content build:site-html build:site-root",
|
|
248
|
+
"build:site-content": "content-build site",
|
|
249
|
+
"build:site-html": "hugo --source build/hugo --minify --gc --cleanDestinationDir",
|
|
250
|
+
"build:site-root": "package-build site-root",
|
|
251
|
+
"serve:site": "npm run build:site-content && hugo server --source build/hugo"
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`build:site-content` writes the whole Hugo source tree under `build/hugo/` —
|
|
255
|
+
the generated `hugo.toml` and the content mount — with `content-build site`;
|
|
256
|
+
`build:site-html` runs Hugo over it, rendering into `build/site/<contentPackage>/`;
|
|
257
|
+
`build:site-root` writes the deployment's `_headers` and `_redirects` beside
|
|
258
|
+
that; and `serve:site` does the first and then `hugo server` for a live
|
|
259
|
+
preview. The repository carries no Hugo configuration of its own: `hugo.toml`
|
|
260
|
+
is generated on every run from `package.json`, `package-build.config.yaml`,
|
|
261
|
+
the installed `@heroiclands/hugo-theme` and the navigation `deps fetch`
|
|
262
|
+
cached, and the only file to add is `@heroiclands/hugo-theme` under
|
|
263
|
+
`devDependencies`. Hugo itself is a separate install — the extended edition,
|
|
264
|
+
on the developer's `PATH` and the runner's.
|
|
265
|
+
|
|
266
|
+
The site build reads the cached navigation, so `build:site` in a package with
|
|
267
|
+
no other dependency still runs `deps fetch` first:
|
|
268
|
+
|
|
269
|
+
```json
|
|
270
|
+
"build:site": "run-s build:deps build:site-content build:site-html build:site-root",
|
|
271
|
+
"build:deps": "content-build deps fetch"
|
|
272
|
+
```
|
|
248
273
|
|
|
249
274
|
### Deployment scripts
|
|
250
275
|
|
|
@@ -453,17 +478,17 @@ site-deploy workflow, so a fix to any of them reaches every repository at once.
|
|
|
453
478
|
|
|
454
479
|
A summary, because "where does this come from" is the question that recurs.
|
|
455
480
|
|
|
456
|
-
| Read | By
|
|
457
|
-
| -------------------------------------------------- |
|
|
458
|
-
| `package.json` | The Foundry package id, the version, the release addresses. |
|
|
459
|
-
| `package-build.config.yaml` | Everything else about the build.
|
|
460
|
-
| `assets/content/**/*.md` | Every content command.
|
|
461
|
-
| `.gitignore` | `content-build format`, `content-build markdown`.
|
|
462
|
-
| `.prettierignore` | `content-build format`.
|
|
463
|
-
| `.github/labels.yml`, `.github/ISSUE_REPORTING.md` | `package-build labels check`.
|
|
464
|
-
| `lang/*.json` | `package-build lang`.
|
|
465
|
-
| `.env.local` | `package-build deploy`.
|
|
466
|
-
| `.github/workflows/build.yml` | The `pre-push` hook, for its step list.
|
|
481
|
+
| Read | By |
|
|
482
|
+
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
483
|
+
| `package.json` | The Foundry package id, the version, the release addresses; the site's `baseURL`, description and author. |
|
|
484
|
+
| `package-build.config.yaml` | Everything else about the build. |
|
|
485
|
+
| `assets/content/**/*.md` | Every content command. |
|
|
486
|
+
| `.gitignore` | `content-build format`, `content-build markdown`. |
|
|
487
|
+
| `.prettierignore` | `content-build format`. |
|
|
488
|
+
| `.github/labels.yml`, `.github/ISSUE_REPORTING.md` | `package-build labels check`. |
|
|
489
|
+
| `lang/*.json` | `package-build lang`. |
|
|
490
|
+
| `.env.local` | `package-build deploy`. |
|
|
491
|
+
| `.github/workflows/build.yml` | The `pre-push` hook, for its step list. |
|
|
467
492
|
|
|
468
493
|
Everything written goes under `build/`. Nothing the toolchain generates is
|
|
469
494
|
committed.
|