@heroiclands/package-build 22.0.2 → 22.1.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.
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Check a navigation's shape, and return it.
3
+ *
4
+ * `[{name, url, children?: [{name, url}]}]`, every `url` absolute. Checked
5
+ * on fetch and again on read: a file that is not a navigation would otherwise
6
+ * reach the generated menu as `undefined` labels and links.
7
+ *
8
+ * @param {unknown} value - The parsed document.
9
+ * @param {string} where - What is being checked, for the error.
10
+ * @returns {NavigationEntry[]} The navigation.
11
+ * @throws {TypeError} When the shape is not a navigation.
12
+ */
13
+ export function checkNavigation(value: unknown, where?: string): NavigationEntry[];
14
+ /**
15
+ * The `[[menu.main]]` entries a navigation renders as.
16
+ *
17
+ * Entry for entry, in order; a dropdown is an entry with an `identifier` and
18
+ * its children are entries naming it as `parent`, which is how the theme's
19
+ * header partial draws one. Weights count from one within each level, so the
20
+ * order is the navigation's and not Hugo's alphabetical fallback.
21
+ *
22
+ * @param {readonly NavigationEntry[]} navigation - The navigation.
23
+ * @returns {MenuEntry[]} The menu entries.
24
+ */
25
+ export function menuEntries(navigation: readonly NavigationEntry[]): MenuEntry[];
26
+ /**
27
+ * Where the fetched navigation sits.
28
+ *
29
+ * @param {object} config - The resolved build configuration.
30
+ * @returns {string} The cache directory.
31
+ */
32
+ export function navigationCacheDir(config: object): string;
33
+ /**
34
+ * The cached navigation.
35
+ *
36
+ * **Reads the cache only.** A cold cache is an error naming the command that
37
+ * fills it, rather than a download nobody asked for: a site build that reaches
38
+ * the network is not reproducible and fails strangely offline. That is the
39
+ * content index's rule, and it holds here for the same reason. A half-finished
40
+ * fetch counts as cold.
41
+ *
42
+ * @param {object} config - The resolved build configuration.
43
+ * @returns {NavigationEntry[]} The navigation.
44
+ * @throws {Error} When it has not been fetched, or is not a navigation.
45
+ */
46
+ export function readCachedNavigation(config: object): NavigationEntry[];
47
+ /**
48
+ * Fetch the navigation into the cache, and stamp it complete.
49
+ *
50
+ * Rebuilt from empty on every call rather than kept when present: the
51
+ * navigation carries no version to key a cache on, and a package added to the
52
+ * roster reaches a site on its next `deps fetch`.
53
+ *
54
+ * @param {object} config - The resolved build configuration.
55
+ * @param {object} [options] - Options.
56
+ * @param {string} [options.url] - Where to fetch from. Defaults to
57
+ * {@link NAVIGATION_URL}.
58
+ * @param {typeof globalThis.fetch} [options.fetch] - The fetch to use.
59
+ * @returns {Promise<string>} The cached file.
60
+ * @throws {Error} When the download fails, or the document is not a navigation.
61
+ */
62
+ export function fetchNavigation(config: object, { url, fetch }?: {
63
+ url?: string | undefined;
64
+ fetch?: typeof globalThis.fetch | undefined;
65
+ }): Promise<string>;
66
+ /**
67
+ * The `themesDir` for a repository, as the path from `build/hugo/` to the
68
+ * directory holding the installed theme.
69
+ *
70
+ * Resolved the way Node resolves a package — `node_modules/` in the
71
+ * repository root, then in each parent — and written as a path rather than
72
+ * assumed, so a worktree that resolves its parent's install says so in the
73
+ * generated file.
74
+ *
75
+ * @param {string} rootDir - The repository root.
76
+ * @returns {string} The relative path, POSIX-separated.
77
+ * @throws {Error} When the theme is installed nowhere above the root.
78
+ */
79
+ export function resolveThemesDir(rootDir: string): string;
80
+ /**
81
+ * The Hugo configuration, as an object.
82
+ *
83
+ * Pure: every input is handed in, so a test can describe the generated shape
84
+ * without a repository on disk. {@link generateHugoConfig} is the same function
85
+ * with the reading put back.
86
+ *
87
+ * `checkHomepage` runs first, before any value is composed — a missing or
88
+ * mismatched `package.json` `homepage` is a finding on every site build.
89
+ *
90
+ * @param {object} options - The sources.
91
+ * @param {object} options.config - The resolved build configuration.
92
+ * @param {string} [options.description] - `package.json`'s `description`.
93
+ * @param {readonly NavigationEntry[]} options.navigation - The navigation.
94
+ * @param {string} options.themesDir - From {@link resolveThemesDir}.
95
+ * @returns {Record<string, any>} The configuration Hugo reads.
96
+ * @throws {TypeError} When `homepage` fails `checkHomepage`, or the
97
+ * configuration declares no `packageBuild.manifest.title`.
98
+ */
99
+ export function hugoConfig({ config, description, navigation, themesDir }: {
100
+ config: object;
101
+ description?: string | undefined;
102
+ navigation: readonly NavigationEntry[];
103
+ themesDir: string;
104
+ }): Record<string, any>;
105
+ /**
106
+ * The configuration as the TOML Hugo reads.
107
+ *
108
+ * @param {Record<string, unknown>} generated - From {@link hugoConfig}.
109
+ * @returns {string} The file's contents.
110
+ */
111
+ export function hugoToml(generated: Record<string, unknown>): string;
112
+ /**
113
+ * The Hugo configuration, every source read from the repository.
114
+ *
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.
119
+ *
120
+ * @param {object} config - The resolved build configuration.
121
+ * @returns {Record<string, any>} The configuration Hugo reads.
122
+ * @throws {Error} When any source is missing or wrong.
123
+ */
124
+ export function generateHugoConfig(config: object): Record<string, any>;
125
+ /**
126
+ * Write `build/hugo/hugo.toml`.
127
+ *
128
+ * @param {object} config - The resolved build configuration.
129
+ * @param {Record<string, unknown>} [generated] - The configuration to write,
130
+ * when the caller already generated it. Generated here otherwise.
131
+ * @returns {{file: string}} The file written.
132
+ */
133
+ export function writeHugoConfig(config: object, generated?: Record<string, unknown>): {
134
+ file: string;
135
+ };
136
+ /** The Hugo source directory, relative to the repository root. */
137
+ export const HUGO_SOURCE: "build/hugo";
138
+ /** The content mount `content-build site` writes, relative to the repository root. */
139
+ export const HUGO_CONTENT: "build/hugo/content";
140
+ /**
141
+ * The directory that is deployed, relative to the repository root.
142
+ *
143
+ * Hugo renders into `<DEPLOY_ROOT>/<contentPackage>/`; `package-build
144
+ * site-root` writes `_headers` and `_redirects` beside it.
145
+ */
146
+ export const DEPLOY_ROOT: "build/site";
147
+ /** The npm package the shared theme arrives as. */
148
+ export const THEME_PACKAGE: "@heroiclands/hugo-theme";
149
+ /** The theme's name under `themesDir`, which is the package's unscoped name. */
150
+ export const THEME: "hugo-theme";
151
+ /** The locale every site renders in. */
152
+ export const LOCALE: "en-us";
153
+ /**
154
+ * The brand chrome's own links, the same on every site.
155
+ *
156
+ * `logo` is resolved through the theme's `cdn-url.html`, so it is a path on
157
+ * the asset host rather than an address.
158
+ */
159
+ export const BRAND: Readonly<{
160
+ logo: "images/brand/sohl-icon-white.webp";
161
+ licenseURL: "https://www.heroiclands.org/license/";
162
+ discordURL: "https://discord.gg/EwMfkNd3az";
163
+ }>;
164
+ /**
165
+ * The kinds no site renders.
166
+ *
167
+ * 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.
170
+ */
171
+ export const DISABLE_KINDS: readonly string[];
172
+ /**
173
+ * The markup settings the toolchain's own output requires.
174
+ *
175
+ * Pages are written with raw HTML in them — a `<figure>` for every image, a
176
+ * `<span>` marking an unresolved link — and Goldmark drops raw HTML unless
177
+ * told otherwise. A theme cannot supply this: Hugo does not merge a theme's
178
+ * `markup` block.
179
+ */
180
+ export const MARKUP: Readonly<{
181
+ goldmark: Readonly<{
182
+ renderer: Readonly<{
183
+ unsafe: true;
184
+ }>;
185
+ }>;
186
+ }>;
187
+ /** Where the navigation is published. */
188
+ export const NAVIGATION_URL: "https://www.heroiclands.org/nav.json";
189
+ /** The cached navigation's file name. */
190
+ export const NAVIGATION_FILE: "nav.json";
191
+ /**
192
+ * A navigation entry, as `nav.json` states one.
193
+ */
194
+ export type NavigationEntry = {
195
+ /**
196
+ * - The entry's label.
197
+ */
198
+ name: string;
199
+ /**
200
+ * - Where it links, absolute.
201
+ */
202
+ url: string;
203
+ /**
204
+ * - A dropdown's entries.
205
+ */
206
+ children?: NavigationEntry[] | undefined;
207
+ };
208
+ /**
209
+ * A Hugo menu entry, as `[[menu.main]]` states one.
210
+ */
211
+ export type MenuEntry = {
212
+ name: string;
213
+ url: string;
214
+ weight: number;
215
+ /**
216
+ * - Set on an entry that has children.
217
+ */
218
+ identifier?: string | undefined;
219
+ /**
220
+ * - Set on a child, naming its parent's identifier.
221
+ */
222
+ parent?: string | undefined;
223
+ };
@@ -0,0 +1,87 @@
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
+ /**
12
+ * Suppress indexing of every address a deployment answers on but nobody
13
+ * advertises.
14
+ *
15
+ * Cloudflare Pages assigns three: the project's own `pages.dev`, a per-
16
+ * deployment `pages.dev`, and the custom domain the project carries so the
17
+ * routing layer has an origin to fetch. None is advertised, all answer with the
18
+ * same pages, and left alone they are indexed and compete with the canonical
19
+ * URL in search results.
20
+ *
21
+ * The third matters most: it is the address the routing layer fetches, so it is
22
+ * the host-assigned address a reader is most plausibly handed. The rules are
23
+ * **scoped to those hostnames**, which keeps this correct for anyone deploying
24
+ * the site under a domain of their own — there it is indexable, and only the
25
+ * host-assigned addresses are not.
26
+ *
27
+ * @returns {string[]} The header block's lines.
28
+ */
29
+ export function noindexHeaders(): string[];
30
+ /**
31
+ * The lifetime pinned on the prefix-root redirect, and why it is pinned.
32
+ *
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.
37
+ *
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
+ * @returns {string} The file's contents.
58
+ */
59
+ export function headers(pkg: string): string;
60
+ /**
61
+ * Write `_headers` and `_redirects` beside the rendered site.
62
+ *
63
+ * @param {object} options - Options.
64
+ * @param {string} options.pkg - The content package name, which is also the
65
+ * directory Hugo rendered into.
66
+ * @param {string} options.out - The directory that is deployed.
67
+ * @returns {{files: string[]}} The files written.
68
+ * @throws {Error} When no rendered site is there, which means the site build
69
+ * has not run and writing root files would publish a deployment with nothing
70
+ * under the prefix.
71
+ */
72
+ export function writeSiteRoot({ pkg, out }: {
73
+ pkg: string;
74
+ out: string;
75
+ }): {
76
+ files: string[];
77
+ };
78
+ /**
79
+ * The namespace the routing layer derives a package's origin in.
80
+ *
81
+ * `/<package>/` on the public host is proxied to
82
+ * `https://<package>.<suffix>/<package>/`, and {@link noindexHeaders} depends on
83
+ * that being a dedicated namespace.
84
+ *
85
+ * @type {string}
86
+ */
87
+ export const ORIGIN_SUFFIX: string;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The SVG with a scheme-aware fill rule, or unchanged where one cannot apply.
3
+ *
4
+ * Three files are returned as they are. One already carrying a
5
+ * `prefers-color-scheme` rule is themed — by this pass on an earlier run, or by
6
+ * its author — and re-theming it would stack rules. One with an inline `fill`
7
+ * cannot be themed at all, because an inline declaration beats a `<style>` rule
8
+ * and the result would be a half-recoloured icon, which is worse than an
9
+ * unthemed one. One with no `<svg>` element is not an SVG.
10
+ *
11
+ * @param {string} svg - The SVG source.
12
+ * @returns {string} The themed source, or the input unchanged.
13
+ */
14
+ export function injectAdaptiveFill(svg: string): string;
15
+ /**
16
+ * The staging hook: theme an SVG, and pass everything else through untouched.
17
+ *
18
+ * @param {string} sourcePath - The file being staged.
19
+ * @returns {string|null} The themed source, or `null` to stage the file as it
20
+ * is — which is what every non-SVG asset gets.
21
+ */
22
+ export function transform(sourcePath: string): string | null;
@@ -188,10 +188,10 @@ export function publishedRelationships(relationships: Record<string, unknown>):
188
188
  *
