@heroiclands/package-build 20.3.0 → 20.4.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 +97 -0
- package/CONTENT.md +111 -92
- package/README.md +2 -9
- package/bin/content-build.mjs +70 -61
- package/bin/package-build.mjs +2 -2
- package/config.mjs +6 -8
- package/content-config.mjs +187 -64
- package/docs/content-format.md +57 -68
- package/e2e.mjs +4 -4
- package/engine/actor-compiler.mjs +36 -36
- package/engine/address-charset.mjs +6 -6
- package/engine/address-diff.mjs +12 -11
- package/engine/anchored-sections.mjs +1 -1
- package/engine/anchors.mjs +1 -1
- package/engine/base-compiler.mjs +36 -38
- package/engine/bundle-notes.mjs +4 -4
- package/engine/bundles.mjs +8 -8
- package/engine/code-fences.mjs +3 -3
- package/engine/compendiums.mjs +8 -8
- package/engine/compile-corpus.mjs +4 -5
- package/engine/content-address.mjs +15 -15
- package/engine/content-charset.mjs +1 -1
- package/engine/content-format-check.mjs +24 -25
- package/engine/content-format.mjs +8 -8
- package/engine/content-html.mjs +202 -0
- package/engine/content-icons.mjs +225 -98
- package/engine/content-index.mjs +17 -17
- package/engine/content-links.mjs +30 -30
- package/engine/content-lint.mjs +20 -24
- package/engine/content-package.mjs +7 -9
- package/engine/content-slug.mjs +2 -2
- package/engine/content-tables.mjs +7 -8
- package/engine/content-tree.mjs +1 -1
- package/engine/derived-fields.mjs +174 -0
- package/engine/diagnostics.mjs +3 -4
- package/engine/document-subtypes.mjs +6 -7
- package/engine/field-reference.mjs +8 -8
- package/engine/field-spec.mjs +29 -30
- package/engine/folder-notes.mjs +14 -14
- package/engine/foreign-catalog.mjs +8 -9
- package/engine/foundry-entries.mjs +19 -20
- package/engine/frontmatter-lint.mjs +64 -69
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +39 -39
- package/engine/helpers.mjs +63 -54
- package/engine/homepage.mjs +20 -22
- package/engine/ids.mjs +15 -15
- package/engine/index-records.mjs +4 -4
- package/engine/index.mjs +14 -8
- package/engine/item-compiler.mjs +54 -29
- package/engine/item-docs.mjs +11 -13
- package/engine/item-registry.mjs +13 -13
- package/engine/journals.mjs +15 -15
- package/engine/macros.mjs +3 -3
- package/engine/map-notes.mjs +6 -6
- package/engine/metadata-index.mjs +5 -5
- package/engine/note-claims.mjs +36 -34
- package/engine/note-ids.mjs +5 -5
- package/engine/note-package.mjs +4 -4
- package/engine/note-renames.mjs +3 -3
- package/engine/note-schemas.mjs +3 -3
- package/engine/note-vocabulary.mjs +27 -26
- package/engine/pack-config.mjs +13 -13
- package/engine/pack-router.mjs +0 -0
- package/engine/prose-config.mjs +9 -9
- package/engine/prose-lint.mjs +12 -13
- package/engine/region-events.mjs +2 -2
- package/engine/retired-fields.mjs +24 -22
- package/engine/runtime-only-fields.mjs +1 -1
- package/engine/scene-levels.mjs +1 -1
- package/engine/scenes.mjs +19 -20
- package/engine/schema-check.mjs +20 -20
- package/engine/schema-extract.mjs +1 -1
- package/engine/site-build.mjs +45 -47
- package/engine/site-index.mjs +17 -18
- package/engine/sql-tables.mjs +21 -13
- package/engine/subtype-registry.mjs +5 -4
- package/engine/system-block.mjs +18 -19
- package/engine/systems.mjs +2 -2
- package/engine/web-wikilinks.mjs +35 -35
- package/engine/wikilink-syntax.mjs +16 -16
- package/engine/wikilinks.mjs +39 -39
- package/hm3/actors.mjs +22 -22
- package/hm3/document-subtypes.mjs +5 -5
- package/hm3/index.mjs +2 -2
- package/hm3/item-builders.mjs +1 -1
- package/hm3/item-fields.mjs +3 -3
- package/hm3/items.mjs +20 -8
- package/hm3/template-priority.mjs +2 -2
- package/lang.mjs +3 -3
- package/manifest.mjs +17 -20
- package/package.json +1 -2
- package/release.mjs +3 -3
- package/sohl/actors.mjs +28 -28
- package/sohl/affiliation-standings.mjs +2 -2
- package/sohl/being-info.mjs +5 -5
- package/sohl/default-item-art.mjs +5 -5
- package/sohl/document-subtypes.mjs +5 -5
- package/sohl/index.mjs +3 -3
- package/sohl/item-builders.mjs +7 -7
- package/sohl/item-fields.mjs +8 -9
- package/sohl/items.mjs +20 -6
- package/sohl/kb-passes.mjs +5 -5
- package/sohl/note-schemas.mjs +7 -7
- package/sohl/skill-base.mjs +1 -1
- package/types/content-config.d.mts +25 -24
- package/types/e2e.d.mts +3 -3
- package/types/engine/actor-compiler.d.mts +14 -13
- package/types/engine/address-charset.d.mts +6 -6
- package/types/engine/address-diff.d.mts +3 -3
- package/types/engine/base-compiler.d.mts +17 -19
- package/types/engine/bundle-notes.d.mts +3 -3
- package/types/engine/bundles.d.mts +1 -1
- package/types/engine/code-fences.d.mts +3 -3
- package/types/engine/compendiums.d.mts +3 -3
- package/types/engine/compile-corpus.d.mts +1 -1
- package/types/engine/content-address.d.mts +11 -11
- package/types/engine/content-format-check.d.mts +6 -6
- package/types/engine/content-format.d.mts +2 -2
- package/types/engine/content-html.d.mts +78 -0
- package/types/engine/content-icons.d.mts +150 -62
- package/types/engine/content-index.d.mts +2 -2
- package/types/engine/content-links.d.mts +8 -8
- package/types/engine/content-lint.d.mts +2 -2
- package/types/engine/content-package.d.mts +6 -8
- package/types/engine/derived-fields.d.mts +101 -0
- package/types/engine/diagnostics.d.mts +2 -2
- package/types/engine/document-subtypes.d.mts +3 -3
- package/types/engine/field-spec.d.mts +37 -39
- package/types/engine/folder-notes.d.mts +4 -5
- package/types/engine/foreign-catalog.d.mts +3 -3
- package/types/engine/foundry-entries.d.mts +6 -7
- package/types/engine/frontmatter-lint.d.mts +7 -7
- package/types/engine/frontmatter.d.mts +7 -7
- package/types/engine/generate.d.mts +7 -7
- package/types/engine/helpers.d.mts +25 -27
- package/types/engine/homepage.d.mts +16 -18
- package/types/engine/ids.d.mts +13 -13
- package/types/engine/index-records.d.mts +3 -3
- package/types/engine/index.d.mts +2 -0
- package/types/engine/item-compiler.d.mts +21 -5
- package/types/engine/item-docs.d.mts +2 -2
- package/types/engine/item-registry.d.mts +6 -6
- package/types/engine/journals.d.mts +3 -3
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/metadata-index.d.mts +4 -4
- package/types/engine/note-claims.d.mts +16 -15
- package/types/engine/note-ids.d.mts +4 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-renames.d.mts +3 -3
- package/types/engine/note-vocabulary.d.mts +9 -8
- package/types/engine/pack-config.d.mts +3 -3
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/prose-config.d.mts +9 -9
- package/types/engine/prose-lint.d.mts +3 -4
- package/types/engine/region-events.d.mts +2 -2
- package/types/engine/retired-fields.d.mts +10 -9
- package/types/engine/schema-check.d.mts +11 -11
- package/types/engine/site-build.d.mts +18 -19
- package/types/engine/site-index.d.mts +3 -4
- package/types/engine/sql-tables.d.mts +11 -5
- package/types/engine/subtype-registry.d.mts +3 -3
- package/types/engine/system-block.d.mts +3 -3
- package/types/engine/web-wikilinks.d.mts +7 -7
- package/types/engine/wikilink-syntax.d.mts +17 -17
- package/types/engine/wikilinks.d.mts +13 -12
- package/types/hm3/actors.d.mts +1 -1
- package/types/hm3/document-subtypes.d.mts +1 -1
- package/types/hm3/items.d.mts +1 -2
- package/types/hm3/template-priority.d.mts +1 -1
- package/types/manifest.d.mts +8 -8
- package/types/sohl/actors.d.mts +2 -2
- package/types/sohl/affiliation-standings.d.mts +2 -2
- package/types/sohl/being-info.d.mts +2 -2
- package/types/sohl/document-subtypes.d.mts +1 -1
- package/types/sohl/items.d.mts +1 -2
- package/types/sohl/note-schemas.d.mts +1 -1
- package/MIGRATING.md +0 -608
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The affiliation standings an authored `relation` map may use — one
|
|
3
|
-
* affiliation's stance toward another
|
|
3
|
+
* affiliation's stance toward another.
|
|
4
4
|
*
|
|
5
5
|
* Plain ESM for the same reason `./default-item-art.mjs` is: the pack scripts
|
|
6
6
|
* run under bare `node`, so they cannot read the runtime's TypeScript
|
|
7
7
|
* `AFFILIATION_STANDING`. This module is where the pipeline reads the list
|
|
8
|
-
* from, rather than restating it inside a compiler
|
|
8
|
+
* from, rather than restating it inside a compiler.
|
|
9
9
|
*
|
|
10
10
|
* The runtime keeps its own `defineType("SOHL.Affiliation.Standing", { … })`
|
|
11
11
|
* declaration in `src/utils/constants.ts`, because that literal is *parsed out
|
|
@@ -36,7 +36,7 @@ export function deriveBeingInfo(sohl: object | null | undefined, index: Map<stri
|
|
|
36
36
|
/**
|
|
37
37
|
* The note `type` whose pages carry a being info block.
|
|
38
38
|
*
|
|
39
|
-
* One name
|
|
39
|
+
* One name: `character` and `creature` are the `being` they
|
|
40
40
|
* had always compiled into. The retired names are deliberately **not** accepted
|
|
41
41
|
* as aliases: they throw elsewhere in the system, and tolerating them here
|
|
42
42
|
* would hide the next drift of this kind rather than surface it.
|
|
@@ -50,7 +50,7 @@ export const BEING_TYPE: "being";
|
|
|
50
50
|
* added in a single place rather than in each consumer's site build.
|
|
51
51
|
*
|
|
52
52
|
* Keyed by **note** type, which is what a being's embedded `(type, shortcode)`
|
|
53
|
-
* references spell — and
|
|
53
|
+
* references spell — and three of those are not the document
|
|
54
54
|
* subtype they compile into. A reference still on a renamed spelling is
|
|
55
55
|
* normalised at the lookup below rather than given a second row here.
|
|
56
56
|
*
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* The Item rows are the thirteen types the item registry declares; the one
|
|
6
6
|
* Actor row is `being`, which was two types (`character` and `creature`)
|
|
7
|
-
* compiling to the same actor
|
|
7
|
+
* compiling to the same actor before they were retired. Types this
|
|
8
8
|
* map does not name — `doc`, `macro`, the three map types — compile into
|
|
9
9
|
* documents that carry no system subtype at all, so they have no row and never
|
|
10
10
|
* needed one.
|
package/types/sohl/items.d.mts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export class Items extends SystemItemCompiler {
|
|
2
2
|
/**
|
|
3
3
|
* SoHL's note-type → document-subtype map — the one declaration that says
|
|
4
|
-
* which block this pass reads, which notes it claims, and what each becomes
|
|
5
|
-
* (#58/#79).
|
|
4
|
+
* which block this pass reads, which notes it claims, and what each becomes.
|
|
6
5
|
*
|
|
7
6
|
* @type {import("../engine/document-subtypes.mjs").DocumentSubtypeMap}
|
|
8
7
|
*/
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* one vocabulary rather than two. They are declared there rather than here
|
|
7
7
|
* because they are note-format knowledge — a `homepage` carries no `system`
|
|
8
8
|
* block and would mean the same thing for a game system that is not SoHL — and
|
|
9
|
-
* because a package declaring no `itemBuilders` never reaches this file
|
|
9
|
+
* because a package declaring no `itemBuilders` never reaches this file.
|
|
10
10
|
*
|
|
11
11
|
* @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
|
|
12
12
|
*/
|
package/MIGRATING.md
DELETED
|
@@ -1,608 +0,0 @@
|
|
|
1
|
-
# Migrating to `@heroiclands/package-build` 15.0.0
|
|
2
|
-
|
|
3
|
-
**Three unrelated changes ship in this major, and they ask different
|
|
4
|
-
repositories for different things.** A page's `url:` front matter is now stated
|
|
5
|
-
relative to the **site root** (#217), which a site-publishing repository answers
|
|
6
|
-
by deleting one line; an empty art path now means the opposite of an absent one
|
|
7
|
-
(#218), which a content tree answers by sweeping `img: ""` and `portrait: ""` to
|
|
8
|
-
`null`; and a note's own `title` no longer reaches an `affiliation` item's
|
|
9
|
-
`system.title` (#218), which asks nothing of any repository that exists today.
|
|
10
|
-
|
|
11
|
-
Route yourself by what you have. A repository that publishes no site skips
|
|
12
|
-
§1–§2. One that authors no empty art path skips §3–§4. One with no
|
|
13
|
-
`type: affiliation` notes skips §6 — and §5, which is only the seam between the
|
|
14
|
-
two halves of #218.
|
|
15
|
-
|
|
16
|
-
## 1. Drop the `site.base: "/"` stopgap (#217)
|
|
17
|
-
|
|
18
|
-
If your repository set it to stop every page publishing at
|
|
19
|
-
`/<package>/<package>/<address>/`, delete the line — the default,
|
|
20
|
-
`/<contentPackage>/`, is now right for both halves:
|
|
21
|
-
|
|
22
|
-
```yaml
|
|
23
|
-
site:
|
|
24
|
-
out: kb/content
|
|
25
|
-
# base: "/" ← delete this
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Keeping it is no longer harmless: the addresses stay correct either way, but
|
|
29
|
-
every same-package link this build renders into a page body stays short
|
|
30
|
-
(`/doc-skills/` rather than `/sohl/doc-skills/`) and 404s.
|
|
31
|
-
|
|
32
|
-
A repository that is genuinely served somewhere other than
|
|
33
|
-
`/<contentPackage>/` still says so here, and that value still reaches every
|
|
34
|
-
`href`.
|
|
35
|
-
|
|
36
|
-
## 2. What the `url:` change does _not_ touch
|
|
37
|
-
|
|
38
|
-
- No note edits, and no configuration key added or removed.
|
|
39
|
-
- Every link-manifest entry, including each entry's `path`, is byte-identical.
|
|
40
|
-
- Every compiled compendium document is unchanged.
|
|
41
|
-
- `trees` pages and section landings state no `url:` and do not move.
|
|
42
|
-
|
|
43
|
-
The published address of every content page **does** move — from
|
|
44
|
-
`/<package>/<package>/<address>/`, where nothing linked, to
|
|
45
|
-
`/<package>/<address>/`, which is what the link manifest, the sitemap and every
|
|
46
|
-
inbound link already named.
|
|
47
|
-
|
|
48
|
-
## 3. Sweep `img: ""` and `portrait: ""` to `null` (#218)
|
|
49
|
-
|
|
50
|
-
`resolveImg` opened with `if (!raw) return ""`, and every caller applied its own
|
|
51
|
-
default to the result with `||`. So `""`, `null` and an absent key were one
|
|
52
|
-
case: all three compiled to the type's default art, and a note had no way to say
|
|
53
|
-
"ship no image" at all.
|
|
54
|
-
|
|
55
|
-
They are now three values with two meanings:
|
|
56
|
-
|
|
57
|
-
| a note writes | it means | it compiles with |
|
|
58
|
-
| -------------- | ------------------------------------ | ---------------- |
|
|
59
|
-
| nothing at all | _unset_ — name me no art | the type default |
|
|
60
|
-
| `img: null` | the same thing, said out loud | the type default |
|
|
61
|
-
| `img: ""` | _blank on purpose_ — I want no image | no image |
|
|
62
|
-
|
|
63
|
-
So a note still carrying `img: ""` **loses its default art**. The same holds for
|
|
64
|
-
`portrait:`, which a being carries independently of `img` and which resolves
|
|
65
|
-
through the same function. Find them both:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
grep -rnE '^[[:space:]]*(img|portrait):[[:space:]]*""[[:space:]]*$' assets/content --include='*.md'
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
and write `null` in each — unless the document really is meant to have no image,
|
|
72
|
-
which is what `""` now says. Before this release `sohl-thalorna` swept forty-five
|
|
73
|
-
`img: ""` notes and `sohl-kethira-basic` eleven `portrait: ""` beings; `sohl`
|
|
74
|
-
authors neither.
|
|
75
|
-
|
|
76
|
-
The frontmatter lint reports every one that is left, as a warning:
|
|
77
|
-
|
|
78
|
-
```
|
|
79
|
-
Note.md:9:1: warning: `img: ""` means "ship no art at all" — it no longer falls
|
|
80
|
-
back to this type's default. Write `img: null` for a note that simply names
|
|
81
|
-
none; keep `""` only where the document is meant to have no image
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## 4. Custom callers pair their default with `??`, not `||`
|
|
85
|
-
|
|
86
|
-
`resolveImg` returns `string | null` now: `null` for an unset path, `""` for a
|
|
87
|
-
deliberate blank. A consumer that calls it directly — a custom item builder, a
|
|
88
|
-
compiler of its own — must switch:
|
|
89
|
-
|
|
90
|
-
```diff
|
|
91
|
-
-img: resolveImg(fm.img) || MY_DEFAULT,
|
|
92
|
-
+img: resolveImg(fm.img) ?? MY_DEFAULT,
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`||` still compiles and still looks right; it silently reinstates the old
|
|
96
|
-
conflation, because `""` is falsy. Every caller in this package moved:
|
|
97
|
-
`sohl/items.mjs`, three in `sohl/actors.mjs` (`img`, `portrait`, and the
|
|
98
|
-
prototype token's `texture.src`), and `engine/macros.mjs`.
|
|
99
|
-
|
|
100
|
-
`itemArt()` is unaffected — a registry entry with no art throws before the
|
|
101
|
-
translation, so its result is never the unset case.
|
|
102
|
-
|
|
103
|
-
## 5. `title` is **not** on the art rule
|
|
104
|
-
|
|
105
|
-
`resolveImg`'s rule reads as a general one about optional strings, and it is
|
|
106
|
-
not — it belongs to the function, and `title` never goes through it. So do not
|
|
107
|
-
extend §3's sweep to `title`, and do not read the table in §3 as saying anything
|
|
108
|
-
about it.
|
|
109
|
-
|
|
110
|
-
**The reason has changed since this section was first written, and the earlier
|
|
111
|
-
one is no longer true.** It used to be that a note's top-level `title` was
|
|
112
|
-
_simultaneously_ the page's heading and the shared source for an `affiliation`
|
|
113
|
-
item's `system.title`, so `title: null` did not fall back — it stringified, and
|
|
114
|
-
the compiled document shipped the literal string `"null"`. That collision is what
|
|
115
|
-
§6 removes: the top-level key is no longer a source for the item field at all.
|
|
116
|
-
|
|
117
|
-
So `title: null` is now simply a note declining to state a heading, and the site
|
|
118
|
-
emitter's `fm.title ?? name` falls back to `name.full` as it always did. It
|
|
119
|
-
reaches no document field and stringifies nothing.
|
|
120
|
-
|
|
121
|
-
`title: ""` still publishes a **deliberately blank heading** — which is what cost
|
|
122
|
-
fifteen `sohl-thalorna` notes their names (HeroicLands/sohl-thalorna#129) — and
|
|
123
|
-
nothing warns about it yet. Whether the frontmatter lint should is #218's, still
|
|
124
|
-
open, and deliberately not settled by the art-field warning in §3.
|
|
125
|
-
|
|
126
|
-
## 6. A note's own `title` no longer fills `system.title` (#218)
|
|
127
|
-
|
|
128
|
-
**No note edit, no URL change, and no compiled document moves.** An
|
|
129
|
-
`affiliation` item's `system.title` stops falling back to the note's own
|
|
130
|
-
top-level `title`. The two were never the same quantity — a note's `title` is
|
|
131
|
-
the heading its page publishes under, while `system.title` is the style of
|
|
132
|
-
address an office carries, Ajaw or Warden — and no note in any content tree
|
|
133
|
-
relied on the fallback, so `content-build package compile` emits byte-identical
|
|
134
|
-
`build/packs-json` for every consumer.
|
|
135
|
-
|
|
136
|
-
Only a `type: affiliation` note is affected, and only if it carries a top-level
|
|
137
|
-
`title` it meant as the item's field rather than as the page's heading:
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
grep -rl '^type: affiliation' assets/content --include='*.md' \
|
|
141
|
-
| xargs grep -l '^title:'
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Anything that turns up wanted one of the two positions that describe the
|
|
145
|
-
_document_ rather than the note — `sohl.system.title`, or `sohl.title`, the
|
|
146
|
-
legacy in-block key most trees already write. A membership's title belongs on
|
|
147
|
-
the entry in the being's `sohl.items`, as `system.title`.
|
|
148
|
-
|
|
149
|
-
`data: { title: ... }` is not a position and never was: `title` is not a `data:`
|
|
150
|
-
property any note type declares, so `content-build lint` refuses it.
|
|
151
|
-
|
|
152
|
-
### Regenerate the item field reference
|
|
153
|
-
|
|
154
|
-
The generated page now prints, under each affected type's table, what the
|
|
155
|
-
top-level key of a non-shared field means instead — so an author reading the
|
|
156
|
-
table learns that writing `title:` at the top of a note will not fill this
|
|
157
|
-
field. Re-run the generator and commit the result, or a repository that checks
|
|
158
|
-
the page for staleness reports it stale:
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
npx content-build docs item-fields --out <the path your repo uses>
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Declaring your own non-shared field
|
|
165
|
-
|
|
166
|
-
A field in an `itemBuilders` `fields:` declaration may now carry
|
|
167
|
-
`topLevelMeans`, whose value is _what the note's top-level key of that name
|
|
168
|
-
means instead_. Declaring it removes the shared top-level position from that
|
|
169
|
-
field's resolution order:
|
|
170
|
-
|
|
171
|
-
```js
|
|
172
|
-
{
|
|
173
|
-
name: "title",
|
|
174
|
-
to: "title",
|
|
175
|
-
...STRING,
|
|
176
|
-
default: "",
|
|
177
|
-
topLevelMeans: "the note's own title — the heading its page is published under",
|
|
178
|
-
describe: "The style of address the office carries.",
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
The value is the reason rather than a bare flag on purpose: the next person
|
|
183
|
-
adding a field needs to know the question exists, and a boolean with a comment
|
|
184
|
-
beside it is two statements of one rule.
|
|
185
|
-
|
|
186
|
-
# Migrating to `@heroiclands/package-build` 12.0.0
|
|
187
|
-
|
|
188
|
-
**No note edit, no URL change, and one thing to check in the Hugo layer.** A
|
|
189
|
-
section is a Hugo directory concept that the note format no longer carries
|
|
190
|
-
(#204): content pages are written **flat** under the content mount, named by
|
|
191
|
-
their address, instead of into a `<section>/` directory.
|
|
192
|
-
|
|
193
|
-
## 1. Nothing in the content tree changes
|
|
194
|
-
|
|
195
|
-
A page's address never contained a section, so **no published URL moves**. A
|
|
196
|
-
`README.md` in the content tree stops being its section's landing and becomes an
|
|
197
|
-
ordinary page addressed `<type>-<shortcode>/` like every other note; if a tree
|
|
198
|
-
still has one that was serving as a landing, it now publishes at its own address.
|
|
199
|
-
No tree in this project had one.
|
|
200
|
-
|
|
201
|
-
A `doc` with no `subType` used to be refused ("no section, so there is nowhere to
|
|
202
|
-
file the page") and now publishes. Its `subType` is a **genre** again — closed to
|
|
203
|
-
`rules`, `userguide`, `reference` — because it no longer doubles as a section
|
|
204
|
-
address on a `README`. That closed check runs after the two #206 added ahead of
|
|
205
|
-
it: a retired spelling is a warning naming its replacement, a hyphenated value
|
|
206
|
-
is an error, and only then is the type's own list the reason.
|
|
207
|
-
|
|
208
|
-
## 2. Declare every section your site links to
|
|
209
|
-
|
|
210
|
-
`site.sections` is now the whole of what a section is. No page is filed into a
|
|
211
|
-
section directory any more, so nothing else makes `/<package>/<prefix><section>/`
|
|
212
|
-
exist:
|
|
213
|
-
|
|
214
|
-
```yaml
|
|
215
|
-
site:
|
|
216
|
-
sections:
|
|
217
|
-
being: { title: Beings, banner: banners/creature.webp }
|
|
218
|
-
weapongear: { title: Weapons, banner: banners/weapons.webp }
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
A card, menu entry or breadcrumb pointing at a section nobody declares is a 404.
|
|
222
|
-
|
|
223
|
-
## 3. Check how a section landing lists its members
|
|
224
|
-
|
|
225
|
-
A declared section's directory holds only its own `_index.md`, so a layout
|
|
226
|
-
reading `.Pages` renders an empty listing. Query the site instead, on the page's
|
|
227
|
-
own `type`:
|
|
228
|
-
|
|
229
|
-
```go-html-template
|
|
230
|
-
{{- $pages := where site.RegularPages "Type" "weapongear" -}}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
That is the shape a content catalog wants regardless — it groups by what a page
|
|
234
|
-
_is_ rather than by where its file happened to be written — and it is what
|
|
235
|
-
`sohl`'s catalog layouts already do.
|
|
236
|
-
|
|
237
|
-
A site rendering through a **shared theme** has no layout of its own to edit. As
|
|
238
|
-
of 13.1.0 the section declares its query instead, and the theme runs it:
|
|
239
|
-
|
|
240
|
-
```yaml
|
|
241
|
-
sections:
|
|
242
|
-
weapongear: { title: Weapons, listType: weapongear }
|
|
243
|
-
user-guide: { title: User Guide, listType: doc, listSubType: userguide }
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
`listType` is the content type, not the section's name — the two need not agree,
|
|
247
|
-
and `listSubType` narrows a type whose genres share it. See
|
|
248
|
-
[What a section may declare](CONTENT.md#what-a-section-may-declare).
|
|
249
|
-
|
|
250
|
-
## What did not change
|
|
251
|
-
|
|
252
|
-
- Every content page's `url:`, and so every published address.
|
|
253
|
-
- Every link-manifest entry, including each entry's `path`.
|
|
254
|
-
- Every compiled compendium document.
|
|
255
|
-
- `site.sections` / `site.readmeSections` and what an entry may declare.
|
|
256
|
-
|
|
257
|
-
# Migrating to `@heroiclands/package-build` 11.0.0
|
|
258
|
-
|
|
259
|
-
**Two edits, and the second is one line per repository.** Every published page
|
|
260
|
-
moves to its address (#181), and the package homepage becomes an ordinary
|
|
261
|
-
addressed note (#182).
|
|
262
|
-
|
|
263
|
-
## 1. A page's URL is its address
|
|
264
|
-
|
|
265
|
-
Every content page now serves at `/<package>/<type>-<shortcode>/` rather than at
|
|
266
|
-
a slug derived from `name.full`. No content edit is required for it — the
|
|
267
|
-
address is computed from fields every note already declares — but **every
|
|
268
|
-
published URL moves**, so anything holding one (an external link, a bookmark, a
|
|
269
|
-
citation in another repository) has to be re-derived.
|
|
270
|
-
|
|
271
|
-
## 2. Give the homepage a `shortcode`
|
|
272
|
-
|
|
273
|
-
The homepage used to **refuse** `shortcode` and `name`, because a URL derived
|
|
274
|
-
from a display name while a homepage's destination was fixed. That premise is
|
|
275
|
-
gone, so both fields are permitted and `shortcode` is **required**:
|
|
276
|
-
|
|
277
|
-
```markdown
|
|
278
|
-
---
|
|
279
|
-
type: homepage
|
|
280
|
-
shortcode: root
|
|
281
|
-
title: HârnMaster Kethira Basic
|
|
282
|
-
---
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
`root` is the convention, not a rule. Without one, `content-build lint` and
|
|
286
|
-
`content-build site` both refuse the note:
|
|
287
|
-
|
|
288
|
-
```text
|
|
289
|
-
assets/content/homepage.md:3:7: error: a `type: homepage` note declares a `shortcode`, like every other note: it is addressed as `homepage-<shortcode>` and published at `/<package>/homepage-<shortcode>/`, which is where `[[homepage-<shortcode>|Text]]` lands. Write `shortcode: root` — the package landing is `homepage-root` in every package
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
`id` is still refused, on ground this does not touch: a homepage compiles into
|
|
293
|
-
no compendium document.
|
|
294
|
-
|
|
295
|
-
## 3. Author the `/<package>/` redirect
|
|
296
|
-
|
|
297
|
-
The landing is published at `/<package>/homepage-root/`, and nothing is written
|
|
298
|
-
at `/<package>/` any more. Add the redirect to the repository's own
|
|
299
|
-
`_redirects`, and pin its lifetime in `_headers` — Cloudflare Pages sets no
|
|
300
|
-
`Cache-Control` on a redirect it generates, and an unpinned 301 is cacheable
|
|
301
|
-
indefinitely:
|
|
302
|
-
|
|
303
|
-
```text
|
|
304
|
-
# _redirects
|
|
305
|
-
/sohl/ /sohl/homepage-root/ 301
|
|
306
|
-
/sohl /sohl/homepage-root/ 301
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
```text
|
|
310
|
-
# _headers
|
|
311
|
-
/sohl/
|
|
312
|
-
Cache-Control: max-age=3600
|
|
313
|
-
/sohl
|
|
314
|
-
Cache-Control: max-age=3600
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
Both path forms, because Pages matches the raw path and `/sohl` and `/sohl/` are
|
|
318
|
-
distinct keys. See `CONTENT.md` for why the pairing works and how to verify it
|
|
319
|
-
after a deploy.
|
|
320
|
-
|
|
321
|
-
# Migrating to `@heroiclands/package-build` 6.0.0
|
|
322
|
-
|
|
323
|
-
**No configuration change to make, and one build check that may now fail.**
|
|
324
|
-
`packageBuild.manifest.packFolders` is compared against the `packs[]` the build
|
|
325
|
-
derives, and a folder naming a pack the package does not ship is an error.
|
|
326
|
-
|
|
327
|
-
## 1. Check what `package-build manifest` says
|
|
328
|
-
|
|
329
|
-
Nothing to edit up front — run it, and the build names anything wrong:
|
|
330
|
-
|
|
331
|
-
```text
|
|
332
|
-
package-build.config.yaml:164:23: error: packFolders: folder "HârnMaster 3 System" names pack "character", which this package does not ship (packs: items, system-help)
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
Every name in a folder's `packs` must appear in the top-level `packs:` list —
|
|
336
|
-
companions included, since Foundry sees no difference. Delete a name that no
|
|
337
|
-
longer resolves, or correct it. An error stops the manifest being written, so
|
|
338
|
-
nothing half-right reaches the stage.
|
|
339
|
-
|
|
340
|
-
## 2. The advisory needs no action
|
|
341
|
-
|
|
342
|
-
A pack no folder names is a **warning**, and the build continues:
|
|
343
|
-
|
|
344
|
-
```text
|
|
345
|
-
package-build.config.yaml:162:13: warning: packFolders: pack "items" is named by no folder, so it ships outside every folder this package declares
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Shipping one pack at the root can be deliberate, so this is not an error. But a
|
|
349
|
-
package that bothered to declare a folder rarely meant to leave one out — that
|
|
350
|
-
is exactly how `HarnMaster-3-FoundryVTT` shipped 1,577 of 1,597 documents loose
|
|
351
|
-
beside its folder. Add the pack to a folder, or leave it and take the advisory.
|
|
352
|
-
|
|
353
|
-
A package that declares no `packFolders` at all is unaffected, and says nothing.
|
|
354
|
-
|
|
355
|
-
## 3. Nothing else
|
|
356
|
-
|
|
357
|
-
- **No configuration key changed**, and no CLI command, flag or exit code beyond
|
|
358
|
-
`manifest` failing on the error above.
|
|
359
|
-
- `writeManifest` takes an optional `configFile`, so a finding names the line it
|
|
360
|
-
is about. Omitting it costs the position, not the finding.
|
|
361
|
-
|
|
362
|
-
# Migrating to `@heroiclands/package-build` 5.0.0
|
|
363
|
-
|
|
364
|
-
**One configuration change: `publish.site` is a mode, not a boolean.** And one
|
|
365
|
-
new authoring capability that needs no migration: a `type: homepage` note.
|
|
366
|
-
|
|
367
|
-
## 1. Respell `publish.site`
|
|
368
|
-
|
|
369
|
-
```yaml
|
|
370
|
-
publish:
|
|
371
|
-
site: content # was `site: true`
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
```yaml
|
|
375
|
-
publish:
|
|
376
|
-
site: homepage # was `site: false`, or absent
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
`homepage` is the default, so a repository that never set the key needs no edit.
|
|
380
|
-
A repository that set it to either boolean gets a `TypeError` at load naming the
|
|
381
|
-
mode to write:
|
|
382
|
-
|
|
383
|
-
```text
|
|
384
|
-
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.
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
Both spellings are **refused rather than mapped** onto the nearest mode. `false`
|
|
388
|
-
read as _this package has no web presence_, which now describes no package at
|
|
389
|
-
all, and a value silently reinterpreted reads to its author as though it still
|
|
390
|
-
means what it said.
|
|
391
|
-
|
|
392
|
-
Nothing else about publishing moved: `publish.address`, `publish.manifests` and
|
|
393
|
-
the whole `site:` block are unchanged, and every address `sohl` and `thalorna`
|
|
394
|
-
already publish is byte-identical across the upgrade.
|
|
395
|
-
|
|
396
|
-
## 2. Author a homepage (optional here, required by #52)
|
|
397
|
-
|
|
398
|
-
Every package is reachable at `https://www.heroiclands.org/<contentPackage>/`,
|
|
399
|
-
and the page there is a note in the content tree:
|
|
400
|
-
|
|
401
|
-
```markdown
|
|
402
|
-
---
|
|
403
|
-
type: homepage
|
|
404
|
-
title: HârnMaster Kethira Basic # optional; defaults to packageBuild.manifest.title
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
What the module is, which system it needs, how to install it.
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
It compiles into no compendium document, appears in no pack and in no link
|
|
411
|
-
manifest, and is addressed by the package rather than by its own name. It is
|
|
412
|
-
written to the root of `site.out`, one level above the content mount.
|
|
413
|
-
|
|
414
|
-
A repository with no homepage note publishes none, and the site build says so in
|
|
415
|
-
its count. Requiring exactly one is a separate change (#52).
|
|
416
|
-
|
|
417
|
-
## 3. What homepage-only means
|
|
418
|
-
|
|
419
|
-
`homepage` mode does not merely leave the content configuration unused — it
|
|
420
|
-
**fences the content surfaces off**. The tree is never walked for pages, and
|
|
421
|
-
`site.sections`, `site.trees`, `site.landing` and `site.backfillSections` emit
|
|
422
|
-
nothing even when they are declared.
|
|
423
|
-
|
|
424
|
-
That is deliberate, and it is a licensing requirement rather than a preference.
|
|
425
|
-
`sohl-kethira-basic` (Keléstia Productions' Fan Material Guidelines) and
|
|
426
|
-
`harn-adventures` (HârnFanon under Lythia's terms) publish a homepage and no
|
|
427
|
-
other page; the failure mode is silent — a `site:` block added later ships
|
|
428
|
-
licensed content with nobody noticing — so the property is asserted by the code
|
|
429
|
-
path rather than left to configuration.
|
|
430
|
-
|
|
431
|
-
`publish.manifests.publish` is a separate decision and stays `false` for both: a
|
|
432
|
-
link manifest is the dependency edge that would stop a module being withdrawable,
|
|
433
|
-
and a homepage is not.
|
|
434
|
-
|
|
435
|
-
# Migrating to `@heroiclands/package-build` 4.0.0
|
|
436
|
-
|
|
437
|
-
**One authoring change: delete `package:` from every content note.** A note's
|
|
438
|
-
package is the repository's configured `contentPackage`, and declaring the field
|
|
439
|
-
is now a build error rather than a redundancy the build tolerated.
|
|
440
|
-
|
|
441
|
-
## 1. Sweep the content tree
|
|
442
|
-
|
|
443
|
-
The field is a whole line, and nothing else reads it:
|
|
444
|
-
|
|
445
|
-
```bash
|
|
446
|
-
find assets/content -name '*.md' -print0 | xargs -0 sed -i '' '/^package: /d'
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
(GNU `sed`: `sed -i '/^package: /d'`.) Then compile — `content-build package
|
|
450
|
-
compile` must produce byte-identical output to the run before the sweep, because
|
|
451
|
-
the value the build derives is the value the notes restated.
|
|
452
|
-
|
|
453
|
-
A note that still carries the field fails the build where it is:
|
|
454
|
-
|
|
455
|
-
```text
|
|
456
|
-
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.
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
`content-build lint` reports every one of them in a single pass, so the sweep can
|
|
460
|
-
be checked before it is compiled.
|
|
461
|
-
|
|
462
|
-
## 2. Nothing else
|
|
463
|
-
|
|
464
|
-
- **`contentPackage` stays**, and is unchanged. It is the address namespace —
|
|
465
|
-
the first segment of every canonical key, the name of the emitted link
|
|
466
|
-
manifest, and the package a cross-package wikilink writes. Every address in
|
|
467
|
-
every manifest is identical across this upgrade.
|
|
468
|
-
- **A generated table's `WHERE … and package = "<pkg>"` clause keeps matching.**
|
|
469
|
-
The package is synthesised into what the table search sees, from
|
|
470
|
-
`contentPackage`; it was never the authored field that answered the clause
|
|
471
|
-
after 3.3.0.
|
|
472
|
-
- **No configuration key changed**, and no CLI command, flag or exit code.
|
|
473
|
-
|
|
474
|
-
## What this replaced
|
|
475
|
-
|
|
476
|
-
A note used to be _selected_ by the field: it compiled when `package:` matched
|
|
477
|
-
`contentPackage` and was skipped, silently and as "belongs to another pass",
|
|
478
|
-
when it did not. A tree whose notes named a package no configuration answered to
|
|
479
|
-
compiled **zero notes and exited 0** (#56). 3.3.0 made the field optional so
|
|
480
|
-
every repository could be swept on a non-breaking version; this major removes it.
|
|
481
|
-
|
|
482
|
-
# Migrating to `@heroiclands/package-build` 3.0.0
|
|
483
|
-
|
|
484
|
-
`@heroiclands/content-build` and `@heroiclands/package-build` are one package.
|
|
485
|
-
The content half now ships inside `@heroiclands/package-build` at 3.0.0;
|
|
486
|
-
`@heroiclands/content-build` is deprecated and receives no further releases.
|
|
487
|
-
|
|
488
|
-
Nothing about how a build _works_ changed. This is a packaging change: the same
|
|
489
|
-
modules, the same CLI commands, the same configuration keys, reachable under one
|
|
490
|
-
name.
|
|
491
|
-
|
|
492
|
-
## Why
|
|
493
|
-
|
|
494
|
-
The two packages split by input — content-build read `assets/content/**`,
|
|
495
|
-
package-build read `lang/`, `styles/`, `src/` and the manifest template — on the
|
|
496
|
-
theory that a module would use one or the other. No consumer ever did. All three
|
|
497
|
-
installed both, and package-build depended on content-build besides, so the
|
|
498
|
-
packaging half dragged the content half in regardless.
|
|
499
|
-
|
|
500
|
-
What the boundary cost was real: one configuration file with two owners, two
|
|
501
|
-
CLIs with a colliding `manifest` command, and a two-repository dance for changes
|
|
502
|
-
that touched a single idea.
|
|
503
|
-
|
|
504
|
-
## 1. Dependencies
|
|
505
|
-
|
|
506
|
-
Drop `@heroiclands/content-build` and move to 3.0.0:
|
|
507
|
-
|
|
508
|
-
```diff
|
|
509
|
-
"devDependencies": {
|
|
510
|
-
- "@heroiclands/content-build": "^1.8.2",
|
|
511
|
-
- "@heroiclands/package-build": "^0.6.1"
|
|
512
|
-
+ "@heroiclands/package-build": "^3.0.0"
|
|
513
|
-
}
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
## 2. Import specifiers
|
|
517
|
-
|
|
518
|
-
Every `@heroiclands/content-build/*` specifier becomes
|
|
519
|
-
`@heroiclands/package-build/*`. Subpaths are otherwise unchanged — `engine/*`,
|
|
520
|
-
`sohl/*`, `prettier` and `markdownlint` all keep their names:
|
|
521
|
-
|
|
522
|
-
```diff
|
|
523
|
-
-import { positionOfLiteral } from "@heroiclands/content-build/engine/diagnostics";
|
|
524
|
-
+import { positionOfLiteral } from "@heroiclands/package-build/engine/diagnostics";
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
**One subpath moved.** Both packages exported a `./config`, meaning different
|
|
528
|
-
things, so the content one is now `./content-config`. `./config` remains the
|
|
529
|
-
packaging configuration it always was, and consumers of it need no change:
|
|
530
|
-
|
|
531
|
-
```diff
|
|
532
|
-
-import { defineConfig } from "@heroiclands/content-build/config";
|
|
533
|
-
+import { defineConfig } from "@heroiclands/package-build/content-config";
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
`defineConfig` is also re-exported from the package root, so
|
|
537
|
-
`import { defineConfig } from "@heroiclands/package-build"` works too.
|
|
538
|
-
|
|
539
|
-
A mechanical pass over a consumer:
|
|
540
|
-
|
|
541
|
-
```bash
|
|
542
|
-
git ls-files -z '*.mjs' '*.ts' | xargs -0 perl -pi -e \
|
|
543
|
-
's{\@heroiclands/content-build/config}{\@heroiclands/package-build/content-config}g;
|
|
544
|
-
s{\@heroiclands/content-build}{\@heroiclands/package-build}g'
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
Review the result rather than trusting it — a changelog or a historical comment
|
|
548
|
-
that names the old package is usually meant to keep naming it.
|
|
549
|
-
|
|
550
|
-
## 3. The CLI
|
|
551
|
-
|
|
552
|
-
**Both commands still exist and behave identically.** `content-build` and
|
|
553
|
-
`package-build` are both bin entries of the merged package, so scripts calling
|
|
554
|
-
either keep working:
|
|
555
|
-
|
|
556
|
-
```jsonc
|
|
557
|
-
"scripts": {
|
|
558
|
-
"build:compiledb": "content-build package compile", // unchanged
|
|
559
|
-
"build:manifest": "package-build manifest" // unchanged
|
|
560
|
-
}
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
Unifying the two into one noun-namespaced CLI — and resolving the `manifest`
|
|
564
|
-
collision, where `content-build manifest` emits the cross-package link manifest
|
|
565
|
-
and `package-build manifest` generates `module.json` — is deliberately _not_
|
|
566
|
-
part of this release. It is a behavior change and gets its own.
|
|
567
|
-
|
|
568
|
-
## 4. Rename the configuration file
|
|
569
|
-
|
|
570
|
-
**Required.** The config stem follows the package:
|
|
571
|
-
|
|
572
|
-
```bash
|
|
573
|
-
git mv content-build.config.yaml package-build.config.yaml # or .yml / .mjs
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
The old stem is **not** accepted. A deprecation window would let a repository
|
|
577
|
-
sit indefinitely on a filename naming a package that no longer exists, and this
|
|
578
|
-
upgrade already requires touching the manifest and the imports — one more `git
|
|
579
|
-
mv` is not what makes it expensive.
|
|
580
|
-
|
|
581
|
-
If a build cannot find the file it says so by name:
|
|
582
|
-
|
|
583
|
-
```
|
|
584
|
-
package-build: no package-build.config.yaml or package-build.config.yml or
|
|
585
|
-
package-build.config.mjs found at or above …
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
Two configs in one directory is still an error rather than a precedence
|
|
589
|
-
question, so a half-finished rename fails loudly instead of quietly building
|
|
590
|
-
from the file you stopped editing.
|
|
591
|
-
|
|
592
|
-
**Every key inside the file is unchanged**, including the `packageBuild:`
|
|
593
|
-
section — which is no longer a block reserved for a separate toolchain, just a
|
|
594
|
-
section.
|
|
595
|
-
|
|
596
|
-
The `CONTENT_BUILD_CONFIG` environment variable, which names the file
|
|
597
|
-
explicitly when a repository keeps it somewhere else, is now
|
|
598
|
-
`PACKAGE_BUILD_CONFIG`. The old name is not read.
|
|
599
|
-
|
|
600
|
-
## What did not change
|
|
601
|
-
|
|
602
|
-
- Every configuration key, and the shape of the whole file — only its name moved.
|
|
603
|
-
- Every CLI command, flag and exit code.
|
|
604
|
-
- Every engine and `sohl` module, and what it exports.
|
|
605
|
-
- The Foundry manifest, the packs it declares, and every compiled document id.
|
|
606
|
-
|
|
607
|
-
A world that resolved `Compendium.<package>.<pack>.<Type>.<id>` before resolves
|
|
608
|
-
it after; nothing about compiled output moved.
|