@heroiclands/package-build 22.3.1 → 22.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/CONTENT.md +189 -306
- package/bin/content-build.mjs +15 -20
- package/bin/package-build.mjs +87 -3
- package/content-config.mjs +70 -179
- package/docs/api.md +27 -32
- package/docs/commands.md +98 -19
- package/docs/configuration.md +90 -126
- package/docs/content-format.md +25 -15
- package/docs/getting-started.md +5 -4
- package/docs/project-setup.md +1 -1
- package/engine/actor-compiler.mjs +53 -14
- package/engine/changelog-lint.mjs +629 -0
- package/engine/content-links.mjs +25 -60
- package/engine/diagnostics.mjs +2 -2
- package/engine/field-reference.mjs +7 -1
- package/engine/homepage.mjs +91 -172
- package/engine/metadata-index.mjs +7 -3
- package/engine/note-vocabulary.mjs +0 -20
- package/engine/pdf-build.mjs +2 -2
- package/engine/site-build.mjs +64 -225
- package/engine/site-config.mjs +15 -53
- package/engine/site-root.mjs +26 -70
- package/githooks/pre-commit +53 -2
- package/package.json +1 -1
- package/types/content-config.d.mts +6 -8
- package/types/engine/actor-compiler.d.mts +42 -9
- package/types/engine/changelog-lint.d.mts +50 -0
- package/types/engine/content-links.d.mts +12 -23
- package/types/engine/diagnostics.d.mts +2 -2
- package/types/engine/homepage.d.mts +51 -91
- package/types/engine/note-vocabulary.d.mts +0 -12
- package/types/engine/site-build.d.mts +28 -129
- package/types/engine/site-config.d.mts +10 -19
- package/types/engine/site-root.d.mts +11 -36
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The file a homepage is written to, relative to the package's site root.
|
|
3
|
-
*
|
|
4
|
-
* Its **address**, flat at the package root, and stated in the page's own `url`
|
|
5
|
-
* — the same separation every other page has, where the directory
|
|
6
|
-
* decides the Hugo section and the front matter decides the URL. Flat rather
|
|
7
|
-
* than inside a `homepage/` section directory, because a homepage is not one of
|
|
8
|
-
* a kind: a section holding exactly one page would publish a landing at
|
|
9
|
-
* `/<package>/kb/homepage/` that nothing links to and nobody wrote.
|
|
10
|
-
*
|
|
11
|
-
* @param {object} fm - Parsed frontmatter.
|
|
12
|
-
* @returns {string} The destination filename, e.g. `homepage-root.md`.
|
|
13
|
-
* @throws {Error} When the note declares no shortcode, and so has no address.
|
|
14
|
-
*/
|
|
15
|
-
export function homepageDestination(fm: object): string;
|
|
16
1
|
/**
|
|
17
2
|
* Whether a note's frontmatter declares the homepage type.
|
|
18
3
|
*
|
|
@@ -24,7 +9,7 @@ export function isHomepage(fm: object | null | undefined): boolean;
|
|
|
24
9
|
* What the address rule says about one note's top-level fields.
|
|
25
10
|
*
|
|
26
11
|
* Two statements about the same thing, so they are made together: the field a
|
|
27
|
-
* homepage **owes** and the
|
|
12
|
+
* homepage **owes** and the fields it may **not** write.
|
|
28
13
|
*
|
|
29
14
|
* The missing `shortcode` comes first, and is located at `type:` rather than at
|
|
30
15
|
* a key that is not there — the `homepage` value is what makes the field
|
|
@@ -34,8 +19,9 @@ export function isHomepage(fm: object | null | undefined): boolean;
|
|
|
34
19
|
* diagnostic per finding walks down the file.
|
|
35
20
|
*
|
|
36
21
|
* Presence is the whole test for a refused field, and absence-or-blank for the
|
|
37
|
-
* required one: `shortcode:` authored empty is no address, and
|
|
38
|
-
* make `id` mean something on a page that compiles to no document
|
|
22
|
+
* required one: `shortcode:` authored empty is no address, and no value can
|
|
23
|
+
* make `id` or `landing` mean something on a page that compiles to no document
|
|
24
|
+
* and renders as its body.
|
|
39
25
|
*
|
|
40
26
|
* Each finding carries the `locator` key to position it at, because the two
|
|
41
27
|
* things that would resolve one — the raw note text and the position helper —
|
|
@@ -79,13 +65,11 @@ export function checkHomepageAddressFields(fm: object | null | undefined, { isAu
|
|
|
79
65
|
* this exists to prevent, and it is silent — the site build reports `wrote 0
|
|
80
66
|
* homepage(s)` and exits 0.
|
|
81
67
|
* - _Two_ and it serves a page nobody chose. **This is a cardinality rule, and
|
|
82
|
-
* only that.**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* name is a question nothing here can answer, and both being reachable is
|
|
88
|
-
* not an answer to it.
|
|
68
|
+
* only that.** Both are written to the mount's `_index.md`, so the second
|
|
69
|
+
* silently overwrites the first; the duplicate-address check catches only
|
|
70
|
+
* the pair that happen to share a shortcode, and says nothing at all about
|
|
71
|
+
* a `homepage-root` beside a `homepage-front`. Which of the two should be
|
|
72
|
+
* the front page is a question nothing here can answer.
|
|
89
73
|
*
|
|
90
74
|
* Neither has a safe default, so neither is a warning. A warning is the right
|
|
91
75
|
* severity for something a build can proceed past correctly, and a build that
|
|
@@ -149,24 +133,15 @@ export function homepageTitle(fm: object | null | undefined, config: object): st
|
|
|
149
133
|
/**
|
|
150
134
|
* The frontmatter a homepage publishes with.
|
|
151
135
|
*
|
|
152
|
-
* The note's own, plus the derived values every emitted page carries: the
|
|
153
|
-
* resolved `title`, the package the build derived — no note declares one
|
|
136
|
+
* The note's own, plus the two derived values every emitted page carries: the
|
|
137
|
+
* resolved `title`, and the package the build derived — no note declares one
|
|
154
138
|
* (`package:` is retired) and the theme's breadcrumb partial reads
|
|
155
|
-
* `.Params.package
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* for one; it decides nothing while `url` is present, but a page carrying only
|
|
162
|
-
* `url` would report a slug Hugo had inferred from the filename.
|
|
163
|
-
*
|
|
164
|
-
* **Site-root relative, and so carrying no package base**, exactly as
|
|
165
|
-
* `pageFrontmatter` states a content page's: Hugo resolves a `url`
|
|
166
|
-
* against `baseURL`, whose path is already where the package is served, so a
|
|
167
|
-
* stated base was written twice and published the landing at
|
|
168
|
-
* `/<package>/<package>/homepage-root/`. Where the package is served is what
|
|
169
|
-
* every *href* is composed from and it reaches this page's address not at all.
|
|
139
|
+
* `.Params.package`.
|
|
140
|
+
*
|
|
141
|
+
* **No `url` and no `slug`.** Hugo publishes the `home` kind at `baseURL`,
|
|
142
|
+
* whose path is already where the package is served, so the page has no
|
|
143
|
+
* address to state; a content page states one because its file sits under the
|
|
144
|
+
* mount and its address does not.
|
|
170
145
|
*
|
|
171
146
|
* An authored `aliases` is dropped for the same reason it is on every other
|
|
172
147
|
* page: Hugo reads it as URL redirects, so passing it through would publish a
|
|
@@ -178,43 +153,33 @@ export function homepageTitle(fm: object | null | undefined, config: object): st
|
|
|
178
153
|
* @param {string} options.contentPackage - The package this build publishes.
|
|
179
154
|
* @param {string} options.title - The resolved title.
|
|
180
155
|
* @returns {object} The frontmatter to write.
|
|
181
|
-
* @throws {Error} When the note declares no shortcode, and so has no address.
|
|
182
156
|
*/
|
|
183
157
|
export function homepageFrontmatter(fm: object, { contentPackage, title }: {
|
|
184
158
|
contentPackage: string;
|
|
185
159
|
title: string;
|
|
186
160
|
}): object;
|
|
187
161
|
/**
|
|
188
|
-
* Every address a homepage carries
|
|
189
|
-
*
|
|
190
|
-
* **Both halves of the page are in scope, and that is the finding rather than
|
|
191
|
-
* the assumption.** Of the six homepages authored today, four carry every link
|
|
192
|
-
* in the body as ordinary markdown and two carry them in `landing:` — and the
|
|
193
|
-
* one whose dead links prompted the check has an *empty body*, so a body-only
|
|
194
|
-
* reading would have found nothing at all on it. A dead link in a card is
|
|
195
|
-
* exactly as broken as one in a paragraph.
|
|
162
|
+
* Every address a homepage carries: the markdown links in its body.
|
|
196
163
|
*
|
|
197
|
-
*
|
|
198
|
-
* the
|
|
164
|
+
* Nowhere else: the frontmatter holds no address, because a homepage is a
|
|
165
|
+
* page with a body and the card block that once carried links is refused.
|
|
166
|
+
* Top-level `title` and `description` are not walked — they are set as text,
|
|
167
|
+
* never rendered as markdown — and `banner:` is not an address: it is an image
|
|
168
|
+
* path resolved through the CDN base, and `banner: none` is a sentinel rather
|
|
169
|
+
* than a target.
|
|
199
170
|
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* browser against the landing's own address, which *is* the package root, so
|
|
204
|
-
* a relative one means the same thing a `url` does.
|
|
171
|
+
* A body link is emitted as written and resolved by the browser against the
|
|
172
|
+
* homepage's own address, which *is* the package root, so a package-relative
|
|
173
|
+
* one (`kb/rules/`) lands where a reader expects.
|
|
205
174
|
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* `title` and `description` are not walked either — they are set as text, never
|
|
209
|
-
* rendered as markdown.
|
|
175
|
+
* Links inside code are ignored, so an example in a fenced block is not
|
|
176
|
+
* reported as a dead address.
|
|
210
177
|
*
|
|
211
|
-
* @param {object|null|undefined} fm - The note's frontmatter.
|
|
212
178
|
* @param {string} [body] - The note's markdown body.
|
|
213
179
|
* @returns {Array<{field: string, url: string, kind: string}>} Every address,
|
|
214
|
-
*
|
|
215
|
-
* written at.
|
|
180
|
+
* in body order, each recorded at `field: "body"` with `kind: "body"`.
|
|
216
181
|
*/
|
|
217
|
-
export function homepageAddresses(
|
|
182
|
+
export function homepageAddresses(body?: string): Array<{
|
|
218
183
|
field: string;
|
|
219
184
|
url: string;
|
|
220
185
|
kind: string;
|
|
@@ -250,17 +215,28 @@ export const HOMEPAGE_FIELDS: readonly import("./field-spec.mjs").FieldSpec[];
|
|
|
250
215
|
*/
|
|
251
216
|
export const HOMEPAGE_SHORTCODE: string;
|
|
252
217
|
/**
|
|
253
|
-
* The
|
|
218
|
+
* The file a homepage is written to, relative to the package's site root.
|
|
254
219
|
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
* destination
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* everywhere else and are permitted.
|
|
220
|
+
* The mount's own `_index.md`: Hugo renders it as the `home` kind, at
|
|
221
|
+
* `baseURL` — which is `/<package>/`, the package's own address. One fixed
|
|
222
|
+
* destination rather than one derived from the note's address, because the
|
|
223
|
+
* homepage's address *is* the package root; the note's `shortcode` names the
|
|
224
|
+
* page in links and decides no file.
|
|
261
225
|
*
|
|
262
|
-
*
|
|
263
|
-
|
|
226
|
+
* @type {string}
|
|
227
|
+
*/
|
|
228
|
+
export const HOMEPAGE_DESTINATION: string;
|
|
229
|
+
/**
|
|
230
|
+
* The top-level fields a homepage refuses, and what each would decide.
|
|
231
|
+
*
|
|
232
|
+
* `id` is the Foundry document id a compendium UUID is built from, and a
|
|
233
|
+
* homepage compiles into no document. `landing` is a card block; the homepage
|
|
234
|
+
* is a page with a body, rendered as one, so nothing reads it — and an index
|
|
235
|
+
* of what the package publishes is a `doc` note carrying a content table,
|
|
236
|
+
* authored where every other page is.
|
|
237
|
+
*
|
|
238
|
+
* `name` and `shortcode` are permitted: the shortcode is what a link is
|
|
239
|
+
* written with, and `name` titles the page like every other note's.
|
|
264
240
|
*
|
|
265
241
|
* **A named class, not an allow-list, and that boundary is the decision.** A
|
|
266
242
|
* homepage's frontmatter is *emitted into the published page*
|
|
@@ -276,19 +252,3 @@ export const HOMEPAGE_SHORTCODE: string;
|
|
|
276
252
|
* @type {ReadonlyMap<string, string>}
|
|
277
253
|
*/
|
|
278
254
|
export const HOMEPAGE_REFUSED_FIELDS: ReadonlyMap<string, string>;
|
|
279
|
-
/**
|
|
280
|
-
* The two frontmatter keys that hold an address, and what each one means.
|
|
281
|
-
*
|
|
282
|
-
* They are **not** interchangeable, and a check that treated them as one would
|
|
283
|
-
* be wrong about both. The theme resolves a `url` against the site with
|
|
284
|
-
* `relURL`, so a package writes `kb/rules/` and is served `/sohl/kb/rules/`
|
|
285
|
-
* without ever naming its own prefix. An `href` is an address that is *already*
|
|
286
|
-
* resolved and is used verbatim — which is what `cards.source: sections` fills
|
|
287
|
-
* in, since a section's permalink already carries the prefix.
|
|
288
|
-
*
|
|
289
|
-
* So a leading `/` is a defect in a `url` (it is prefixed a second time) and
|
|
290
|
-
* correct in an `href`.
|
|
291
|
-
*
|
|
292
|
-
* @type {ReadonlySet<string>}
|
|
293
|
-
*/
|
|
294
|
-
export const HOMEPAGE_ADDRESS_KEYS: ReadonlySet<string>;
|
|
@@ -50,18 +50,6 @@ export function exclusiveTagGroups(type: string, groups?: object): {
|
|
|
50
50
|
* @returns {boolean} Whether the note carries it.
|
|
51
51
|
*/
|
|
52
52
|
export function hasTag(fm: object | null | undefined, tag: string): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Whether a note carries any `tags:` at all, however authored.
|
|
55
|
-
*
|
|
56
|
-
* The one question the site build asks of tags in aggregate — whether the
|
|
57
|
-
* tree publishes taxonomy pages — rather than about a particular tag. Reads
|
|
58
|
-
* `tags` and `tag` exactly as {@link hasTag} does, and treats an empty list
|
|
59
|
-
* or a blank string as carrying none.
|
|
60
|
-
*
|
|
61
|
-
* @param {object|null|undefined} fm - Parsed frontmatter.
|
|
62
|
-
* @returns {boolean} Whether the note carries at least one tag.
|
|
63
|
-
*/
|
|
64
|
-
export function hasAnyTag(fm: object | null | undefined): boolean;
|
|
65
53
|
/**
|
|
66
54
|
* Whether a note is tagged as an unfinished **draft**.
|
|
67
55
|
*
|
|
@@ -46,25 +46,24 @@ export function collectHomepages(contentBase: string, ctx: object): {
|
|
|
46
46
|
addressFindings: object[];
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
49
|
-
* Writes each homepage
|
|
49
|
+
* Writes each homepage as the package root's `_index.md`.
|
|
50
50
|
*
|
|
51
51
|
* Its own writer, deliberately small. A homepage is authored markdown published
|
|
52
|
-
* verbatim — no table expansion
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* **Verbatim is the answer, not a gap.** A
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* {@link auditHomepageLinks} reads the
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* **Its destination is
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* package's own repository authors, which is a routing fact rather than a page.
|
|
52
|
+
* verbatim — no table expansion and no link resolution — so routing it through
|
|
53
|
+
* {@link renderPages} would buy it a pipeline it has no input for, and would
|
|
54
|
+
* make homepage-only mode depend on the index, the foreign manifests and the
|
|
55
|
+
* table universe that mode exists to not build.
|
|
56
|
+
*
|
|
57
|
+
* **Verbatim is the answer, not a gap.** A homepage's links could not be
|
|
58
|
+
* *resolved* here without giving `homepage` mode the index its licensing fence
|
|
59
|
+
* exists to not build, so they are **checked** instead:
|
|
60
|
+
* {@link auditHomepageLinks} reads the body's markdown links, and reports a
|
|
61
|
+
* wikilink on the page rather than resolving one.
|
|
62
|
+
*
|
|
63
|
+
* **Its destination is fixed**: {@link HOMEPAGE_DESTINATION}, at the package's
|
|
64
|
+
* site root, which Hugo renders as the `home` kind at `/<package>/`. The page
|
|
65
|
+
* states no `url` — the home kind has none to state — and the mount below it
|
|
66
|
+
* holds pages and nothing else, so this is the only `_index.md` in the tree.
|
|
68
67
|
*
|
|
69
68
|
* @param {string} outRoot - The package's site root — the content mount's
|
|
70
69
|
* root, `build/hugo/content`, one level above the mount itself.
|
|
@@ -84,7 +83,7 @@ export function writeHomepages(outRoot: string, pages: readonly object[], config
|
|
|
84
83
|
* - **Frontmatter wikilinks** first, because frontmatter is copied to the page
|
|
85
84
|
* verbatim and a link written in one reaches the reader as literal `[[…]]`.
|
|
86
85
|
* - **Addresses** next: a note that has no address — no shortcode to be
|
|
87
|
-
* addressed by
|
|
86
|
+
* addressed by — would silently drop a page.
|
|
88
87
|
* There is no collision gate beside it: an address is `(type, shortcode)`,
|
|
89
88
|
* which is unique within a package by rule, so two pages cannot claim one URL.
|
|
90
89
|
* - **Foreign manifests** last, in two steps. *Unusable* is a file this build
|
|
@@ -125,31 +124,6 @@ export function gatesFailed(gates: any): boolean;
|
|
|
125
124
|
* @returns {Map<string, object[]>} Package → the notes it may tabulate.
|
|
126
125
|
*/
|
|
127
126
|
export function tableUniverse(pages: object[]): Map<string, object[]>;
|
|
128
|
-
/**
|
|
129
|
-
* The front matter a section's landing states about itself.
|
|
130
|
-
*
|
|
131
|
-
* The section metadata a configuration resolved, ready to be written or merged
|
|
132
|
-
* onto a page. Two things happen here and nothing else does:
|
|
133
|
-
*
|
|
134
|
-
* - **`title` leads.** It is the one key every landing has carried since the
|
|
135
|
-
* first one, and a landing whose block opened with `banner:` would be a
|
|
136
|
-
* gratuitous diff on every consumer's tree.
|
|
137
|
-
* - **An absent value is left off**, not written as `undefined` — which is not
|
|
138
|
-
* a value YAML can carry, and would abort the serializer.
|
|
139
|
-
*
|
|
140
|
-
* Everything else the section declared is passed through. That is the point of
|
|
141
|
-
* the function: two writers transcribing `title` and `banner` by
|
|
142
|
-
* name, so the vocabulary lived in three places — the schema that admits a key
|
|
143
|
-
* and the two writers that copy it — and a key added to the schema alone
|
|
144
|
-
* validated cleanly and then reached no page. The *schema* is the bound worth
|
|
145
|
-
* keeping (see `normalizeSectionMeta`, which refuses a key it does not know and
|
|
146
|
-
* names it); a second, silent bound in the writers is not.
|
|
147
|
-
*
|
|
148
|
-
* @param {object} meta - A resolved `site.sections` / `site.readmeSections`
|
|
149
|
-
* entry.
|
|
150
|
-
* @returns {object} Its front matter, `title` first.
|
|
151
|
-
*/
|
|
152
|
-
export function sectionFrontmatter(meta: object): object;
|
|
153
127
|
/**
|
|
154
128
|
* The frontmatter a page publishes with.
|
|
155
129
|
*
|
|
@@ -180,10 +154,8 @@ export function sectionFrontmatter(meta: object): object;
|
|
|
180
154
|
* A content page carries the package the build **derived**. No note
|
|
181
155
|
* declares one — `package:` is retired — so the note's frontmatter alone
|
|
182
156
|
* would publish a page that does not say which package it belongs to. The
|
|
183
|
-
* emitted page is what a
|
|
184
|
-
*
|
|
185
|
-
* `.Params.package`, so without it that crumb degrades from a linked, labelled
|
|
186
|
-
* section to a bare type slug. Writing the derived value keeps a page
|
|
157
|
+
* emitted page is what a theme reads: `breadcrumbs.html` reads
|
|
158
|
+
* `.Params.package`. Writing the derived value keeps a page
|
|
187
159
|
* self-describing and makes sweeping the field out of a content tree
|
|
188
160
|
* output-preserving for a site as it already is for the packs.
|
|
189
161
|
*
|
|
@@ -209,16 +181,15 @@ export function pageFrontmatter(page: object, { decorate, webSrc, artSrc }: {
|
|
|
209
181
|
* Where a page is written, relative to the output root.
|
|
210
182
|
*
|
|
211
183
|
* **Flat, under the mount, named by its address**. A content page's URL
|
|
212
|
-
* is its address — `/<package>/<type>-<shortcode>/` — and the file is
|
|
213
|
-
* the same way, so the two agree.
|
|
214
|
-
* Hugo
|
|
215
|
-
* a directory chosen only to satisfy a rendering engine's idea
|
|
216
|
-
* section is has no business in the note format.
|
|
184
|
+
* is its address — `/<package>/<type>-<shortcode>/` — and the file is named
|
|
185
|
+
* the same way, so the two agree. No page creates a directory: a section is
|
|
186
|
+
* a Hugo listing over a content directory, the `section` kind is disabled on
|
|
187
|
+
* every site, and a directory chosen only to satisfy a rendering engine's idea
|
|
188
|
+
* of what a section is has no business in the note format.
|
|
217
189
|
*
|
|
218
|
-
* The name is the *whole* address
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
* are distinct whatever the sections.
|
|
190
|
+
* The name is the *whole* address, so two types cannot fight over one file: a
|
|
191
|
+
* `doc` note's `subType` may be spelled the same as another note's `type`, and
|
|
192
|
+
* `doc-gear.md` and `weapongear-gear.md` are distinct.
|
|
222
193
|
*
|
|
223
194
|
* @param {object} page - The page.
|
|
224
195
|
* @returns {string} The file, relative to the mount.
|
|
@@ -251,74 +222,6 @@ export function renderPages(pages: object[], options: object): {
|
|
|
251
222
|
wikiErrors: object[];
|
|
252
223
|
imageErrors: object[];
|
|
253
224
|
};
|
|
254
|
-
/**
|
|
255
|
-
* Writes the Hugo sections a published tree declares.
|
|
256
|
-
*
|
|
257
|
-
* **This is where a section lives now, and the only place**. A content
|
|
258
|
-
* note carries none: it is addressed by `(type, shortcode)` and emitted flat
|
|
259
|
-
* under the mount, so nothing a page does creates a directory. A site that wants
|
|
260
|
-
* `/<package>/<prefix><section>/` to answer — with a title, a hero, and whatever
|
|
261
|
-
* listing its layout builds — says so here, in configuration, and this writes
|
|
262
|
-
* the `_index.md` that makes Hugo agree it is a section.
|
|
263
|
-
*
|
|
264
|
-
* Three jobs, all of them Hugo's directory semantics rather than the note
|
|
265
|
-
* format's:
|
|
266
|
-
*
|
|
267
|
-
* - **The mount's own landing**, so `/<package>/<prefix>` is a page rather than
|
|
268
|
-
* a directory listing. It carries a `type` of its own: Hugo's template lookup
|
|
269
|
-
* walks up a page's path, so an untyped landing template at the mount would
|
|
270
|
-
* also serve every section below it that has none.
|
|
271
|
-
* - **Declared sections** get a titled `_index.md` with their hero, so a landing
|
|
272
|
-
* matches the card that links to it instead of showing Hugo's auto-humanised
|
|
273
|
-
* directory name. The body is empty, which lets the theme decide what to list.
|
|
274
|
-
* - **Every other directory directly under the mount** gets a bare `_index.md`,
|
|
275
|
-
* or its own address publishes nothing. Hugo generates a section page
|
|
276
|
-
* automatically only for a *top-level* content directory; below that, a
|
|
277
|
-
* directory without an `_index.md` is not a section, so its URL 404s while its
|
|
278
|
-
* children publish normally. With content pages flat, no note creates a
|
|
279
|
-
* directory below the mount, so this reaches only what something else
|
|
280
|
-
* placed there.
|
|
281
|
-
*
|
|
282
|
-
* **A section listing is not a page listing any more.** A layout that reads
|
|
283
|
-
* `.Pages` off a section it declares here will find nothing, because no file is
|
|
284
|
-
* filed into it; one that queries `site.RegularPages` by `Params.type` — which
|
|
285
|
-
* is how `sohl`'s eleven catalog layouts already work — is unaffected. That is a
|
|
286
|
-
* consumer's layout to choose, and it is stated here because the choice is no
|
|
287
|
-
* longer free.
|
|
288
|
-
*
|
|
289
|
-
* Scoped to one level on purpose. A directory further down was not a section
|
|
290
|
-
* before either, and giving it one here would silently re-scope the prev/next
|
|
291
|
-
* navigation of every page inside it.
|
|
292
|
-
*
|
|
293
|
-
* @param {string} outRoot - The mount directory.
|
|
294
|
-
* @param {object} options
|
|
295
|
-
* @param {Record<string, object>} [options.sections] - The declared sections,
|
|
296
|
-
* each written as a titled `_index.md` carrying its own frontmatter.
|
|
297
|
-
* @param {object} [options.landing] - The mount's own landing frontmatter.
|
|
298
|
-
* Omitted, the mount gets no `_index.md` of its own.
|
|
299
|
-
* @param {((name: string) => string)|null} [options.sectionTitle] - Titles a
|
|
300
|
-
* directory below the mount that declared no section. `null` leaves such a
|
|
301
|
-
* directory without an `_index.md`.
|
|
302
|
-
* @returns {number} How many landings were written.
|
|
303
|
-
*/
|
|
304
|
-
export function writeSectionLandings(outRoot: string, { sections, landing, sectionTitle }: {
|
|
305
|
-
sections?: Record<string, object> | undefined;
|
|
306
|
-
landing?: object | undefined;
|
|
307
|
-
sectionTitle?: ((name: string) => string) | null | undefined;
|
|
308
|
-
}): number;
|
|
309
|
-
/**
|
|
310
|
-
* A section landing's title, from its directory name — `macro` → `Macros`.
|
|
311
|
-
*
|
|
312
|
-
* Hugo derives exactly this for a section page it generates itself, but not for
|
|
313
|
-
* one backed by an `_index.md`: an explicit file with no `title` renders a blank
|
|
314
|
-
* heading. So a backfilled landing states its own, in plain English
|
|
315
|
-
* pluralisation rather than Hugo's inflector, which spells that section
|
|
316
|
-
* "Macroes".
|
|
317
|
-
*
|
|
318
|
-
* @param {string} name - The directory name.
|
|
319
|
-
* @returns {string} The display title.
|
|
320
|
-
*/
|
|
321
|
-
export function pluralTitle(name: string): string;
|
|
322
225
|
/**
|
|
323
226
|
* Resolves `site.pass` to its bundle.
|
|
324
227
|
*
|
|
@@ -346,10 +249,7 @@ export function resolveSitePass(name: string | undefined, options: object): {
|
|
|
346
249
|
* `sql` directive with none prepared is a table error: nothing here runs a
|
|
347
250
|
* query.
|
|
348
251
|
* @returns {{gates: object, stats: object|null, tableErrors: object[],
|
|
349
|
-
* wikiErrors: object[], imageErrors: object[], manifests: object|null
|
|
350
|
-
* hasTags: boolean}} `hasTags` is whether any note the walk read carries
|
|
351
|
-
* `tags:` — what {@link module:engine/site-config.hugoConfig} reads to
|
|
352
|
-
* decide whether the site emits taxonomy pages.
|
|
252
|
+
* wikiErrors: object[], imageErrors: object[], manifests: object|null}}
|
|
353
253
|
*/
|
|
354
254
|
export function buildSite({ config, sqlTables }?: {
|
|
355
255
|
config?: object | undefined;
|
|
@@ -361,7 +261,6 @@ export function buildSite({ config, sqlTables }?: {
|
|
|
361
261
|
wikiErrors: object[];
|
|
362
262
|
imageErrors: object[];
|
|
363
263
|
manifests: object | null;
|
|
364
|
-
hasTags: boolean;
|
|
365
264
|
};
|
|
366
265
|
export { formatUnaddressableFinding };
|
|
367
266
|
import { formatUnaddressableFinding } from "./metadata-index.mjs";
|
|
@@ -91,19 +91,15 @@ export function resolveThemesDir(rootDir: string): string;
|
|
|
91
91
|
* @param {object} options.config - The resolved build configuration.
|
|
92
92
|
* @param {readonly NavigationEntry[]} options.navigation - The navigation.
|
|
93
93
|
* @param {string} options.themesDir - From {@link resolveThemesDir}.
|
|
94
|
-
* @param {boolean} [options.hasTags] - Whether any note the site build walked
|
|
95
|
-
* carries `tags:`, from {@link module:engine/site-build.buildSite}'s
|
|
96
|
-
* `hasTags`. Defaults to `false` — no tagged note, no taxonomy pages.
|
|
97
94
|
* @returns {Record<string, any>} The configuration Hugo reads.
|
|
98
95
|
* @throws {TypeError} When `homepage` fails `checkHomepage`, or the
|
|
99
96
|
* configuration declares no `packageBuild.manifest.title`, no
|
|
100
97
|
* `site.description`, or no `site.assets`.
|
|
101
98
|
*/
|
|
102
|
-
export function hugoConfig({ config, navigation, themesDir
|
|
99
|
+
export function hugoConfig({ config, navigation, themesDir }: {
|
|
103
100
|
config: object;
|
|
104
101
|
navigation: readonly NavigationEntry[];
|
|
105
102
|
themesDir: string;
|
|
106
|
-
hasTags?: boolean | undefined;
|
|
107
103
|
}): Record<string, any>;
|
|
108
104
|
/**
|
|
109
105
|
* The configuration as the TOML Hugo reads.
|
|
@@ -120,17 +116,10 @@ export function hugoToml(generated: Record<string, unknown>): string;
|
|
|
120
116
|
* run this before touching the output tree and fail with it intact.
|
|
121
117
|
*
|
|
122
118
|
* @param {object} config - The resolved build configuration.
|
|
123
|
-
* @param {object} [options] - Options.
|
|
124
|
-
* @param {boolean} [options.hasTags] - Whether any note the site build walked
|
|
125
|
-
* carries `tags:`. Defaults to `false`, so a caller generating the
|
|
126
|
-
* configuration before the walk (to fail fast on a missing source) gets the
|
|
127
|
-
* untagged shape; pass the site build's own `hasTags` once it is known.
|
|
128
119
|
* @returns {Record<string, any>} The configuration Hugo reads.
|
|
129
120
|
* @throws {Error} When any source is missing or wrong.
|
|
130
121
|
*/
|
|
131
|
-
export function generateHugoConfig(config: object,
|
|
132
|
-
hasTags?: boolean | undefined;
|
|
133
|
-
}): Record<string, any>;
|
|
122
|
+
export function generateHugoConfig(config: object): Record<string, any>;
|
|
134
123
|
/**
|
|
135
124
|
* Write `build/hugo/hugo.toml`.
|
|
136
125
|
*
|
|
@@ -171,13 +160,15 @@ export const BRAND: Readonly<{
|
|
|
171
160
|
discordURL: "https://discord.gg/EwMfkNd3az";
|
|
172
161
|
}>;
|
|
173
162
|
/**
|
|
174
|
-
* The kinds
|
|
163
|
+
* The kinds no site renders.
|
|
175
164
|
*
|
|
176
|
-
* A
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
165
|
+
* A site is its homepage and its pages: `home` and `page` are the only kinds,
|
|
166
|
+
* for every package and whatever its notes carry. A `section` is a listing
|
|
167
|
+
* Hugo would generate from a content directory; `taxonomy` and `term` are
|
|
168
|
+
* listings it would generate from `tags:`; `RSS` is a feed. Every structure
|
|
169
|
+
* between the homepage and the pages is authored instead, as a `doc` note
|
|
170
|
+
* carrying a content table — a tag is a field such a table filters on, not a
|
|
171
|
+
* page of its own.
|
|
181
172
|
*/
|
|
182
173
|
export const DISABLE_KINDS: readonly string[];
|
|
183
174
|
/**
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Where a package's landing is served, now that it is an addressed page.
|
|
3
|
-
*
|
|
4
|
-
* The site build emits the homepage at its own address rather than as the
|
|
5
|
-
* site root's `_index.md`, so the prefix root is a redirect to it.
|
|
6
|
-
*
|
|
7
|
-
* @param {string} pkg - The content package name.
|
|
8
|
-
* @returns {string} The landing's path.
|
|
9
|
-
*/
|
|
10
|
-
export function landingPath(pkg: string): string;
|
|
11
1
|
/**
|
|
12
2
|
* Suppress indexing of every address a deployment answers on but nobody
|
|
13
3
|
* advertises.
|
|
@@ -28,37 +18,22 @@ export function landingPath(pkg: string): string;
|
|
|
28
18
|
*/
|
|
29
19
|
export function noindexHeaders(): string[];
|
|
30
20
|
/**
|
|
31
|
-
* The
|
|
21
|
+
* The `_headers` file's contents: the `noindex` rules, and nothing else.
|
|
32
22
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* keeps the 301's canonical signal without the permanence.
|
|
23
|
+
* No `Cache-Control` is pinned on the prefix root. It is the homepage, and a
|
|
24
|
+
* lifetime on it would hold a stale copy at the most-linked address after a
|
|
25
|
+
* deploy; Pages' own defaults for a page apply.
|
|
37
26
|
*
|
|
38
|
-
* @param {string} pkg - The content package name.
|
|
39
|
-
* @returns {string[]} The header block's lines.
|
|
40
|
-
*/
|
|
41
|
-
export function cacheHeaders(pkg: string): string[];
|
|
42
|
-
/**
|
|
43
|
-
* Both forms of the prefix root, because Pages matches the raw path.
|
|
44
|
-
*
|
|
45
|
-
* Redirect matching runs before any trailing-slash or `index.html` handling, so
|
|
46
|
-
* `/<pkg>` and `/<pkg>/` are distinct keys and a rule on one does not catch the
|
|
47
|
-
* other.
|
|
48
|
-
*
|
|
49
|
-
* @param {string} pkg - The content package name.
|
|
50
|
-
* @returns {string} The `_redirects` file's contents.
|
|
51
|
-
*/
|
|
52
|
-
export function redirects(pkg: string): string;
|
|
53
|
-
/**
|
|
54
|
-
* The `_headers` file's contents.
|
|
55
|
-
*
|
|
56
|
-
* @param {string} pkg - The content package name.
|
|
57
27
|
* @returns {string} The file's contents.
|
|
58
28
|
*/
|
|
59
|
-
export function headers(
|
|
29
|
+
export function headers(): string;
|
|
60
30
|
/**
|
|
61
|
-
* Write `_headers`
|
|
31
|
+
* Write `_headers` beside the rendered site, and remove any `_redirects`.
|
|
32
|
+
*
|
|
33
|
+
* The removal is part of owning the root: a `_redirects` this build did not
|
|
34
|
+
* write is one an earlier build left, and Cloudflare Pages applies whatever
|
|
35
|
+
* sits there. Left in place it would redirect the prefix root — the homepage —
|
|
36
|
+
* to an address nothing publishes.
|
|
62
37
|
*
|
|
63
38
|
* @param {object} options - Options.
|
|
64
39
|
* @param {string} options.pkg - The content package name, which is also the
|