@heroiclands/package-build 3.4.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +182 -0
- package/CONTENT.md +100 -22
- package/MIGRATING.md +120 -0
- package/bin/content-build.mjs +6 -2
- package/content-config.mjs +109 -6
- package/engine/base-compiler.mjs +33 -36
- package/engine/content-links.mjs +15 -13
- package/engine/content-package.mjs +3 -2
- package/engine/field-reference.mjs +2 -2
- package/engine/frontmatter-lint.mjs +26 -0
- package/engine/helpers.mjs +10 -12
- package/engine/homepage.mjs +150 -0
- package/engine/index.mjs +10 -1
- package/engine/journals.mjs +2 -3
- package/engine/macros.mjs +2 -3
- package/engine/manifest-emit.mjs +17 -12
- package/engine/note-package.mjs +75 -68
- package/engine/note-schemas.mjs +44 -0
- package/engine/pack-router.mjs +3 -3
- package/engine/retired-fields.mjs +123 -0
- package/engine/scenes.mjs +7 -11
- package/engine/site-build.mjs +151 -22
- package/engine/site-index.mjs +5 -5
- package/package.json +1 -1
- package/sohl/actors.mjs +2 -3
- package/sohl/items.mjs +2 -3
- package/sohl/note-schemas.mjs +8 -0
- package/types/content-config.d.mts +105 -4
- package/types/engine/base-compiler.d.mts +12 -17
- package/types/engine/content-package.d.mts +3 -2
- package/types/engine/helpers.d.mts +5 -8
- package/types/engine/homepage.d.mts +118 -0
- package/types/engine/index.d.mts +3 -0
- package/types/engine/manifest-emit.d.mts +7 -8
- package/types/engine/note-package.d.mts +29 -34
- package/types/engine/note-schemas.d.mts +6 -0
- package/types/engine/pack-router.d.mts +3 -3
- package/types/engine/retired-fields.d.mts +54 -0
- package/types/engine/site-build.d.mts +52 -4
- package/types/sohl/note-schemas.d.mts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,187 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 4da0dbc: Every package publishes an authored homepage at `/<contentPackage>/`, and
|
|
8
|
+
`publish.site` becomes a mode rather than a boolean (#51, #55).
|
|
9
|
+
|
|
10
|
+
**A `type: homepage` note (#51)**
|
|
11
|
+
|
|
12
|
+
A new engine-level content type that compiles into a **page** rather than into a
|
|
13
|
+
compendium document. Its whole frontmatter envelope is `type` and an optional
|
|
14
|
+
`title`, defaulting to `packageBuild.manifest.title` so the package's name is not
|
|
15
|
+
written twice:
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
---
|
|
19
|
+
type: homepage
|
|
20
|
+
title: HârnMaster Kethira Basic
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
What the module is, which system it needs, how to install it.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
It compiles into no document, appears in no pack and in no link manifest, and is
|
|
27
|
+
addressed by the **package** — `/<contentPackage>/` — rather than by a slug
|
|
28
|
+
derived from its name, so `name.full`, `shortcode` and `id` decide nothing on it.
|
|
29
|
+
It is written at the root of `site.out`, one level above the content mount.
|
|
30
|
+
|
|
31
|
+
The page is _authored, not assembled_. Deriving it from the manifest, the release
|
|
32
|
+
address and `relationships` was the obvious shortcut and produces a page nobody
|
|
33
|
+
chose the contents of — it cannot express that Kethira requires buying the book
|
|
34
|
+
from Keléstia, or which of twenty sections a reader should start with.
|
|
35
|
+
|
|
36
|
+
It is declared in `engine/note-schemas.mjs` rather than in the `sohl` item
|
|
37
|
+
registry: the `engine/` ÷ `sohl/` line is note-format knowledge against
|
|
38
|
+
game-system knowledge, and a homepage carries no `system` block and mirrors no
|
|
39
|
+
item builder. Reachability is the symptom that makes it obvious —
|
|
40
|
+
`HarnMaster-3-FoundryVTT` declares no `itemBuilders` at all, so a type living in
|
|
41
|
+
the SoHL registry would be unavailable to HM3 and every HM3 module, which is most
|
|
42
|
+
of the packages that need a homepage and nothing else.
|
|
43
|
+
|
|
44
|
+
**`publish.site` is a mode (#55) — breaking**
|
|
45
|
+
|
|
46
|
+
| Was | Write |
|
|
47
|
+
| ------------- | ---------------------------------- |
|
|
48
|
+
| `site: true` | `site: content` |
|
|
49
|
+
| `site: false` | `site: homepage` |
|
|
50
|
+
| absent | absent — the default is `homepage` |
|
|
51
|
+
|
|
52
|
+
`homepage` publishes the authored homepage and **no other page**; `content`
|
|
53
|
+
publishes it plus every page the content tree compiles to. There is no value
|
|
54
|
+
meaning "no web presence", because every package publishes its homepage.
|
|
55
|
+
|
|
56
|
+
Both booleans are **refused rather than mapped** onto the nearest mode, naming
|
|
57
|
+
the mode to write. `false` read as _this package has no web presence_, which
|
|
58
|
+
describes no package now, and a value silently reinterpreted reads to its author
|
|
59
|
+
as though it still means what it said.
|
|
60
|
+
|
|
61
|
+
**Homepage-only is a first-class mode, not an accommodation.**
|
|
62
|
+
`sohl-kethira-basic` (Keléstia Productions' Fan Material Guidelines) and
|
|
63
|
+
`harn-adventures` (HârnFanon under Lythia's terms) each publish a homepage and
|
|
64
|
+
nothing beneath it — two packages under two different fan-content licences. The
|
|
65
|
+
boundary is _published content_: journal text, artwork, item descriptions,
|
|
66
|
+
compiled notes. Because the failure mode is silent — a `site:` block added later
|
|
67
|
+
ships licensed content with nobody noticing — the mode **fences the content
|
|
68
|
+
surfaces off**: in `homepage` mode the tree is never walked for pages, and
|
|
69
|
+
`sections`, `trees`, `landing` and `backfillSections` emit nothing even when they
|
|
70
|
+
are declared. Measured against the real `sohl-kethira-basic` tree — 363 notes,
|
|
71
|
+
and a `site:` block deliberately declaring sections and a landing — the build
|
|
72
|
+
emits exactly one file.
|
|
73
|
+
|
|
74
|
+
`publish.manifests.publish` is a separate decision and stays `false` for both, for
|
|
75
|
+
an unrelated reason: a link manifest is the dependency edge that would stop a
|
|
76
|
+
module being withdrawable, and a homepage is one row in a routing table.
|
|
77
|
+
|
|
78
|
+
**Nothing else moves.** `publish.address`, `publish.manifests` and the whole
|
|
79
|
+
`site:` block are unchanged, and every address `sohl` already publishes is
|
|
80
|
+
byte-identical across the upgrade. Verified against the real tree: 1,669 emitted
|
|
81
|
+
files before, 1,670 after, the one addition being `kb/content/_index.md`; the
|
|
82
|
+
link manifest's 2,989 entries and all 3,126 compiled pack documents are
|
|
83
|
+
byte-identical with and without the homepage note.
|
|
84
|
+
|
|
85
|
+
## 4.0.0
|
|
86
|
+
|
|
87
|
+
### Major Changes
|
|
88
|
+
|
|
89
|
+
- 8cfa834: Reject `package:` in a note's frontmatter (#56).
|
|
90
|
+
|
|
91
|
+
A note's package is the repository's configured `contentPackage`, full stop. A
|
|
92
|
+
note that declares the field fails the build, naming the file — **whatever the
|
|
93
|
+
value says**. An agreeing declaration is refused exactly as a disagreeing one
|
|
94
|
+
is: there is no value that makes writing the field correct, and a field accepted
|
|
95
|
+
while it agrees is a field that grows back one note at a time.
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
assets/content/Gear/Axe.md:12:1: error: `package: sohl` is a retired frontmatter field — delete it. A note's package is this repository's configured `contentPackage` ("sohl", in package-build.config.yaml), and every note in the tree belongs to it.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`content-build lint` reports every such note in one pass, so a tree can be
|
|
102
|
+
checked before it is compiled; `package compile` and `manifest` refuse it.
|
|
103
|
+
|
|
104
|
+
**This is the third and last step**, and the two before it are already released
|
|
105
|
+
and adopted. 3.3.0 made the field optional so an absent one was normal and a
|
|
106
|
+
disagreeing one was an error; every content tree on the org was then swept on
|
|
107
|
+
that version — `sohl` (1,639 files), `thalorna` (1,716), `kethira` (363),
|
|
108
|
+
`harnensemble` (2,517). Nothing this release refuses is authored anywhere today.
|
|
109
|
+
|
|
110
|
+
**Why a major.** Consumers resolve `^3`, so a minor would reach every repository
|
|
111
|
+
on the next Dependabot run. A major is adopted deliberately, one repository at a
|
|
112
|
+
time, in a pull request that can also delete the field if any grew back — which
|
|
113
|
+
is the whole mechanism that made the deprecate → migrate → remove sequence safe.
|
|
114
|
+
|
|
115
|
+
**Migrating** is one line, and nothing else reads the field:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
find assets/content -name '*.md' -print0 | xargs -0 sed -i '' '/^package: /d'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`package compile` then produces byte-identical output, because the value the
|
|
122
|
+
build derives is the value the notes restated. See `MIGRATING.md`.
|
|
123
|
+
|
|
124
|
+
**`contentPackage` is unaffected, and is not vestigial.** It is the address
|
|
125
|
+
namespace — the first segment of every canonical key, the name of the emitted
|
|
126
|
+
link manifest, and the package a cross-package wikilink writes. Retiring the
|
|
127
|
+
frontmatter field is what leaves it as the single source of that value: every
|
|
128
|
+
key is now derived from the configuration, where it used to come from two
|
|
129
|
+
sources that happened to agree.
|
|
130
|
+
|
|
131
|
+
**A generated table's `WHERE … and package = "<pkg>"` clause keeps matching** —
|
|
132
|
+
45 such clauses across `sohl` and `thalorna` depend on it. The package is
|
|
133
|
+
_synthesised_ into what the table search sees, from `contentPackage`; it is a
|
|
134
|
+
search value, never an authored one.
|
|
135
|
+
|
|
136
|
+
**API.** `engine/note-package.mjs` no longer exports `notePackage` — every call
|
|
137
|
+
site takes `contentPackage` directly, so no key is derived from frontmatter
|
|
138
|
+
anywhere — and `assertNotePackage` is now `assertNoDeclaredPackage`, which
|
|
139
|
+
asserts the field's absence rather than answering which package a note belongs
|
|
140
|
+
to. `expandNoteTables` no longer takes `pkg`: a table searches the whole tree,
|
|
141
|
+
which is one package's notes and nothing else.
|
|
142
|
+
- ad7691f: Remove `draft:` from a note's frontmatter (#69).
|
|
143
|
+
|
|
144
|
+
The field excluded a note from the compiled packs, from the link manifest and
|
|
145
|
+
from a consuming site build — and **nothing reported the consequence**.
|
|
146
|
+
`content-links.mjs`, `site-index.mjs` and `content-lint.mjs` never read it, so a
|
|
147
|
+
wikilink into a drafted note was indistinguishable from a link to a note that
|
|
148
|
+
does not exist, and no checker could say which. Its entire effect was to move a
|
|
149
|
+
note from _published_ to _unresolvable_, in silence. It also suppressed real
|
|
150
|
+
build failures: a note the compilers never reached could not fail on the defects
|
|
151
|
+
it carried.
|
|
152
|
+
|
|
153
|
+
Nothing used it. Across every HeroicLands content repository — `sohl`,
|
|
154
|
+
`sohl-thalorna`, `sohl-kethira-basic`, `harn-ensemble`, `harn-adventures` — not
|
|
155
|
+
one note declared it.
|
|
156
|
+
|
|
157
|
+
**What changed**
|
|
158
|
+
|
|
159
|
+
- The three readers are gone: the compile loop, the link-manifest walk, and the
|
|
160
|
+
scenes pass's map collection. So are the `skippedDraft` tally, its `PassStats`
|
|
161
|
+
field, and the `Skipped N draft(s)` log line.
|
|
162
|
+
- A note declaring `draft:` now **fails the build**, naming the file and the
|
|
163
|
+
line, whatever the value says — `draft: false` included, since it reads as
|
|
164
|
+
"publish this note", which is what happens either way. A field left merely
|
|
165
|
+
ignored reads to its author as though it still works, which is the same
|
|
166
|
+
silence in a different place.
|
|
167
|
+
- `content-build lint` reports it too, so a whole tree is answered at once
|
|
168
|
+
rather than one note per build.
|
|
169
|
+
|
|
170
|
+
**The `draft` _tag_ is untouched.** It is an authoring marker, read only by the
|
|
171
|
+
generated-table pass for `FROM #draft` queries, and 268 `sohl-thalorna` notes
|
|
172
|
+
carry it. An unfinished page is honest about being unfinished; a dropped link is
|
|
173
|
+
silent.
|
|
174
|
+
|
|
175
|
+
**Adopting**
|
|
176
|
+
|
|
177
|
+
Nothing to sweep — no note in the org declares the field. A consumer that
|
|
178
|
+
carries one deletes the line.
|
|
179
|
+
|
|
180
|
+
This lands in the same major as the `package:` rejection (#56 step 3), so the
|
|
181
|
+
two retired fields are one adoption rather than two. They are refused the same
|
|
182
|
+
way, through the same diagnostic format and the same positioning, and the
|
|
183
|
+
locator both need is now shared rather than written twice.
|
|
184
|
+
|
|
3
185
|
## 3.4.0
|
|
4
186
|
|
|
5
187
|
### Minor Changes
|
package/CONTENT.md
CHANGED
|
@@ -128,9 +128,11 @@ packageBuild:
|
|
|
128
128
|
- { from: assets/icons, to: assets/icons }
|
|
129
129
|
|
|
130
130
|
# Three independent switches — every combination is real — plus the address
|
|
131
|
-
# scheme both `manifest` and `site` derive addresses under.
|
|
131
|
+
# scheme both `manifest` and `site` derive addresses under. `site` is a mode,
|
|
132
|
+
# not a boolean: `homepage` (the default) publishes the authored homepage and
|
|
133
|
+
# no other page; `content` publishes it plus every page the tree compiles to.
|
|
132
134
|
publish:
|
|
133
|
-
site:
|
|
135
|
+
site: content
|
|
134
136
|
manifests: { publish: true, consume: true }
|
|
135
137
|
address:
|
|
136
138
|
prefix: kb/
|
|
@@ -147,8 +149,8 @@ site:
|
|
|
147
149
|
|
|
148
150
|
The loader validates the document, resolves every path against the directory
|
|
149
151
|
the file sits in, fills the optional halves with their defaults
|
|
150
|
-
(`skipDirectories: []`, `packageBuild: {}`, the conventional `paths`,
|
|
151
|
-
|
|
152
|
+
(`skipDirectories: []`, `packageBuild: {}`, the conventional `paths`, both
|
|
153
|
+
manifest switches off and `publish.site` at its `homepage` floor),
|
|
152
154
|
derives `assetRoot`, `packDirectories`, `itemTypes` and `docEntryTypes`, and
|
|
153
155
|
freezes the result. A malformed configuration throws a `TypeError` naming the
|
|
154
156
|
offending field, so it fails at load rather than as an empty pack much later.
|
|
@@ -178,27 +180,44 @@ something migrates on it.
|
|
|
178
180
|
### A note's package is the repository's, not the note's
|
|
179
181
|
|
|
180
182
|
`contentPackage` is the **address namespace** every note in the tree is
|
|
181
|
-
published under
|
|
183
|
+
published under: the first segment of every canonical key (`sohl-skill-clmb`),
|
|
184
|
+
the name of the link manifest this build emits (`sohl.json`), and the package a
|
|
185
|
+
cross-package wikilink writes to reach one of these notes. It is the
|
|
186
|
+
repository's identity in the address space — not a filter — and a note does not
|
|
187
|
+
restate it.
|
|
188
|
+
|
|
189
|
+
**`package:` in a note's frontmatter is retired, and declaring it fails the
|
|
190
|
+
build**, naming the file, whatever the value says. An agreeing declaration is
|
|
191
|
+
refused exactly as a disagreeing one is: there is no value that makes writing
|
|
192
|
+
the field correct. The diagnostic says so, and says where the value comes from
|
|
193
|
+
instead:
|
|
182
194
|
|
|
183
|
-
|
|
184
|
-
is
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
195
|
+
```text
|
|
196
|
+
assets/content/Gear/Axe.md:12:1: error: `package: sohl` is a retired frontmatter field — delete it. A note's package is this repository's configured `contentPackage` ("sohl", in package-build.config.yaml), and every note in the tree belongs to it.
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`content-build lint` reports every such note in one pass; `content-build
|
|
200
|
+
package compile` and `content-build manifest` refuse the tree.
|
|
189
201
|
|
|
190
202
|
A generated table that scopes itself with `WHERE … and package = "<pkg>"` keeps
|
|
191
|
-
working
|
|
192
|
-
|
|
193
|
-
|
|
203
|
+
working: the package is **synthesised** into what the table search sees,
|
|
204
|
+
supplied from `contentPackage` rather than read off the note. It is a search
|
|
205
|
+
value, never an authored one.
|
|
194
206
|
|
|
195
207
|
It used to **select**: a note compiled when its `package:` matched and was
|
|
196
208
|
skipped when it did not. Every content tree is single-package — each is
|
|
197
209
|
single-sourced in the repository that ships it — so the field restated one
|
|
198
210
|
constant thousands of times, while a tree whose notes named a package no
|
|
199
211
|
configuration answered to compiled **zero notes and exited 0**. Deleting the
|
|
200
|
-
field from a note is
|
|
201
|
-
|
|
212
|
+
field from a note is the fix; deleting the _configured_ value is not, since
|
|
213
|
+
every address derives from it.
|
|
214
|
+
|
|
215
|
+
Sweeping a tree is mechanical — the field is a whole line, and nothing else
|
|
216
|
+
reads it:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
find assets/content -name '*.md' -print0 | xargs -0 sed -i '' '/^package: /d'
|
|
220
|
+
```
|
|
202
221
|
|
|
203
222
|
### A registry of your own
|
|
204
223
|
|
|
@@ -577,10 +596,11 @@ It reads its whole input from configuration and takes nothing else:
|
|
|
577
596
|
| `publish.address` | The address scheme those paths are derived under — see below. |
|
|
578
597
|
|
|
579
598
|
**Both addresses are optional, independently.** A note that compiles into no
|
|
580
|
-
document has no `uuid`, and a package that ships compendiums and publishes
|
|
581
|
-
|
|
582
|
-
neither is guessed: inventing the missing one
|
|
583
|
-
exist, which is the silent dead link the manifest
|
|
599
|
+
document has no `uuid`, and a package that ships compendiums and publishes only
|
|
600
|
+
a homepage (`publish.site: homepage`) has no `path` on any entry — its notes are
|
|
601
|
+
not pages. Neither is an error, and neither is guessed: inventing the missing one
|
|
602
|
+
asserts a target that does not exist, which is the silent dead link the manifest
|
|
603
|
+
exists to prevent.
|
|
584
604
|
|
|
585
605
|
**`publish.manifests.publish` is a declaration, not a preference.** The file is
|
|
586
606
|
vendored by other repositories and read as authoritative, so emitting one is a
|
|
@@ -598,7 +618,7 @@ time and 404s for the reader.
|
|
|
598
618
|
|
|
599
619
|
```yaml
|
|
600
620
|
publish:
|
|
601
|
-
site:
|
|
621
|
+
site: content
|
|
602
622
|
manifests: { publish: true, consume: true }
|
|
603
623
|
address:
|
|
604
624
|
prefix: kb/ # default: "" — the package root
|
|
@@ -641,6 +661,64 @@ address derivation, the address index, table expansion, wikilink resolution,
|
|
|
641
661
|
code-fence protection, the foreign-manifest merge, the page emission and the
|
|
642
662
|
section-landing backfill.
|
|
643
663
|
|
|
664
|
+
### The homepage, and how much else is published
|
|
665
|
+
|
|
666
|
+
Every package is reachable at `https://www.heroiclands.org/<contentPackage>/`,
|
|
667
|
+
and what a reader finds there is a note in the content tree — one markdown file,
|
|
668
|
+
written by a person:
|
|
669
|
+
|
|
670
|
+
```markdown
|
|
671
|
+
---
|
|
672
|
+
type: homepage
|
|
673
|
+
title: HârnMaster Kethira Basic # optional; defaults to packageBuild.manifest.title
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
What the module is, which system it needs, how to install it.
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
That is the whole envelope. A homepage **compiles into no compendium
|
|
680
|
+
document**, appears in no pack and in no link manifest, and is addressed by the
|
|
681
|
+
_package_ rather than by its own name — so `name.full`, `shortcode` and `id`
|
|
682
|
+
decide nothing on it. It is dispatched on `type` like every other note, not on a
|
|
683
|
+
filename: `README.md` is already a section landing under `landing: readme`, and
|
|
684
|
+
in `sohl-thalorna` it is a developer explainer about the source tree.
|
|
685
|
+
|
|
686
|
+
`type: homepage` is declared by the **engine**, not by the `sohl` item registry,
|
|
687
|
+
so a package that configures no `itemBuilders` at all — `HarnMaster-3-FoundryVTT`
|
|
688
|
+
and every HM3 module — can author one. The `engine/` ÷ `sohl/` line is
|
|
689
|
+
note-format knowledge against game-system knowledge, and a homepage carries no
|
|
690
|
+
`system` block.
|
|
691
|
+
|
|
692
|
+
`publish.site` then says how much _else_ is published:
|
|
693
|
+
|
|
694
|
+
| Mode | What is published |
|
|
695
|
+
| ---------- | ------------------------------------------------------------------------------- |
|
|
696
|
+
| `homepage` | The authored homepage, and no other page. **The default, and the floor.** |
|
|
697
|
+
| `content` | The homepage plus every page the content tree compiles to, and its extra trees. |
|
|
698
|
+
|
|
699
|
+
There is no value meaning "no web presence": every package publishes its
|
|
700
|
+
homepage. It was a boolean until 5.0.0, and both spellings are now refused
|
|
701
|
+
naming the mode to write instead — see [MIGRATING.md](MIGRATING.md).
|
|
702
|
+
|
|
703
|
+
**Homepage-only is a first-class mode, not an accommodation.**
|
|
704
|
+
`sohl-kethira-basic` (unofficial Hârn fan material under Keléstia Productions'
|
|
705
|
+
Fan Material Guidelines) and `harn-adventures` (HârnFanon under Lythia's terms)
|
|
706
|
+
must each publish a homepage and nothing beneath it. The boundary is _published
|
|
707
|
+
content_ — journal text, artwork, item descriptions, compiled notes — and a page
|
|
708
|
+
announcing the module discloses none of it. Because the failure mode is silent,
|
|
709
|
+
the mode **fences the content surfaces off** rather than trusting a
|
|
710
|
+
configuration to stay empty: in `homepage` mode the tree is never walked for
|
|
711
|
+
pages, and `sections`, `trees`, `landing` and `backfillSections` emit nothing
|
|
712
|
+
even when they are declared.
|
|
713
|
+
|
|
714
|
+
That is separate from `publish.manifests.publish`, which stays off for both for
|
|
715
|
+
an unrelated reason: a link manifest is the dependency edge that would stop the
|
|
716
|
+
module being withdrawable, and a homepage is one row in a routing table.
|
|
717
|
+
|
|
718
|
+
The homepage is written at the root of `site.out` — the package's own address —
|
|
719
|
+
one level above the content mount, which is where `publish.address.prefix` puts
|
|
720
|
+
everything else.
|
|
721
|
+
|
|
644
722
|
**What it does not do is decide addresses.** Those come from `publish.address`,
|
|
645
723
|
the same setting the link manifest reads, so a page and its manifest entry cannot
|
|
646
724
|
disagree about where the page is. Everything under `site:` is _framing_ —
|
|
@@ -669,7 +747,7 @@ site:
|
|
|
669
747
|
|
|
670
748
|
| Key | What it decides |
|
|
671
749
|
| ------------------ | ------------------------------------------------------------------------------------------------ |
|
|
672
|
-
| `out` | The Hugo content root. **Required
|
|
750
|
+
| `out` | The Hugo content root. **Required** in both modes, and wiped on every run — see below. |
|
|
673
751
|
| `base` | Where the package is served. Defaults to `/<contentPackage>/`. |
|
|
674
752
|
| `packages` | Which content packages this site renders. Defaults to its own. |
|
|
675
753
|
| `sections` | Landing title and hero per section, so a landing matches the card that links to it. |
|
package/MIGRATING.md
CHANGED
|
@@ -1,3 +1,123 @@
|
|
|
1
|
+
# Migrating to `@heroiclands/package-build` 5.0.0
|
|
2
|
+
|
|
3
|
+
**One configuration change: `publish.site` is a mode, not a boolean.** And one
|
|
4
|
+
new authoring capability that needs no migration: a `type: homepage` note.
|
|
5
|
+
|
|
6
|
+
## 1. Respell `publish.site`
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
publish:
|
|
10
|
+
site: content # was `site: true`
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
publish:
|
|
15
|
+
site: homepage # was `site: false`, or absent
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`homepage` is the default, so a repository that never set the key needs no edit.
|
|
19
|
+
A repository that set it to either boolean gets a `TypeError` at load naming the
|
|
20
|
+
mode to write:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
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.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Both spellings are **refused rather than mapped** onto the nearest mode. `false`
|
|
27
|
+
read as _this package has no web presence_, which now describes no package at
|
|
28
|
+
all, and a value silently reinterpreted reads to its author as though it still
|
|
29
|
+
means what it said.
|
|
30
|
+
|
|
31
|
+
Nothing else about publishing moved: `publish.address`, `publish.manifests` and
|
|
32
|
+
the whole `site:` block are unchanged, and every address `sohl` and `thalorna`
|
|
33
|
+
already publish is byte-identical across the upgrade.
|
|
34
|
+
|
|
35
|
+
## 2. Author a homepage (optional here, required by #52)
|
|
36
|
+
|
|
37
|
+
Every package is reachable at `https://www.heroiclands.org/<contentPackage>/`,
|
|
38
|
+
and the page there is a note in the content tree:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
---
|
|
42
|
+
type: homepage
|
|
43
|
+
title: HârnMaster Kethira Basic # optional; defaults to packageBuild.manifest.title
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
What the module is, which system it needs, how to install it.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
It compiles into no compendium document, appears in no pack and in no link
|
|
50
|
+
manifest, and is addressed by the package rather than by its own name. It is
|
|
51
|
+
written to the root of `site.out`, one level above the content mount.
|
|
52
|
+
|
|
53
|
+
A repository with no homepage note publishes none, and the site build says so in
|
|
54
|
+
its count. Requiring exactly one is a separate change (#52).
|
|
55
|
+
|
|
56
|
+
## 3. What homepage-only means
|
|
57
|
+
|
|
58
|
+
`homepage` mode does not merely leave the content configuration unused — it
|
|
59
|
+
**fences the content surfaces off**. The tree is never walked for pages, and
|
|
60
|
+
`site.sections`, `site.trees`, `site.landing` and `site.backfillSections` emit
|
|
61
|
+
nothing even when they are declared.
|
|
62
|
+
|
|
63
|
+
That is deliberate, and it is a licensing requirement rather than a preference.
|
|
64
|
+
`sohl-kethira-basic` (Keléstia Productions' Fan Material Guidelines) and
|
|
65
|
+
`harn-adventures` (HârnFanon under Lythia's terms) publish a homepage and no
|
|
66
|
+
other page; the failure mode is silent — a `site:` block added later ships
|
|
67
|
+
licensed content with nobody noticing — so the property is asserted by the code
|
|
68
|
+
path rather than left to configuration.
|
|
69
|
+
|
|
70
|
+
`publish.manifests.publish` is a separate decision and stays `false` for both: a
|
|
71
|
+
link manifest is the dependency edge that would stop a module being withdrawable,
|
|
72
|
+
and a homepage is not.
|
|
73
|
+
|
|
74
|
+
# Migrating to `@heroiclands/package-build` 4.0.0
|
|
75
|
+
|
|
76
|
+
**One authoring change: delete `package:` from every content note.** A note's
|
|
77
|
+
package is the repository's configured `contentPackage`, and declaring the field
|
|
78
|
+
is now a build error rather than a redundancy the build tolerated.
|
|
79
|
+
|
|
80
|
+
## 1. Sweep the content tree
|
|
81
|
+
|
|
82
|
+
The field is a whole line, and nothing else reads it:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
find assets/content -name '*.md' -print0 | xargs -0 sed -i '' '/^package: /d'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
(GNU `sed`: `sed -i '/^package: /d'`.) Then compile — `content-build package
|
|
89
|
+
compile` must produce byte-identical output to the run before the sweep, because
|
|
90
|
+
the value the build derives is the value the notes restated.
|
|
91
|
+
|
|
92
|
+
A note that still carries the field fails the build where it is:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
assets/content/Gear/Axe.md:12:1: error: `package: sohl` is a retired frontmatter field — delete it. A note's package is this repository's configured `contentPackage` ("sohl", in package-build.config.yaml), and every note in the tree belongs to it.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`content-build lint` reports every one of them in a single pass, so the sweep can
|
|
99
|
+
be checked before it is compiled.
|
|
100
|
+
|
|
101
|
+
## 2. Nothing else
|
|
102
|
+
|
|
103
|
+
- **`contentPackage` stays**, and is unchanged. It is the address namespace —
|
|
104
|
+
the first segment of every canonical key, the name of the emitted link
|
|
105
|
+
manifest, and the package a cross-package wikilink writes. Every address in
|
|
106
|
+
every manifest is identical across this upgrade.
|
|
107
|
+
- **A generated table's `WHERE … and package = "<pkg>"` clause keeps matching.**
|
|
108
|
+
The package is synthesised into what the table search sees, from
|
|
109
|
+
`contentPackage`; it was never the authored field that answered the clause
|
|
110
|
+
after 3.3.0.
|
|
111
|
+
- **No configuration key changed**, and no CLI command, flag or exit code.
|
|
112
|
+
|
|
113
|
+
## What this replaced
|
|
114
|
+
|
|
115
|
+
A note used to be _selected_ by the field: it compiled when `package:` matched
|
|
116
|
+
`contentPackage` and was skipped, silently and as "belongs to another pass",
|
|
117
|
+
when it did not. A tree whose notes named a package no configuration answered to
|
|
118
|
+
compiled **zero notes and exited 0** (#56). 3.3.0 made the field optional so
|
|
119
|
+
every repository could be swept on a non-breaking version; this major removes it.
|
|
120
|
+
|
|
1
121
|
# Migrating to `@heroiclands/package-build` 3.0.0
|
|
2
122
|
|
|
3
123
|
`@heroiclands/content-build` and `@heroiclands/package-build` are one package.
|
package/bin/content-build.mjs
CHANGED
|
@@ -76,6 +76,9 @@ import { lintFrontmatter } from "../engine/frontmatter-lint.mjs";
|
|
|
76
76
|
// set — an adventure module ships skills, beings and magic swords — so no
|
|
77
77
|
// consumer gets a subset (#19, #20).
|
|
78
78
|
import { NOTE_SCHEMAS } from "../sohl/note-schemas.mjs";
|
|
79
|
+
// The engine's own types, merged under the registry's so the vocabulary stands
|
|
80
|
+
// in a package that configures no `itemBuilders` at all (#51).
|
|
81
|
+
import { ENGINE_NOTE_SCHEMAS } from "../engine/note-schemas.mjs";
|
|
79
82
|
import { checkFormatting, lintMarkdown } from "../engine/prose-lint.mjs";
|
|
80
83
|
import { emitLinkManifest } from "../engine/manifest-emit.mjs";
|
|
81
84
|
import {
|
|
@@ -346,7 +349,7 @@ function lintCommand() {
|
|
|
346
349
|
skipDirectories: config.skipDirectories,
|
|
347
350
|
});
|
|
348
351
|
const frontmatter = lintFrontmatter(index, {
|
|
349
|
-
schemas: NOTE_SCHEMAS,
|
|
352
|
+
schemas: { ...ENGINE_NOTE_SCHEMAS, ...NOTE_SCHEMAS },
|
|
350
353
|
references: argv.references,
|
|
351
354
|
});
|
|
352
355
|
|
|
@@ -823,7 +826,8 @@ function siteCommand() {
|
|
|
823
826
|
|
|
824
827
|
const s = result.stats;
|
|
825
828
|
log.info(
|
|
826
|
-
`wrote ${s.
|
|
829
|
+
`wrote ${s.homepages ?? 0} homepage(s) + ` +
|
|
830
|
+
`${s.content ?? 0} content page(s) + ` +
|
|
827
831
|
`${s.tree ?? 0} tree page(s) + ${s.landings} ` +
|
|
828
832
|
`landing(s) to ${path.relative(process.cwd(), s.out)}`,
|
|
829
833
|
);
|