@heroiclands/package-build 11.0.0 → 13.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 +279 -0
- package/CONTENT.md +96 -49
- package/MIGRATING.md +65 -0
- package/content-config.mjs +51 -22
- package/docs/content-format.md +51 -27
- package/engine/base-compiler.mjs +6 -1
- package/engine/content-address.mjs +24 -73
- package/engine/frontmatter-lint.mjs +92 -1
- package/engine/manifest-emit.mjs +16 -18
- package/engine/note-vocabulary.mjs +159 -1
- package/engine/retired-fields.mjs +76 -3
- package/engine/site-build.mjs +70 -78
- package/engine/site-index.mjs +20 -8
- package/engine/web-wikilinks.mjs +1 -1
- package/engine/wikilinks.mjs +1 -1
- package/package.json +1 -1
- package/types/content-config.d.mts +29 -17
- package/types/engine/content-address.d.mts +22 -34
- package/types/engine/note-vocabulary.d.mts +76 -0
- package/types/engine/retired-fields.d.mts +47 -0
- package/types/engine/site-build.d.mts +56 -31
- package/types/engine/site-index.d.mts +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,284 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 13.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 0c2def0: A section is a Hugo directory concept, and the note format no longer carries one
|
|
8
|
+
(#204). Content pages emit **flat** under the mount, named by their address; the
|
|
9
|
+
`README.md` landing convention, `sectionOf`, the `<section>/` output routing, and
|
|
10
|
+
the "no section, so nowhere to file the page" refusal are all gone.
|
|
11
|
+
|
|
12
|
+
**Why it goes.** Since #181 a page's URL _is_ its address,
|
|
13
|
+
`/<package>/<type>-<shortcode>/`, so a section appears in **no address at all**.
|
|
14
|
+
Its only remaining job was choosing the directory a page was written into, and
|
|
15
|
+
the only reason that mattered was Hugo's rule about what counts as a section —
|
|
16
|
+
`writeSectionLandings`'s own docstring said both of its jobs "exist because of
|
|
17
|
+
how Hugo decides what a section is". So the note format carried a filename
|
|
18
|
+
convention, a landing rule, a routing function and a refusal in order to satisfy
|
|
19
|
+
a rendering engine's directory semantics. #197 was the bill for that: `subType`
|
|
20
|
+
did double duty — a genre for an ordinary `doc`, a URL section for a `README` —
|
|
21
|
+
the two vocabularies collided, and it took #198, #200, #201 and a release to
|
|
22
|
+
settle by widening one of them rather than by removing the overload.
|
|
23
|
+
|
|
24
|
+
**A page that introduces the notes of a type is now an ordinary note**, named by
|
|
25
|
+
convention and with no build path of its own: `type: doc`, `subType: reference`,
|
|
26
|
+
`shortcode: <type>`, addressed `doc-<type>`. The package's own front page already
|
|
27
|
+
worked this way (`homepage-root`, #182).
|
|
28
|
+
|
|
29
|
+
| Surface | Before | After |
|
|
30
|
+
| -------------------------------------- | --------------------------------------------- | ------------------------------------------------- |
|
|
31
|
+
| A content page's file | `<mount>/<section>/<type>-<shortcode>.md` | `<mount>/<type>-<shortcode>.md` |
|
|
32
|
+
| A content page's `url:` | `/<package>/<type>-<shortcode>/` | **unchanged** |
|
|
33
|
+
| A `README.md` in the content tree | its section's landing, addressed `<section>/` | an ordinary page, addressed `<type>-<shortcode>/` |
|
|
34
|
+
| A `doc` with no `subType` | refused — "no section" | published, at `doc-<shortcode>/` |
|
|
35
|
+
| A `doc`'s `subType` | a genre, or a section address on a `README` | a genre, closed to what the type declares |
|
|
36
|
+
| `packageAddress(fm, { isReadme })` | branched on the filename | a pure function of the frontmatter |
|
|
37
|
+
| `sectionOf` | exported | removed |
|
|
38
|
+
| `declaredSections` | exported, fed the lint | removed — it had no other reader |
|
|
39
|
+
| `lintNote` / `lintFrontmatter` options | `landing`, `types`, `sections` | removed |
|
|
40
|
+
|
|
41
|
+
**The closed-set check becomes meaningful again.** #206, released alongside this,
|
|
42
|
+
put a retired-spelling warning and an address-charset error ahead of it in
|
|
43
|
+
`checkSubType`; removing the section branch from underneath leaves three checks
|
|
44
|
+
in one order — retired spelling, then charset, then the genres the type declares
|
|
45
|
+
— with nothing widening the last of them. A `doc` note whose `subType` names a
|
|
46
|
+
content type is refused again, `README` or not.
|
|
47
|
+
|
|
48
|
+
**`site.sections` is not retired — it is now the whole of what a section is.**
|
|
49
|
+
With no page filed into `<section>/`, nothing else makes
|
|
50
|
+
`/<package>/<prefix><section>/` exist at all, so `writeSectionLandings` stays and
|
|
51
|
+
its role changes from backfilling directories that pages created to _declaring_
|
|
52
|
+
the Hugo sections a site wants. Two consequences follow for a consuming site:
|
|
53
|
+
|
|
54
|
+
- **Declare every section the site links to.** A card, menu entry or breadcrumb
|
|
55
|
+
pointing at an undeclared section is a 404.
|
|
56
|
+
- **A section landing lists no child pages.** Its directory holds only its own
|
|
57
|
+
`_index.md`, so a layout reading `.Pages` finds nothing; one that queries
|
|
58
|
+
`site.RegularPages` by `Params.type` is unaffected, and that is the shape a
|
|
59
|
+
content catalog wants anyway — it groups by what a page _is_, not by where its
|
|
60
|
+
file happened to be written.
|
|
61
|
+
|
|
62
|
+
**`publish.address.landing` is inert, and still accepted.** Both publishing
|
|
63
|
+
consumers declare `landing: readme`, which stated something true when they wrote
|
|
64
|
+
it; refusing it now would break them over a correct statement, and silently
|
|
65
|
+
ignoring it would be worse. It selects nothing and is deleted once no
|
|
66
|
+
configuration writes it — the third step, and a separate change. The retired
|
|
67
|
+
`collection` value stays refused by name (#202).
|
|
68
|
+
|
|
69
|
+
**Migration.** No note edit is required, and **no published URL moves** — an
|
|
70
|
+
address never contained a section. What a consuming site must check is its
|
|
71
|
+
layouts and its `site.sections`, per the two consequences above. Verified against
|
|
72
|
+
`sohl`, `sohl-thalorna` and `sohl-kethira-basic` at `origin/main`: `lint`,
|
|
73
|
+
`links`, `manifest` and `package compile` are byte-identical for all three (both
|
|
74
|
+
link manifests and every compiled pack document), and `sohl`'s emitted site is
|
|
75
|
+
byte-identical page for page, keyed by URL — all 1,606 addresses unchanged, 1,670
|
|
76
|
+
of 1,671 files identical. The one difference is a backfilled `kb/macro/_index.md`
|
|
77
|
+
that no longer exists, `macro` being the one section `sohl` did not declare;
|
|
78
|
+
nothing in its site or the shared theme links it.
|
|
79
|
+
|
|
80
|
+
## 12.0.0
|
|
81
|
+
|
|
82
|
+
### Major Changes
|
|
83
|
+
|
|
84
|
+
- ab34b1c: Retire the `collection` landing rule, the `section:` frontmatter key it read,
|
|
85
|
+
and the `collection` doc subtype that selected it (#202). A section is landed by
|
|
86
|
+
the `README.md` in its directory, and that is now the only rule.
|
|
87
|
+
|
|
88
|
+
**Why it goes.** Every publishing tree had already migrated: no note in `sohl`,
|
|
89
|
+
`sohl-thalorna` or `sohl-kethira-basic` declares `section:` or writes
|
|
90
|
+
`subType: collection`, and both publishing consumers configure `landing: readme`.
|
|
91
|
+
What was left was not merely unused but **unimplemented on one of the two sides
|
|
92
|
+
that must agree**. `engine/content-address.mjs` branched on the configured rule;
|
|
93
|
+
`engine/site-build.mjs` never read it — it derives `isReadme` from the basename
|
|
94
|
+
and treats a `README.md` as a landing whatever the configuration says. So under
|
|
95
|
+
`landing: collection` the link manifest and the emitted site would have disagreed
|
|
96
|
+
about where a page is, which is the single failure the shared address function
|
|
97
|
+
exists to prevent. With one rule they agree by construction.
|
|
98
|
+
|
|
99
|
+
**`landing: collection` is refused, not merely unrecognized.** Reported as a bad
|
|
100
|
+
value it would read as a misspelling of the rule that survives, and an author
|
|
101
|
+
would correct the value rather than learn that the mechanism is gone. The
|
|
102
|
+
diagnostic names the key, says the rule is retired, says a section is landed by
|
|
103
|
+
its `README.md`, and says the `section:` key went with it — located to the line
|
|
104
|
+
and column in `package-build.config.yaml`, as every configuration finding is.
|
|
105
|
+
|
|
106
|
+
**`section:` is refused the way `draft:`, `package:` and `aliases:` are.** It had
|
|
107
|
+
exactly one reader — the retired branch — and no schema or vocabulary declared
|
|
108
|
+
it, so nothing checked it: left in place it would be _ignored_, which reads to
|
|
109
|
+
its author as though it still works. It is now reported by `content-build lint`
|
|
110
|
+
and refused at compile, with the file, line and column.
|
|
111
|
+
|
|
112
|
+
| Surface | Before | After |
|
|
113
|
+
| -------------------------------- | ------------------------------------- | -------------------------------------- |
|
|
114
|
+
| `publish.address.landing` | `readme` \| `collection` | `readme` — the value is still accepted |
|
|
115
|
+
| `section:` in a note | read under `collection`, else ignored | refused, at lint and at compile |
|
|
116
|
+
| `subType: collection` on a `doc` | selected the rule | not a subtype the format declares |
|
|
117
|
+
| `LANDING_RULES` | `["readme", "collection"]` | `["readme"]` |
|
|
118
|
+
|
|
119
|
+
**Migration.** Delete `landing: collection` from `publish.address` — or write
|
|
120
|
+
`landing: readme` — and make each section's landing the `README.md` in its
|
|
121
|
+
directory. Delete any `section:` a note still carries. A repository that already
|
|
122
|
+
configures `landing: readme` and writes no `section:` needs no change: `lint`,
|
|
123
|
+
`links` and `site` were verified byte-identical against `sohl`, `sohl-thalorna`
|
|
124
|
+
and `sohl-kethira-basic` at `origin/main`, including all 1,657 pages `sohl`
|
|
125
|
+
emits.
|
|
126
|
+
|
|
127
|
+
**`publish.address.landing` itself survives, for now.** It is the key both
|
|
128
|
+
publishing consumers declare, and refusing a correct `landing: readme` would
|
|
129
|
+
break them over a statement that is still true. With one rule it selects nothing,
|
|
130
|
+
so it is a candidate for deletion once no configuration writes it — the third
|
|
131
|
+
step `package:` took (#56), and a separate change.
|
|
132
|
+
|
|
133
|
+
### Minor Changes
|
|
134
|
+
|
|
135
|
+
- ed06be0: Hold `type` and `subType` to the address charset, and rename a `doc`'s
|
|
136
|
+
`user-guide` subtype to `userguide` (#206).
|
|
137
|
+
|
|
138
|
+
**The rule.** An address is `package-type-shortcode`, read back by counting
|
|
139
|
+
hyphen-separated segments, and that is sound for exactly one reason: no segment
|
|
140
|
+
may contain a hyphen. `ADDRESS_SEGMENT_PATTERN` (`^[A-Za-z0-9]+$`) stated it and
|
|
141
|
+
`SHORTCODE_PATTERN` aliased it, but only a **shortcode** was checked against it.
|
|
142
|
+
The other two values that reach an address were not: a `type` is the first
|
|
143
|
+
segment of every address, and a `doc`'s `subType` is the section it routes to —
|
|
144
|
+
a path segment of its own, and, under #204, a shortcode. Both are now held to
|
|
145
|
+
the same constant, read rather than restated; a third spelling of one rule is how
|
|
146
|
+
the disagreements found in #202 and #203 happened.
|
|
147
|
+
|
|
148
|
+
**The diagnostic** is located where the value was written, in the standard form:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
assets/content/Beings/Folk.md:3:1: error: `subType` "common-folk" is not an address segment — a subType is letters and digits only (^[A-Za-z0-9]+$), the same charset a shortcode is held to. …
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The charset is checked **ahead of** the closed-set check, which is what makes it
|
|
155
|
+
reach a type whose `subTypes` are declared but not yet enumerated (`being`) —
|
|
156
|
+
values nothing may otherwise claim to check.
|
|
157
|
+
|
|
158
|
+
**`user-guide` became `userguide`**, the one declared value that broke the rule
|
|
159
|
+
and the only hyphenated `type` or `subType` in the vocabulary. A hyphenated
|
|
160
|
+
declaration can no longer be imported at all: the registry is checked against the
|
|
161
|
+
charset as `engine/note-vocabulary.mjs` loads.
|
|
162
|
+
|
|
163
|
+
**The old spelling is accepted for one release, and says so.** A `doc` written
|
|
164
|
+
`subType: user-guide` is reported as a **warning** naming the note, the retired
|
|
165
|
+
value and its replacement, and the note still compiles:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
User_Guide/Actions.md:3:1: warning: `subType` "user-guide" is a retired spelling of "userguide" on a doc; write "userguide". …
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
_The ordering is the reverse of the usual, deliberately._ For a retired field the
|
|
172
|
+
sweep goes first; here it must go last. 43 `sohl` notes author `user-guide`
|
|
173
|
+
today, and declaring only the new spelling would invalidate all 43 with a release
|
|
174
|
+
they had no chance to sweep ahead of. So the acceptance ships first, consumers
|
|
175
|
+
rename, and a later change removes the acceptance — at which point the old
|
|
176
|
+
spelling falls through to the ordinary undeclared-value error with no code left
|
|
177
|
+
to remove. That later change is the breaking one; this one breaks nothing, which
|
|
178
|
+
is why it is a minor.
|
|
179
|
+
|
|
180
|
+
**`type` gets no transitional path**, deliberately: no note in `sohl`,
|
|
181
|
+
`sohl-thalorna` or `sohl-kethira-basic` authors a hyphenated type, so an
|
|
182
|
+
acceptance would be dead code guarding a case that does not exist. Measured
|
|
183
|
+
against a pristine `origin/main` extraction of each tree, the only hyphenated
|
|
184
|
+
value of either key anywhere is the 43 `user-guide` notes.
|
|
185
|
+
|
|
186
|
+
## 11.1.0
|
|
187
|
+
|
|
188
|
+
### Minor Changes
|
|
189
|
+
|
|
190
|
+
- 8906d7a: **A `README` landing's `subType` is checked against the sections the repository declares, not the genre list.**
|
|
191
|
+
|
|
192
|
+
Two vocabularies were spelled with one key. For every note, `subType` is a
|
|
193
|
+
sub-kind of its type, checked against a closed list. For a `README` under
|
|
194
|
+
`publish.address.landing: readme` it is additionally the **URL section** —
|
|
195
|
+
`sectionOf` reads a `doc`'s `subType` as the segment the landing addresses — and
|
|
196
|
+
that is an open set the consuming repository names in `site.sections` /
|
|
197
|
+
`site.readmeSections`. `engine/frontmatter-lint.mjs` applied the closed reading
|
|
198
|
+
while `engine/content-address.mjs` applied the open one, so the two halves of the
|
|
199
|
+
toolchain disagreed about the same note: `content-build site` addressed and
|
|
200
|
+
published `Weapons/README.md` at `weapongear/`, and `content-build lint` refused
|
|
201
|
+
it because `doc` declares only `rules`, `user-guide` and `reference`. An item
|
|
202
|
+
section's landing was not expressible.
|
|
203
|
+
|
|
204
|
+
The check now widens **for a landing only**, and only under `landing: readme`: a
|
|
205
|
+
`README` whose `subType` is its section may name any section the repository
|
|
206
|
+
declares, as well as any of its type's own genres — a genre is a section a `doc`
|
|
207
|
+
tree publishes under whether or not the repository describes it, so narrowing to
|
|
208
|
+
the configured set alone would refuse a correct `README`. An ordinary note's
|
|
209
|
+
`subType` stays closed to its type's genres, unchanged.
|
|
210
|
+
|
|
211
|
+
**The guard survives**, checked against the set that actually decides where the
|
|
212
|
+
page goes:
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
Weapons/README.md:4:1: error: `subType` "weapongeer" is the section this README
|
|
216
|
+
lands at, and nothing declares it: it is neither a section this repository
|
|
217
|
+
configures under `site.sections` / `site.readmeSections` (rules, user-guide,
|
|
218
|
+
weapongear, …) nor one of the subtypes doc declares (rules, user-guide,
|
|
219
|
+
reference). Did you mean "weapongear"?
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Whether the value is an address is asked of `sectionOf` rather than by naming a
|
|
223
|
+
type, so the linter still knows no type names of its own; the section list is
|
|
224
|
+
read from the resolved configuration the site build renders those landings from,
|
|
225
|
+
through a new `declaredSections(config)`, so neither can name a section the other
|
|
226
|
+
does not.
|
|
227
|
+
|
|
228
|
+
_Minor rather than patch_: `lintNote` and `lintFrontmatter` take two new
|
|
229
|
+
options (`landing`, `sections`) and `content-config.mjs` exports
|
|
230
|
+
`declaredSections`. Both options default to today's behaviour, so a caller that
|
|
231
|
+
passes neither — and a repository that declares no sections — is unaffected.
|
|
232
|
+
|
|
233
|
+
Closes #197
|
|
234
|
+
|
|
235
|
+
### Patch Changes
|
|
236
|
+
|
|
237
|
+
- 68910b6: **A `README` landing may name any section that exists, not only a configured one.**
|
|
238
|
+
|
|
239
|
+
#197 widened a landing's `subType` check by one term and it was the wrong one:
|
|
240
|
+
the sections the repository configures in `site.sections` /
|
|
241
|
+
`site.readmeSections`. That keys on configuration a consumer may legitimately not
|
|
242
|
+
have. `sohl-thalorna` has **no `site:` block at all** — it renders its site
|
|
243
|
+
through a local fork of the emitter — so `declaredSections` answered `[]`, the
|
|
244
|
+
accepted set collapsed back to the three `doc` genres, and five of its landings
|
|
245
|
+
were still refused for naming their own content type:
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
assets/content/Characters/README.md:7:1: error: `subType` "being" is not one of the subtypes doc declares (rules, user-guide, reference)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
A landing's `subType` is an **address**, so it is now checked against the
|
|
252
|
+
addresses that exist — the range of `sectionOf` over every note the format
|
|
253
|
+
permits, plus whatever the repository names:
|
|
254
|
+
|
|
255
|
+
1. **Every content type the specification declares.** `sectionOf` returns
|
|
256
|
+
`fm.type` for a non-`doc` note, so `being`, `lore`, `scenario` and
|
|
257
|
+
`weapongear` are sections _by construction_, configured or not.
|
|
258
|
+
2. **The type's own subtypes** — `rules`, `user-guide`, `reference`.
|
|
259
|
+
3. **The configured sections**, which may name one that is neither: `sohl` has
|
|
260
|
+
`credits` and `dev-docs`.
|
|
261
|
+
|
|
262
|
+
**The guard survives.** A misspelling is in none of the three, so it still fails,
|
|
263
|
+
and the near miss is drawn from the whole union. What is deliberately no longer
|
|
264
|
+
caught is a landing for a section that exists but is currently empty — which is
|
|
265
|
+
legitimate, and is why the set is the types the format _declares_ rather than
|
|
266
|
+
those _present in the tree_: `sohl` ships two such landings above tables that
|
|
267
|
+
stay empty until the first note of each type does.
|
|
268
|
+
|
|
269
|
+
**The type list is the specification's, not the schema map's.** `NOTE_SCHEMAS`
|
|
270
|
+
declares 18 types and `docs/content-format.md` declares 23; `lore`, `place`,
|
|
271
|
+
`scenario`, `vehicle` and `armorlocation` are in the second only. Checking an
|
|
272
|
+
address against the schema map would refuse `Lore/README.md` for a reason that
|
|
273
|
+
is not about addresses, and would report one gap twice in two vocabularies.
|
|
274
|
+
Whether a note's fields can be checked is a different question, answered
|
|
275
|
+
elsewhere and reported on the notes themselves.
|
|
276
|
+
|
|
277
|
+
`lintNote` / `lintFrontmatter` take a `types` option beside `sections`; both
|
|
278
|
+
default to empty, so a caller that passes neither is unaffected.
|
|
279
|
+
|
|
280
|
+
Closes #200
|
|
281
|
+
|
|
3
282
|
## 11.0.0
|
|
4
283
|
|
|
5
284
|
### Major Changes
|
package/CONTENT.md
CHANGED
|
@@ -796,6 +796,26 @@ values. A `weapon` declares none — SoHL distinguishes a weapon's uses by strik
|
|
|
796
796
|
mode rather than by kind — so `subType` on one is a finding; a `skill` declares
|
|
797
797
|
ten, so `subType: crafte` is a finding naming `craft`.
|
|
798
798
|
|
|
799
|
+
**A `type` and a `subType` are both held to `^[A-Za-z0-9]+$`** (#206) — the same
|
|
800
|
+
constant a `shortcode` is held to, read rather than restated. A type is the
|
|
801
|
+
first segment of every address, so a hyphen in one is read back as a segment
|
|
802
|
+
boundary nobody wrote. A `subType` reaches no address since #204 retired
|
|
803
|
+
sections, and keeps the rule anyway: it is a vocabulary term the toolchain keys
|
|
804
|
+
on, and one charset that holds for every term is a rule an author can state. The
|
|
805
|
+
rule is checked ahead of the closed-set check, which is what makes it reach a
|
|
806
|
+
type whose values are declared but not yet enumerated:
|
|
807
|
+
|
|
808
|
+
```text
|
|
809
|
+
assets/content/Beings/Folk.md:3:1: error: `subType` "common-folk" is not an address segment — a subType is letters and digits only (^[A-Za-z0-9]+$), the same charset a shortcode is held to. …
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
One declared value broke that rule: a `doc`'s `user-guide`, now **`userguide`**.
|
|
813
|
+
The old spelling is accepted for one transitional release and reported as a
|
|
814
|
+
**warning** naming the replacement — an error would red every tree that took the
|
|
815
|
+
release before it had a chance to sweep, and the note still compiles to the
|
|
816
|
+
correct page. A later release removes the acceptance, and the old spelling then
|
|
817
|
+
falls through to the ordinary undeclared-value error.
|
|
818
|
+
|
|
799
819
|
The vocabulary lives in `engine/note-vocabulary.mjs`, one entry per note type,
|
|
800
820
|
taken from the content-format specification. It is note-format knowledge rather
|
|
801
821
|
than any system's: `data:` holds what is true of the thing, and what a system
|
|
@@ -1206,15 +1226,24 @@ package's fixed mounts (`/<package>/` for the landing page, `/<package>/api/` fo
|
|
|
1206
1226
|
generated API docs), neither of which contains a hyphen or names a type. So the
|
|
1207
1227
|
namespace is provably disjoint rather than conventionally so.
|
|
1208
1228
|
|
|
1209
|
-
**
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1229
|
+
**A page is written flat, named by its address** (#204). It used to be filed
|
|
1230
|
+
into `<section>/`, because Hugo derives a page's section from where the file is
|
|
1231
|
+
written and a section gave it a landing page, `.CurrentSection` and a per-section
|
|
1232
|
+
layout lookup. But a section appears in no address, so the note format was
|
|
1233
|
+
carrying a key, a filename convention, a landing rule and a synthesis pass in
|
|
1234
|
+
order to satisfy a rendering engine's directory semantics. The file is now
|
|
1235
|
+
`<mount>/<type>-<shortcode>.md` and the front-matter `url:` still publishes it at
|
|
1236
|
+
the package root, one level above.
|
|
1237
|
+
|
|
1238
|
+
**There is no landing page.** A `README.md` was its section's landing and
|
|
1239
|
+
addressed the section itself; that is retired with the section. A page that
|
|
1240
|
+
introduces the notes of a type is an ordinary note addressed `doc-<type>`, with
|
|
1241
|
+
no build path of its own — exactly as the package's own front page is
|
|
1242
|
+
`homepage-root` (#182).
|
|
1243
|
+
|
|
1244
|
+
**Sections stay, as configuration.** `site.sections` still writes an `_index.md`
|
|
1245
|
+
per section, and that is now the _only_ thing that makes one exist — see
|
|
1246
|
+
[What a section may declare](#what-a-section-may-declare).
|
|
1218
1247
|
|
|
1219
1248
|
### The address scheme
|
|
1220
1249
|
|
|
@@ -1231,33 +1260,35 @@ publish:
|
|
|
1231
1260
|
manifests: { publish: true, consume: true }
|
|
1232
1261
|
address:
|
|
1233
1262
|
prefix: kb/ # default: "" — the package root
|
|
1234
|
-
landing: readme #
|
|
1263
|
+
landing: readme # inert since #204; still accepted
|
|
1235
1264
|
```
|
|
1236
1265
|
|
|
1237
|
-
- **`prefix`** — the content tree's mount within the package:
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
- **`landing`** —
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1266
|
+
- **`prefix`** — the content tree's mount within the package: the Hugo directory
|
|
1267
|
+
its pages are written under. `sohl` publishes a knowledgebase alongside
|
|
1268
|
+
generated API docs, so its tree sits under `kb/` while its pages address the
|
|
1269
|
+
package root (`affliction-aconite/`); `thalorna`'s site is nothing but its
|
|
1270
|
+
content, so it has no prefix. It must end in a slash and must not begin with
|
|
1271
|
+
one — where the _package_ is mounted is the consuming build's knowledge and is
|
|
1272
|
+
never recorded here.
|
|
1273
|
+
- **`landing`** — **inert, and accepted only so it keeps loading.** It named
|
|
1274
|
+
which note addressed a whole section rather than a page within one. There are
|
|
1275
|
+
no sections in the note format (#204) and so no landings, so it selects
|
|
1276
|
+
nothing; it is still accepted because both publishing consumers declare
|
|
1277
|
+
`landing: readme` and refusing a correct statement would break them. It is
|
|
1278
|
+
removed once no configuration writes it. The retired second rule, `collection`,
|
|
1279
|
+
is still refused by name (#202), along with the `collection` subtype and the
|
|
1280
|
+
top-level `section:` key.
|
|
1281
|
+
|
|
1282
|
+
A note's `subType` is checked against the values its type declares, and only
|
|
1283
|
+
those. It briefly had a second reading — a `README` landing's `subType` was the
|
|
1284
|
+
_address_ it landed at, so the closed genre list could not answer for it (#197,
|
|
1285
|
+
#198, #200, #201) — and #204 removed the cause rather than widening the
|
|
1286
|
+
vocabulary again.
|
|
1287
|
+
|
|
1288
|
+
The only note the scheme yields no address for is one carrying no `shortcode`.
|
|
1289
|
+
It is **reported and omitted**, never guessed: the command prints one located
|
|
1290
|
+
diagnostic per note and still writes the file, because a note with no address is
|
|
1291
|
+
ordinary while a manifest entry pointing at a page that does not exist is not.
|
|
1261
1292
|
|
|
1262
1293
|
## Publishing a website
|
|
1263
1294
|
|
|
@@ -1270,7 +1301,7 @@ The sibling of `package compile`: the same content tree, rendered as pages
|
|
|
1270
1301
|
instead of compiled into packs. It does the walk, the frontmatter read, the
|
|
1271
1302
|
address derivation, the address index, table expansion, wikilink resolution,
|
|
1272
1303
|
code-fence protection, the foreign-manifest merge, the page emission and the
|
|
1273
|
-
section-landing
|
|
1304
|
+
section-landing synthesis.
|
|
1274
1305
|
|
|
1275
1306
|
### The homepage, and how much else is published
|
|
1276
1307
|
|
|
@@ -1300,8 +1331,9 @@ still refuses `id`. Everything else about its address is ordinary: it declares a
|
|
|
1300
1331
|
[The homepage is addressed like every other note](#the-homepage-is-addressed-like-every-other-note)).
|
|
1301
1332
|
`/<contentPackage>/` itself is a redirect the package authors, not a page this
|
|
1302
1333
|
build writes. It is dispatched on `type` like every other note, not on a
|
|
1303
|
-
filename
|
|
1304
|
-
|
|
1334
|
+
filename — nothing in this format is decided by a file's name, which is why
|
|
1335
|
+
`sohl-thalorna` can keep a `README.md` in its content tree as a developer
|
|
1336
|
+
explainer about the source tree.
|
|
1305
1337
|
|
|
1306
1338
|
`type: homepage` is declared by the **engine**, not by the `sohl` item registry,
|
|
1307
1339
|
so a package that configures no `itemBuilders` at all — `HarnMaster-3-FoundryVTT`
|
|
@@ -1338,8 +1370,8 @@ module being withdrawable, and a homepage is one row in a routing table.
|
|
|
1338
1370
|
The homepage's file is written at the root of `site.out` — the package's own
|
|
1339
1371
|
site root, one level above the content mount, which is where
|
|
1340
1372
|
`publish.address.prefix` puts everything else — under the name its address gives
|
|
1341
|
-
it, `homepage-root.md`. As with every other page, the
|
|
1342
|
-
|
|
1373
|
+
it, `homepage-root.md`. As with every other page, the front matter's `url`
|
|
1374
|
+
decides where it publishes.
|
|
1343
1375
|
|
|
1344
1376
|
**What it does not do is decide addresses.** Those come from `publish.address`,
|
|
1345
1377
|
the same setting the link manifest reads, so a page and its manifest entry cannot
|
|
@@ -1375,20 +1407,33 @@ site:
|
|
|
1375
1407
|
| `out` | The Hugo content root. **Required** in both modes, and wiped on every run — see below. |
|
|
1376
1408
|
| `base` | Where the package is served. Defaults to `/<contentPackage>/`. |
|
|
1377
1409
|
| `packages` | Which content packages this site renders. Defaults to its own. |
|
|
1378
|
-
| `sections` |
|
|
1379
|
-
| `readmeSections` | The same, for a
|
|
1410
|
+
| `sections` | The Hugo sections this site declares, and what each says about itself — see below. |
|
|
1411
|
+
| `readmeSections` | The same, for a `trees` entry, whose landing comes from its own `README`. |
|
|
1380
1412
|
| `landing` | Frontmatter for the mount's own `_index.md`. Passed through — the vocabulary is the theme's. |
|
|
1381
|
-
| `backfillSections` | Write a bare `_index.md` for any other
|
|
1413
|
+
| `backfillSections` | Write a bare `_index.md` for any other directory directly under the mount. |
|
|
1382
1414
|
| `trees` | Extra source trees published beside the content, preserving their source layout below a section. |
|
|
1383
1415
|
| `pass` | A named bundle of this repository's own body rewrites. |
|
|
1384
1416
|
| `passOptions` | That bundle's options. |
|
|
1385
1417
|
|
|
1386
1418
|
### What a section may declare
|
|
1387
1419
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1420
|
+
**`sections` is what a section _is_ now** (#204). A content page is addressed
|
|
1421
|
+
`(type, shortcode)` and written flat under the mount, so no page creates a
|
|
1422
|
+
directory and nothing else makes `/<package>/<prefix><section>/` answer at all.
|
|
1423
|
+
A site that wants that address says so here, and this build writes the
|
|
1424
|
+
`_index.md` that makes Hugo agree it is a section.
|
|
1425
|
+
|
|
1426
|
+
Two consequences follow, and neither is optional:
|
|
1427
|
+
|
|
1428
|
+
- **Declare every section the site links to.** A card, a menu entry or a
|
|
1429
|
+
breadcrumb pointing at a section nobody declared is a 404.
|
|
1430
|
+
- **A section landing lists no child pages.** Its directory holds only its own
|
|
1431
|
+
`_index.md`, so a layout reading `.Pages` finds nothing. A layout that queries
|
|
1432
|
+
`site.RegularPages` by `Params.type` is unaffected, and that is the shape a
|
|
1433
|
+
content catalog wants anyway — it groups by what a page _is_, not by where its
|
|
1434
|
+
file happened to be written.
|
|
1435
|
+
|
|
1436
|
+
Whatever the entry may carry is the whole of what the section can say.
|
|
1392
1437
|
|
|
1393
1438
|
| Key | Required | What it does |
|
|
1394
1439
|
| ------------- | -------- | ------------------------------------------------------------------------- |
|
|
@@ -1396,9 +1441,11 @@ whatever that entry may carry is the whole of what the section can say.
|
|
|
1396
1441
|
| `banner` | no | The hero image, resolved as a CDN asset like any other `banner:`. |
|
|
1397
1442
|
| `description` | no | The hero standfirst under the heading, and the blurb a landing card uses. |
|
|
1398
1443
|
|
|
1399
|
-
`readmeSections` takes the same three, for a
|
|
1400
|
-
|
|
1401
|
-
|
|
1444
|
+
`readmeSections` takes the same three, for a **`trees`** entry: those pages keep
|
|
1445
|
+
their source layout below a named section, so the tree's own `README.md` is that
|
|
1446
|
+
section's landing. What the section declares wins over what the `README` happens
|
|
1447
|
+
to carry — the landing has to match the card that links to it. No content note
|
|
1448
|
+
reaches this map any more.
|
|
1402
1449
|
|
|
1403
1450
|
**The vocabulary is closed, and a key outside it is refused by name:**
|
|
1404
1451
|
|
package/MIGRATING.md
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
+
# Migrating to `@heroiclands/package-build` 12.0.0
|
|
2
|
+
|
|
3
|
+
**No note edit, no URL change, and one thing to check in the Hugo layer.** A
|
|
4
|
+
section is a Hugo directory concept that the note format no longer carries
|
|
5
|
+
(#204): content pages are written **flat** under the content mount, named by
|
|
6
|
+
their address, instead of into a `<section>/` directory.
|
|
7
|
+
|
|
8
|
+
## 1. Nothing in the content tree changes
|
|
9
|
+
|
|
10
|
+
A page's address never contained a section, so **no published URL moves**. A
|
|
11
|
+
`README.md` in the content tree stops being its section's landing and becomes an
|
|
12
|
+
ordinary page addressed `<type>-<shortcode>/` like every other note; if a tree
|
|
13
|
+
still has one that was serving as a landing, it now publishes at its own address.
|
|
14
|
+
No tree in this project had one.
|
|
15
|
+
|
|
16
|
+
A `doc` with no `subType` used to be refused ("no section, so there is nowhere to
|
|
17
|
+
file the page") and now publishes. Its `subType` is a **genre** again — closed to
|
|
18
|
+
`rules`, `userguide`, `reference` — because it no longer doubles as a section
|
|
19
|
+
address on a `README`. That closed check runs after the two #206 added ahead of
|
|
20
|
+
it: a retired spelling is a warning naming its replacement, a hyphenated value
|
|
21
|
+
is an error, and only then is the type's own list the reason.
|
|
22
|
+
|
|
23
|
+
## 2. Declare every section your site links to
|
|
24
|
+
|
|
25
|
+
`site.sections` is now the whole of what a section is. No page is filed into a
|
|
26
|
+
section directory any more, so nothing else makes `/<package>/<prefix><section>/`
|
|
27
|
+
exist:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
site:
|
|
31
|
+
sections:
|
|
32
|
+
being: { title: Beings, banner: banners/creature.webp }
|
|
33
|
+
weapongear: { title: Weapons, banner: banners/weapons.webp }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A card, menu entry or breadcrumb pointing at a section nobody declares is a 404.
|
|
37
|
+
|
|
38
|
+
## 3. Check how a section landing lists its members
|
|
39
|
+
|
|
40
|
+
A declared section's directory holds only its own `_index.md`, so a layout
|
|
41
|
+
reading `.Pages` renders an empty listing. Query the site instead, on the page's
|
|
42
|
+
own `type`:
|
|
43
|
+
|
|
44
|
+
```go-html-template
|
|
45
|
+
{{- $pages := where site.RegularPages "Type" "weapongear" -}}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That is the shape a content catalog wants regardless — it groups by what a page
|
|
49
|
+
_is_ rather than by where its file happened to be written — and it is what
|
|
50
|
+
`sohl`'s catalog layouts already do.
|
|
51
|
+
|
|
52
|
+
## 4. `publish.address.landing` is inert, and still accepted
|
|
53
|
+
|
|
54
|
+
It named which note addressed a whole section. There are no landings, so it
|
|
55
|
+
selects nothing; `landing: readme` keeps loading because it stated something true
|
|
56
|
+
when it was written, and the key is removed once no configuration declares it.
|
|
57
|
+
`landing: collection` is still refused by name (#202).
|
|
58
|
+
|
|
59
|
+
## What did not change
|
|
60
|
+
|
|
61
|
+
- Every content page's `url:`, and so every published address.
|
|
62
|
+
- Every link-manifest entry, including each entry's `path`.
|
|
63
|
+
- Every compiled compendium document.
|
|
64
|
+
- `site.sections` / `site.readmeSections` and what an entry may declare.
|
|
65
|
+
|
|
1
66
|
# Migrating to `@heroiclands/package-build` 11.0.0
|
|
2
67
|
|
|
3
68
|
**Two edits, and the second is one line per repository.** Every published page
|