189
189
  * - **Declared** — everything in `packageBuild.manifest`, emitted unchanged, so
190
190
  * a key Foundry adds later needs no release of this package.
191
- * - **Derived** — the identity, the release addresses, the version, the Foundry
192
- * and system compatibility ranges, and the pack list. These are refused if
193
- * also declared: an authored copy would be overwritten and the two would
194
- * disagree with nothing to say so.
191
+ * - **Derived** — the identity, the description, the release addresses, the
192
+ * 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
195
  * - **Computed** — namespaced `flags` a repository works out for itself, merged
196
196
  * over any it declared.
197
197
  *
package/types/stage.d.mts CHANGED
@@ -77,8 +77,9 @@ export function cleanBuildArtifacts(root: string, { extra, includeNodeModules }?
77
77
  /**
78
78
  * Directories every HeroicLands repository regenerates and none commits.
79
79
  *
80
- * A repository adds its own `sohl-thalorna` also clears the Hugo output
81
- * beneath `site/` — but these four are common to all of them because they come
82
- * from the shared toolchain rather than from any one package's layout.
80
+ * A repository adds its own through `packageBuild.clean.extra`, but these four
81
+ * are common to all of them because they come from the shared toolchain rather
82
+ * than from any one package's layout. Everything the site build writes — the
83
+ * Hugo source tree, Hugo's cache and the rendered site — is under `build/`.
83
84
  */
84
85
  export const BUILD_ARTIFACT_DIRS: readonly string[];