@heroiclands/package-build 22.3.0 → 22.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.
@@ -46,25 +46,24 @@ export function collectHomepages(contentBase: string, ctx: object): {
46
46
  addressFindings: object[];
47
47
  };
48
48
  /**
49
- * Writes each homepage at its address, below the package's own root.
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, no section landing and no link resolution — so
53
- * routing it through {@link renderPages} would buy it a pipeline it has no input
54
- * for, and would make homepage-only mode depend on the index, the foreign
55
- * manifests and the table universe that mode exists to not build.
56
- *
57
- * **Verbatim is the answer, not a gap.** A landing's links
58
- * could not be *resolved* here without giving `homepage` mode the index its
59
- * licensing fence exists to not build, so they are **checked** instead:
60
- * {@link auditHomepageLinks} reads the `landing:` addresses and the body's
61
- * markdown links, and reports a wikilink on the page rather than resolving one.
62
- *
63
- * **Its destination is no longer fixed**. The file is written at the
64
- * note's address, flat at the package's site root, and the page states that
65
- * address as its `url` — the same separation of file from URL every other page
66
- * has. Nothing is written at `/<package>/` itself: that becomes a redirect the
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, or no section to be filed under — would silently drop a page.
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
- * theme reads: `breadcrumbs.html` builds its middle crumb from
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 now named
213
- * the same way, so the two agree. Filing it into `<section>/` so that
214
- * Hugo would read a section off its path; a section appears in no address, and
215
- * a directory chosen only to satisfy a rendering engine's idea of what a
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 rather than a section-relative half of it, so
219
- * two types cannot fight over one file: a `doc` note's `subType` may be spelled
220
- * the same as another note's `type`, and `doc-gear.md` and `weapongear-gear.md`
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, hasTags }: {
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, { hasTags }?: {
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 a site with no tagged notes renders.
163
+ * The kinds no site renders.
175
164
  *
176
- * A section exists only where `site.sections` declares one, so a tree holding
177
- * only the homepage emits nothing beyond it; a taxonomy nobody's notes fill
178
- * and a feed would be empty shells. A site whose notes carry `tags:` emits
179
- * `taxonomy` and `term` after all see {@link hugoConfig} but `RSS` is
180
- * disabled either way: nothing here publishes a feed.
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 lifetime pinned on the prefix-root redirect, and why it is pinned.
21
+ * The `_headers` file's contents: the `noindex` rules, and nothing else.
32
22
  *
33
- * Cloudflare Pages sets no `Cache-Control` on a redirect it generates those
34
- * responses carry `location` and nothing else and a 301 with no lifetime is
35
- * cached by a browser indefinitely, on the most-linked URL there is. An hour
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(pkg: string): string;
29
+ export function headers(): string;
60
30
  /**
61
- * Write `_headers` and `_redirects` beside the rendered site.
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