@heroiclands/package-build 22.1.0 → 22.2.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.
@@ -157,8 +157,8 @@ export function compareEmittedSystem({ system, artifact, documentType, subtype,
157
157
  * Two places to find it, because a system checks itself against source it owns
158
158
  * while a module checks against a dependency it fetched:
159
159
  *
160
- * - **A system**: its own `schema.json`, generated from its `src/` and
161
- * committed beside it.
160
+ * - **A system**: its own `schema.json`, generated from its `src/` into
161
+ * `build/` by `package-build schema`.
162
162
  * - **A module**: the copy cached by `content-build deps fetch`, from the
163
163
  * archive of the version it pins — which is what makes the comparison happen
164
164
  * at `verified` rather than against whatever the system's `main` holds today.
@@ -282,9 +282,9 @@ export function checkAuthoredSystemData(fm: object, { block, documentType, subTy
282
282
  * subtype declares.
283
283
  *
284
284
  * The build-time face of {@link compareEmittedSystem}: it resolves the schema
285
- * the way every other check here does — the system's own committed artifact, or
286
- * the cached one from the release a module pins — and attaches the message a
287
- * reader sees.
285
+ * the way every other check here does — the system's own published artifact,
286
+ * or the cached one from the release a module pins — and attaches the message
287
+ * a reader sees.
288
288
  *
289
289
  * **Silent where there is nothing to check against**, exactly as its two
290
290
  * siblings are: a module pinning a system version released before the artifact
@@ -396,7 +396,10 @@ export function resolveSitePass(name: string | undefined, options: object): {
396
396
  * `sql` directive with none prepared is a table error: nothing here runs a
397
397
  * query.
398
398
  * @returns {{gates: object, stats: object|null, tableErrors: object[],
399
- * wikiErrors: object[], imageErrors: object[], manifests: object|null}}
399
+ * wikiErrors: object[], imageErrors: object[], manifests: object|null,
400
+ * hasTags: boolean}} `hasTags` is whether any note the walk read carries
401
+ * `tags:` — what {@link module:engine/site-config.hugoConfig} reads to
402
+ * decide whether the site emits taxonomy pages.
400
403
  */
401
404
  export function buildSite({ config, sqlTables }?: {
402
405
  config?: object | undefined;
@@ -408,6 +411,7 @@ export function buildSite({ config, sqlTables }?: {
408
411
  wikiErrors: object[];
409
412
  imageErrors: object[];
410
413
  manifests: object | null;
414
+ hasTags: boolean;
411
415
  };
412
416
  export { formatUnaddressableFinding };
413
417
  import { formatUnaddressableFinding } from "./metadata-index.mjs";
@@ -89,18 +89,21 @@ export function resolveThemesDir(rootDir: string): string;
89
89
  *
90
90
  * @param {object} options - The sources.
91
91
  * @param {object} options.config - The resolved build configuration.
92
- * @param {string} [options.description] - `package.json`'s `description`.
93
92
  * @param {readonly NavigationEntry[]} options.navigation - The navigation.
94
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.
95
97
  * @returns {Record<string, any>} The configuration Hugo reads.
96
98
  * @throws {TypeError} When `homepage` fails `checkHomepage`, or the
97
- * configuration declares no `packageBuild.manifest.title`.
99
+ * configuration declares no `packageBuild.manifest.title`, no
100
+ * `site.description`, or no `site.assets`.
98
101
  */
99
- export function hugoConfig({ config, description, navigation, themesDir }: {
102
+ export function hugoConfig({ config, navigation, themesDir, hasTags }: {
100
103
  config: object;
101
- description?: string | undefined;
102
104
  navigation: readonly NavigationEntry[];
103
105
  themesDir: string;
106
+ hasTags?: boolean | undefined;
104
107
  }): Record<string, any>;
105
108
  /**
106
109
  * The configuration as the TOML Hugo reads.
@@ -112,16 +115,22 @@ export function hugoToml(generated: Record<string, unknown>): string;
112
115
  /**
113
116
  * The Hugo configuration, every source read from the repository.
114
117
  *
115
- * Reads `package.json`, the cached navigation and the installed theme's
116
- * location, and composes them with {@link hugoConfig}. Nothing is written, so
117
- * a caller can run this before touching the output tree and fail with it
118
- * intact.
118
+ * Reads the cached navigation and the installed theme's location, and
119
+ * composes them with {@link hugoConfig}. Nothing is written, so a caller can
120
+ * run this before touching the output tree and fail with it intact.
119
121
  *
120
122
  * @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.
121
128
  * @returns {Record<string, any>} The configuration Hugo reads.
122
129
  * @throws {Error} When any source is missing or wrong.
123
130
  */
124
- export function generateHugoConfig(config: object): Record<string, any>;
131
+ export function generateHugoConfig(config: object, { hasTags }?: {
132
+ hasTags?: boolean | undefined;
133
+ }): Record<string, any>;
125
134
  /**
126
135
  * Write `build/hugo/hugo.toml`.
127
136
  *
@@ -162,11 +171,13 @@ export const BRAND: Readonly<{
162
171
  discordURL: "https://discord.gg/EwMfkNd3az";
163
172
  }>;
164
173
  /**
165
- * The kinds no site renders.
174
+ * The kinds a site with no tagged notes renders.
166
175
  *
167
176
  * A section exists only where `site.sections` declares one, so a tree holding
168
- * only the homepage emits nothing beyond it; taxonomies and feeds would be
169
- * empty shells on every site.
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.
170
181
  */
171
182
  export const DISABLE_KINDS: readonly string[];
172
183
  /**
@@ -7,13 +7,18 @@
7
7
  * @param {Map<string, {package: string, type?: string}>} [options.foreignIndex]
8
8
  * The merged index from `loadForeignIndexes`. Omit when the build publishes
9
9
  * no cross-package links.
10
+ * @param {Set<string>} [options.noIndexPackages] - Packages declared
11
+ * `contentIndex: false` — a Foundry dependency only, with no fetched index.
12
+ * A link naming one fails naming the key, rather than reading as prose or an
13
+ * ordinary dead address.
10
14
  * @returns {SiteIndex} The index, and what could not be addressed unambiguously.
11
15
  */
12
- export function buildSiteIndex(entries: readonly SiteEntry[], { foreignIndex }?: {
16
+ export function buildSiteIndex(entries: readonly SiteEntry[], { foreignIndex, noIndexPackages }?: {
13
17
  foreignIndex?: Map<string, {
14
18
  package: string;
15
19
  type?: string;
16
20
  }> | undefined;
21
+ noIndexPackages?: Set<string> | undefined;
17
22
  }): SiteIndex;
18
23
  /**
19
24
  * The per-page context a wikilink resolver takes.
@@ -44,9 +44,10 @@ export function frontmatterWikilinks(fm: unknown): Array<{
44
44
  *
45
45
  * **Every target that resolves nowhere fails the build**, and is
46
46
  * classified into the vocabulary all three resolvers share — `unlabelled`,
47
- * `not-an-address`, `unknown-type`, `ambiguous`, `unresolved`. Failures are
48
- * collected in `ctx.errors`, each carrying the authored `link` and its
49
- * `occurrence` so a caller can report the line and column it sits on.
47
+ * `not-an-address`, `unknown-type`, `ambiguous`, `unresolved`,
48
+ * `no-content-index`. Failures are collected in `ctx.errors`, each carrying
49
+ * the authored `link` and its `occurrence` so a caller can report the line and
50
+ * column it sits on.
50
51
  *
51
52
  * There is deliberately no exception letting a hyphen-form address through while
52
53
  * any linkable package had no vendored manifest, since a real cross-package
@@ -77,9 +78,12 @@ export function frontmatterWikilinks(fm: unknown): Array<{
77
78
  *
78
79
  * @param {string} body - The markdown body.
79
80
  * @param {object} ctx - `{ index, assets, collide, sections, contentTypes,
80
- * packages, foreign, type, errors, src, file }`.
81
+ * packages, noIndexPackages, foreign, type, errors, src, file }`.
81
82
  * `packages` is every package an address may name, without which the leading
82
- * package segment of a canonical address reads as an unknown type; `foreign`
83
+ * package segment of a canonical address reads as an unknown type;
84
+ * `noIndexPackages` is every package declared `contentIndex: false`, so a
85
+ * qualified address naming one fails with `no-content-index` rather than
86
+ * `not-an-address`; `foreign`
83
87
  * is the cross-package manifest index; `assets` is the address space an embed
84
88
  * resolves against. `src` is the page's display
85
89
  * path and `file` the source file a diagnostic should name — absent, `src`
@@ -223,6 +223,9 @@ export const WIKILINK: RegExp;
223
223
  * - `unresolved` — parses as an address, and nothing publishes it.
224
224
  * - `ambiguous` — more than one package publishes the short address.
225
225
  * - `unknown-anchor` — the address resolved, the `#section` it names did not.
226
+ * - `no-content-index` — the address names a package declared
227
+ * `contentIndex: false`, a Foundry dependency only, so no index was fetched
228
+ * for it to resolve against.
226
229
  *
227
230
  * @type {ReadonlySet<string>}
228
231
  */
@@ -81,13 +81,18 @@ export function resolveItemDocType(qualifier: string, types: Set<string>): strin
81
81
  * @param {Set<string>} types - Every type the content tree contains.
82
82
  * @param {Set<string>} [packages] - Every package an address may name. Omitted
83
83
  * by callers that resolve within one package, where the form cannot occur.
84
+ * @param {Set<string>} [noIndexPackages] - Packages declared `contentIndex:
85
+ * false` — a Foundry dependency only, with no fetched index. A fully
86
+ * qualified target naming one is refused with `no-content-index` before its
87
+ * type is even considered, since there is no index to resolve it against.
84
88
  * @returns {{type: string, shortcode: string, itemDoc: boolean,
85
89
  * package?: string, system?: string, reason?: undefined}
86
- * | {reason: "unknown-type"} | null}
90
+ * | {reason: "unknown-type"|"no-content-index", package?: string} | null}
87
91
  * The resolved qualifier; a `reason` when the target is definitely qualified
88
- * but names no known type; or `null` when it is not an address at all.
92
+ * but names no known type or no fetched index; or `null` when it is not an
93
+ * address at all.
89
94
  */
90
- export function readQualifier(target: string, types: Set<string>, packages?: Set<string>): {
95
+ export function readQualifier(target: string, types: Set<string>, packages?: Set<string>, noIndexPackages?: Set<string>): {
91
96
  type: string;
92
97
  shortcode: string;
93
98
  itemDoc: boolean;
@@ -95,7 +100,8 @@ export function readQualifier(target: string, types: Set<string>, packages?: Set
95
100
  system?: string;
96
101
  reason?: undefined;
97
102
  } | {
98
- reason: "unknown-type";
103
+ reason: "unknown-type" | "no-content-index";
104
+ package?: string;
99
105
  } | null;
100
106
  /**
101
107
  * The deterministic JournalEntryPage id for one anchor: SHA-256 of
@@ -132,6 +138,10 @@ export function anchorPageId(noteId: string, anchorSlug: string): string;
132
138
  * @param {Map<string, object>} [opts.assets] - The files this package ships, by
133
139
  * canonical address. They resolve no link — an asset is not a document — and
134
140
  * answer only the art fields, which name a file and never a document.
141
+ * @param {Set<string>} [opts.noIndexPackages] - Packages declared
142
+ * `contentIndex: false` — a Foundry dependency only. A link naming one fails
143
+ * with `no-content-index` rather than resolving, ambiguously, as either a
144
+ * typo or an undeclared package.
135
145
  * @returns {{byShortcode: Map<string, object>, types: Set<string>}} `types` is
136
146
  * every type the tree actually contains, so a qualifier naming no real type
137
147
  * can be told apart from a missing target.
@@ -144,8 +154,9 @@ export function buildWikilinkIndex(docs: Array<{
144
154
  pack?: string;
145
155
  docPack?: string;
146
156
  draft?: boolean;
147
- }>, packageId: string, foreign?: Map<string, object>, contentPackage?: string, { assets }?: {
157
+ }>, packageId: string, foreign?: Map<string, object>, contentPackage?: string, { assets, noIndexPackages }?: {
148
158
  assets?: Map<string, object> | undefined;
159
+ noIndexPackages?: Set<string> | undefined;
149
160
  }): {
150
161
  byShortcode: Map<string, object>;
151
162
  types: Set<string>;
@@ -187,11 +187,13 @@ export function publishedRelationships(relationships: Record<string, unknown>):
187
187
  * Three kinds of key end up in the result:
188
188
  *
189
189
  * - **Declared** — everything in `packageBuild.manifest`, emitted unchanged, so
190
- * a key Foundry adds later needs no release of this package.
190
+ * a key Foundry adds later needs no release of this package. The one
191
+ * exception is `descriptionHtml`, folded into the description below rather
192
+ * than surviving under its own name.
191
193
  * - **Derived** — the identity, the description, the release addresses, the
192
194
  * version, the Foundry and system compatibility ranges, and the pack list.
193
- * These are refused if also declared: an authored copy would be overwritten
194
- * and the two would disagree with nothing to say so.
195
+ * These are refused if also declared (`description` directly; `descriptionHtml`
196
+ * is how it is authored) and the two would disagree with nothing to say so.
195
197
  * - **Computed** — namespaced `flags` a repository works out for itself, merged
196
198
  * over any it declared.
197
199
  *
@@ -18,14 +18,14 @@
18
18
  * @param {boolean} [opts.pdf] - Whether to build the book that ships beside the
19
19
  * archive. `true` by default; `false` skips the build and reports the skip.
20
20
  * @returns {Promise<{zip: string, manifest: string, metadata?: string,
21
- * pdf?: string, pdfFindings: object[], pdfSkipped: string|null,
21
+ * schema?: string, pdf?: string, pdfFindings: object[], pdfSkipped: string|null,
22
22
  * bytes: number, version: string}>} The paths written, what the book build
23
23
  * found, the archive's size, and the version the manifest declares.
24
- * `metadata` is absent when the manifest advertises no content index, and
25
- * `pdf` is absent when no book was written. `pdfSkipped` is `null` when a
26
- * book was built, and otherwise the reason none was — itself `null` when the
27
- * book builder could not be loaded, which is reported through
28
- * `pdfFindings`.
24
+ * `metadata` is absent when the manifest advertises no content index,
25
+ * `schema` is absent when the stage carries no `schema.json`, and `pdf` is
26
+ * absent when no book was written. `pdfSkipped` is `null` when a book was
27
+ * built, and otherwise the reason none was itself `null` when the book
28
+ * builder could not be loaded, which is reported through `pdfFindings`.
29
29
  * @throws {Error} When the stage has no manifest — there is nothing to release,
30
30
  * and an archive without one installs as nothing.
31
31
  */
@@ -39,6 +39,7 @@ export function packRelease({ stageDir, outDir, artifact, metadataDir, pdf, }?:
39
39
  zip: string;
40
40
  manifest: string;
41
41
  metadata?: string;
42
+ schema?: string;
42
43
  pdf?: string;
43
44
  pdfFindings: object[];
44
45
  pdfSkipped: string | null;