@heroiclands/package-build 22.0.3 → 22.1.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 +66 -0
- package/CONTENT.md +56 -18
- package/README.md +1 -1
- package/bin/content-build.mjs +67 -23
- package/bin/package-build.mjs +3 -2
- package/config.mjs +52 -1
- package/content-config.mjs +264 -8
- package/docs/api.md +33 -30
- package/docs/commands.md +68 -32
- package/docs/configuration.md +276 -62
- package/docs/getting-started.md +15 -4
- package/docs/project-setup.md +45 -20
- package/engine/content-links.mjs +19 -9
- package/engine/helpers.mjs +2 -1
- package/engine/metadata-index.mjs +32 -0
- package/engine/note-vocabulary.mjs +20 -0
- package/engine/pack-config.mjs +21 -2
- package/engine/site-build.mjs +29 -55
- package/engine/site-config.mjs +503 -0
- package/engine/site-index.mjs +10 -1
- package/engine/web-wikilinks.mjs +16 -6
- package/engine/wikilink-syntax.mjs +10 -0
- package/engine/wikilinks.mjs +34 -7
- package/manifest.mjs +12 -7
- package/package.json +2 -1
- package/stage.mjs +4 -3
- package/types/config.d.mts +24 -0
- package/types/content-config.d.mts +64 -0
- package/types/engine/content-links.d.mts +3 -2
- package/types/engine/metadata-index.d.mts +22 -0
- package/types/engine/note-vocabulary.d.mts +12 -0
- package/types/engine/site-build.d.mts +8 -26
- package/types/engine/site-config.d.mts +236 -0
- package/types/engine/site-index.d.mts +6 -1
- package/types/engine/web-wikilinks.d.mts +9 -5
- package/types/engine/wikilink-syntax.d.mts +3 -0
- package/types/engine/wikilinks.d.mts +16 -5
- package/types/manifest.d.mts +4 -4
- package/types/stage.d.mts +4 -3
package/engine/wikilinks.mjs
CHANGED
|
@@ -203,13 +203,18 @@ export function resolveItemDocType(qualifier, types) {
|
|
|
203
203
|
* @param {Set<string>} types - Every type the content tree contains.
|
|
204
204
|
* @param {Set<string>} [packages] - Every package an address may name. Omitted
|
|
205
205
|
* by callers that resolve within one package, where the form cannot occur.
|
|
206
|
+
* @param {Set<string>} [noIndexPackages] - Packages declared `contentIndex:
|
|
207
|
+
* false` — a Foundry dependency only, with no fetched index. A fully
|
|
208
|
+
* qualified target naming one is refused with `no-content-index` before its
|
|
209
|
+
* type is even considered, since there is no index to resolve it against.
|
|
206
210
|
* @returns {{type: string, shortcode: string, itemDoc: boolean,
|
|
207
211
|
* package?: string, system?: string, reason?: undefined}
|
|
208
|
-
* | {reason: "unknown-type"} | null}
|
|
212
|
+
* | {reason: "unknown-type"|"no-content-index", package?: string} | null}
|
|
209
213
|
* The resolved qualifier; a `reason` when the target is definitely qualified
|
|
210
|
-
* but names no known type; or `null` when it is not an
|
|
214
|
+
* but names no known type or no fetched index; or `null` when it is not an
|
|
215
|
+
* address at all.
|
|
211
216
|
*/
|
|
212
|
-
export function readQualifier(target, types, packages) {
|
|
217
|
+
export function readQualifier(target, types, packages, noIndexPackages) {
|
|
213
218
|
// **Package, system and type are lowercase; the shortcode is not.** A
|
|
214
219
|
// shortcode is case-sensitive and routinely mixed — `Clb`, `LtShoe`,
|
|
215
220
|
// `HsTunic` — so it is written as the note declares it. The three segments
|
|
@@ -221,7 +226,7 @@ export function readQualifier(target, types, packages) {
|
|
|
221
226
|
// (`[[Shock State]]`), and calling that a badly-cased address rather than
|
|
222
227
|
// not an address would name the wrong mistake. Neither tree carries a
|
|
223
228
|
// violation — 10,538 authored targets — so this pins a rule already kept.
|
|
224
|
-
const read = readQualifierCased(target, types, packages);
|
|
229
|
+
const read = readQualifierCased(target, types, packages, noIndexPackages);
|
|
225
230
|
if (read && !read.reason && qualifyingSegments(target).some((s) => /[A-Z]/.test(s))) {
|
|
226
231
|
return { reason: "not-lowercase" };
|
|
227
232
|
}
|
|
@@ -249,9 +254,10 @@ function qualifyingSegments(target) {
|
|
|
249
254
|
* @param {string} target
|
|
250
255
|
* @param {Set<string>} types
|
|
251
256
|
* @param {Set<string>} [packages]
|
|
257
|
+
* @param {Set<string>} [noIndexPackages]
|
|
252
258
|
* @returns {object|null}
|
|
253
259
|
*/
|
|
254
|
-
function readQualifierCased(target, types, packages) {
|
|
260
|
+
function readQualifierCased(target, types, packages, noIndexPackages) {
|
|
255
261
|
// The slash form is legacy and states neither package nor system, so it is
|
|
256
262
|
// read first and separately. A slash is unconditionally a qualifier —
|
|
257
263
|
// nothing else uses one — which is why an unknown type before it is
|
|
@@ -281,6 +287,10 @@ function readQualifierCased(target, types, packages) {
|
|
|
281
287
|
// qualified.
|
|
282
288
|
case 4: {
|
|
283
289
|
const pkg = norm(parts[0]);
|
|
290
|
+
// Checked before the type: a package with no fetched index has no
|
|
291
|
+
// vocabulary to resolve the rest of the target against, and the
|
|
292
|
+
// fix is the config declaration, not the shortcode.
|
|
293
|
+
if (noIndexPackages?.has(pkg)) return { reason: "no-content-index", package: pkg };
|
|
284
294
|
if (!packages?.has(pkg)) return null;
|
|
285
295
|
const system = norm(parts[1]);
|
|
286
296
|
if (!isSystemSegment(system)) return null;
|
|
@@ -359,11 +369,21 @@ export function anchorPageId(noteId, anchorSlug) {
|
|
|
359
369
|
* @param {Map<string, object>} [opts.assets] - The files this package ships, by
|
|
360
370
|
* canonical address. They resolve no link — an asset is not a document — and
|
|
361
371
|
* answer only the art fields, which name a file and never a document.
|
|
372
|
+
* @param {Set<string>} [opts.noIndexPackages] - Packages declared
|
|
373
|
+
* `contentIndex: false` — a Foundry dependency only. A link naming one fails
|
|
374
|
+
* with `no-content-index` rather than resolving, ambiguously, as either a
|
|
375
|
+
* typo or an undeclared package.
|
|
362
376
|
* @returns {{byShortcode: Map<string, object>, types: Set<string>}} `types` is
|
|
363
377
|
* every type the tree actually contains, so a qualifier naming no real type
|
|
364
378
|
* can be told apart from a missing target.
|
|
365
379
|
*/
|
|
366
|
-
export function buildWikilinkIndex(
|
|
380
|
+
export function buildWikilinkIndex(
|
|
381
|
+
docs,
|
|
382
|
+
packageId,
|
|
383
|
+
foreign,
|
|
384
|
+
contentPackage,
|
|
385
|
+
{ assets, noIndexPackages } = {},
|
|
386
|
+
) {
|
|
367
387
|
if (!packageId) {
|
|
368
388
|
throw new Error(
|
|
369
389
|
"buildWikilinkIndex: packageId is required — it is the first " +
|
|
@@ -454,6 +474,8 @@ export function buildWikilinkIndex(docs, packageId, foreign, contentPackage, { a
|
|
|
454
474
|
foreign: foreignByKey,
|
|
455
475
|
/** The files this package ships, by canonical address. */
|
|
456
476
|
assets: assets ?? new Map(),
|
|
477
|
+
/** Packages declared `contentIndex: false`, a Foundry dependency only. */
|
|
478
|
+
noIndexPackages: noIndexPackages ?? new Set(),
|
|
457
479
|
};
|
|
458
480
|
}
|
|
459
481
|
|
|
@@ -656,7 +678,12 @@ export function convertWikilinks(markdown, { type, id, pack, docPack, index }) {
|
|
|
656
678
|
if (target === "" && slug) {
|
|
657
679
|
doc = { type, id, pack, docPack };
|
|
658
680
|
} else {
|
|
659
|
-
const qualified = readQualifier(
|
|
681
|
+
const qualified = readQualifier(
|
|
682
|
+
target,
|
|
683
|
+
index.types,
|
|
684
|
+
index.packages,
|
|
685
|
+
index.noIndexPackages,
|
|
686
|
+
);
|
|
660
687
|
qualifiedRead = qualified;
|
|
661
688
|
// A target that does not parse as an address is a defect: there is
|
|
662
689
|
// no second namespace left to fall through to.
|
package/manifest.mjs
CHANGED
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
*
|
|
29
29
|
* - **Declared** — the `packageBuild.manifest` block, emitted unchanged, so a
|
|
30
30
|
* key Foundry adds in a later version needs no release of this package.
|
|
31
|
-
* - **Derived** — the identity, the
|
|
32
|
-
* compatibility ranges and the pack list. Declaring one of
|
|
33
|
-
* rather than an override: the authored copy would be
|
|
31
|
+
* - **Derived** — the identity, the description, the version, the release
|
|
32
|
+
* addresses, the compatibility ranges and the pack list. Declaring one of
|
|
33
|
+
* these is an error rather than an override: the authored copy would be
|
|
34
|
+
* silently overwritten.
|
|
34
35
|
* - **Computed** — namespaced `flags` a repository works out for itself.
|
|
35
36
|
*
|
|
36
37
|
* **Nothing here invents an address.** The repository URL is read from
|
|
@@ -459,10 +460,10 @@ function withoutBuildKeys(entry) {
|
|
|
459
460
|
*
|
|
460
461
|
* - **Declared** — everything in `packageBuild.manifest`, emitted unchanged, so
|
|
461
462
|
* a key Foundry adds later needs no release of this package.
|
|
462
|
-
* - **Derived** — the identity, the
|
|
463
|
-
* and system compatibility ranges, and the pack list.
|
|
464
|
-
* also declared: an authored copy would be overwritten
|
|
465
|
-
* disagree with nothing to say so.
|
|
463
|
+
* - **Derived** — the identity, the description, the release addresses, the
|
|
464
|
+
* version, the Foundry and system compatibility ranges, and the pack list.
|
|
465
|
+
* These are refused if also declared: an authored copy would be overwritten
|
|
466
|
+
* and the two would disagree with nothing to say so.
|
|
466
467
|
* - **Computed** — namespaced `flags` a repository works out for itself, merged
|
|
467
468
|
* over any it declared.
|
|
468
469
|
*
|
|
@@ -492,6 +493,10 @@ export function buildManifest({ config, packageJson, artifact, flags }) {
|
|
|
492
493
|
artifact,
|
|
493
494
|
}),
|
|
494
495
|
};
|
|
496
|
+
// Own-property presence, not just value, decides whether a key survives
|
|
497
|
+
// into `ordered` below — an explicit `undefined` would still occupy a slot
|
|
498
|
+
// in it. Set only when `package.json` actually declares one.
|
|
499
|
+
if (packageJson.description !== undefined) derived.description = packageJson.description;
|
|
495
500
|
if (config.compatibility) derived.compatibility = config.compatibility;
|
|
496
501
|
|
|
497
502
|
// `requiresSystem` is the gate half of the declare/require split. It
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.1.1",
|
|
4
4
|
"description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — content compilation, manifest, localization, staging, bundle, release and deployment.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
"markdown-it": "^15.0.0",
|
|
148
148
|
"markdownlint-cli2": "^0.23.2",
|
|
149
149
|
"prettier": "^3.9.6",
|
|
150
|
+
"smol-toml": "^1.7.0",
|
|
150
151
|
"ssh2-sftp-client": "^12.1.1",
|
|
151
152
|
"typescript": "^6.0.3",
|
|
152
153
|
"unidecode": "^1.1.0",
|
package/stage.mjs
CHANGED
|
@@ -42,9 +42,10 @@ import path from "node:path";
|
|
|
42
42
|
/**
|
|
43
43
|
* Directories every HeroicLands repository regenerates and none commits.
|
|
44
44
|
*
|
|
45
|
-
* A repository adds its own
|
|
46
|
-
*
|
|
47
|
-
*
|
|
45
|
+
* A repository adds its own through `packageBuild.clean.extra`, but these four
|
|
46
|
+
* are common to all of them because they come from the shared toolchain rather
|
|
47
|
+
* than from any one package's layout. Everything the site build writes — the
|
|
48
|
+
* Hugo source tree, Hugo's cache and the rendered site — is under `build/`.
|
|
48
49
|
*/
|
|
49
50
|
export const BUILD_ARTIFACT_DIRS = Object.freeze(["build", ".vite", ".vitepress", ".rollup.cache"]);
|
|
50
51
|
|
package/types/config.d.mts
CHANGED
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
* @returns {string} An absolute path to import.
|
|
11
11
|
*/
|
|
12
12
|
export function resolveAssetTransform(declared: string, rootDir: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* `package.json`'s `homepage`, checked against the address it must be.
|
|
15
|
+
*
|
|
16
|
+
* A package's Foundry manifest already derives its own `url` from
|
|
17
|
+
* `contentPackage` (`packageHomepage` in `manifest.mjs`); `homepage` states
|
|
18
|
+
* the same address a second time, in `package.json`, for the generated Hugo
|
|
19
|
+
* configuration to read a `baseURL` from without knowing where each
|
|
20
|
+
* repository keeps its own site configuration.
|
|
21
|
+
*
|
|
22
|
+
* Required unconditionally: every package publishes a site, so there is no
|
|
23
|
+
* package this does not apply to.
|
|
24
|
+
*
|
|
25
|
+
* **Not called by {@link resolvePackageBuildConfig}.** Every packaging
|
|
26
|
+
* command — `clean`, `deploy`, `manifest` and the rest — resolves through it,
|
|
27
|
+
* and none of them reads `homepage`: the Foundry manifest's own `url` is
|
|
28
|
+
* `packageHomepage(contentPackage)`, independent of it. The right caller is
|
|
29
|
+
* whatever reads `homepage` to write a site's `baseURL`.
|
|
30
|
+
*
|
|
31
|
+
* @param {string|null} homepage - The resolved `package.json` `homepage`, or
|
|
32
|
+
* `null` when none is declared.
|
|
33
|
+
* @param {string} contentPackage - The resolved `contentPackage`.
|
|
34
|
+
* @returns {void}
|
|
35
|
+
*/
|
|
36
|
+
export function checkHomepage(homepage: string | null, contentPackage: string): void;
|
|
13
37
|
/**
|
|
14
38
|
* Resolve a package-build configuration from an already-loaded shared one.
|
|
15
39
|
*
|
|
@@ -73,6 +73,7 @@ export namespace DEFAULT_PATHS {
|
|
|
73
73
|
let unpack: "build/tmp/packs";
|
|
74
74
|
let foreignCache: "build/cache/foreign";
|
|
75
75
|
let metadataCache: "build/cache/metadata";
|
|
76
|
+
let navigationCache: "build/cache/navigation";
|
|
76
77
|
}
|
|
77
78
|
/**
|
|
78
79
|
* The Foundry document types a compendium pack may hold. This is the set the
|
|
@@ -175,6 +176,20 @@ export const SITE_MODES: readonly ["homepage", "content"];
|
|
|
175
176
|
* @type {symbol}
|
|
176
177
|
*/
|
|
177
178
|
export const DERIVED_SYSTEM_VERSION: symbol;
|
|
179
|
+
/**
|
|
180
|
+
* Hugo keys a repository may **not** declare under `site.hugo`, because the
|
|
181
|
+
* site build generates them and would only overwrite what was written.
|
|
182
|
+
*
|
|
183
|
+
* The same rule `DERIVED_MANIFEST_KEYS` states for the manifest, for the same
|
|
184
|
+
* reason: an authored `baseURL` would look authoritative, sit there unread,
|
|
185
|
+
* and disagree with the site forever. Each key names where its value comes
|
|
186
|
+
* from. A dotted key names a nested one, and covers everything beneath it —
|
|
187
|
+
* `params.brand` refuses `params.brand.logo` too — so `site.hugo` reaches only
|
|
188
|
+
* what the generator does not write.
|
|
189
|
+
*
|
|
190
|
+
* @type {Readonly<Record<string, string>>}
|
|
191
|
+
*/
|
|
192
|
+
export const DERIVED_HUGO_KEYS: Readonly<Record<string, string>>;
|
|
178
193
|
/**
|
|
179
194
|
* How much of a package reaches the web.
|
|
180
195
|
*
|
|
@@ -339,6 +354,11 @@ export type PathsInput = {
|
|
|
339
354
|
* only those supplying a catalogue.
|
|
340
355
|
*/
|
|
341
356
|
metadataCache?: string | undefined;
|
|
357
|
+
/**
|
|
358
|
+
* Where the site navigation is fetched
|
|
359
|
+
* to, for the generated Hugo menu.
|
|
360
|
+
*/
|
|
361
|
+
navigationCache?: string | undefined;
|
|
342
362
|
};
|
|
343
363
|
/**
|
|
344
364
|
* {@link PathsInput}, resolved to absolute paths against `rootDir`.
|
|
@@ -352,6 +372,7 @@ export type ResolvedPaths = {
|
|
|
352
372
|
unpack: string;
|
|
353
373
|
foreignCache: string;
|
|
354
374
|
metadataCache: string;
|
|
375
|
+
navigationCache: string;
|
|
355
376
|
};
|
|
356
377
|
/**
|
|
357
378
|
* The identity every compiled document's `_stats` block carries.
|
|
@@ -484,6 +505,17 @@ export type RelationshipSpec = {
|
|
|
484
505
|
* `_stats.systemVersion` is stamped from.
|
|
485
506
|
*/
|
|
486
507
|
compatibility?: CompatibilitySpec | undefined;
|
|
508
|
+
/**
|
|
509
|
+
* Whether `deps fetch` fetches this
|
|
510
|
+
* dependency's content index. Default
|
|
511
|
+
* `true`. `false` declares the dependency
|
|
512
|
+
* for the Foundry manifest only — nothing
|
|
513
|
+
* this tree cites by wikilink — and refuses
|
|
514
|
+
* `itemCatalog: true` on the same entry,
|
|
515
|
+
* since a catalogue is fetched from the same
|
|
516
|
+
* index.
|
|
517
|
+
*/
|
|
518
|
+
contentIndex?: boolean | undefined;
|
|
487
519
|
};
|
|
488
520
|
/**
|
|
489
521
|
* How a generated documentation page is framed in the repository publishing it.
|
|
@@ -590,6 +622,22 @@ export type ContentBuildConfigInput = {
|
|
|
590
622
|
* package.
|
|
591
623
|
*/
|
|
592
624
|
foundryPackage?: string | undefined;
|
|
625
|
+
/**
|
|
626
|
+
* `package.json`'s own `homepage` —
|
|
627
|
+
* the site build's `baseURL`. Checked
|
|
628
|
+
* by `checkHomepage` in
|
|
629
|
+
* `config.mjs`.
|
|
630
|
+
*/
|
|
631
|
+
homepage?: string | undefined;
|
|
632
|
+
/**
|
|
633
|
+
* `package.json`'s own `author`, in
|
|
634
|
+
* either of npm's forms.
|
|
635
|
+
*/
|
|
636
|
+
author?: string | {
|
|
637
|
+
name: string;
|
|
638
|
+
email?: string;
|
|
639
|
+
url?: string;
|
|
640
|
+
} | undefined;
|
|
593
641
|
/**
|
|
594
642
|
* Whether the package is a system, a
|
|
595
643
|
* module, or documentation — the kind
|
|
@@ -683,6 +731,22 @@ export type ContentBuildConfig = {
|
|
|
683
731
|
* package, which ships no Foundry package.
|
|
684
732
|
*/
|
|
685
733
|
foundryPackage: string | null;
|
|
734
|
+
/**
|
|
735
|
+
* `package.json`'s own `homepage`,
|
|
736
|
+
* checked by `checkHomepage` in
|
|
737
|
+
* `config.mjs`.
|
|
738
|
+
*/
|
|
739
|
+
homepage: string | null;
|
|
740
|
+
/**
|
|
741
|
+
* `package.json`'s own `author`, normalised
|
|
742
|
+
* from either of npm's forms; `null` when
|
|
743
|
+
* the package declares none.
|
|
744
|
+
*/
|
|
745
|
+
author: Readonly<{
|
|
746
|
+
name: string;
|
|
747
|
+
email?: string;
|
|
748
|
+
url?: string;
|
|
749
|
+
}> | null;
|
|
686
750
|
packageKind: PackageKind;
|
|
687
751
|
/**
|
|
688
752
|
* Derived, and **conditional**: the served
|
|
@@ -144,8 +144,9 @@ export function auditHomepageLinks(index: ReturnType<typeof buildLinkIndex>): Ar
|
|
|
144
144
|
* which addresses a foreign manifest answered. Each `deadAddresses` entry
|
|
145
145
|
* carries a `reason` from {@link LINK_FINDING_REASONS} —
|
|
146
146
|
* `"not-an-address"`, `"unknown-type"`, `"ambiguous"` (with the claiming
|
|
147
|
-
* `packages`), or `"unresolved"` — and every one of
|
|
148
|
-
* the three resolvers agree on severity for every
|
|
147
|
+
* `packages`), `"no-content-index"`, or `"unresolved"` — and every one of
|
|
148
|
+
* them is an **error**: the three resolvers agree on severity for every
|
|
149
|
+
* class.
|
|
149
150
|
*/
|
|
150
151
|
export function auditLinks(index: ReturnType<typeof buildLinkIndex>): {
|
|
151
152
|
deadAnchors: object[];
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
* and needing no items is the mirror of it. Gating the index on the catalogue
|
|
10
10
|
* flag would serve neither.
|
|
11
11
|
*
|
|
12
|
+
* **Excludes a relationship declaring `contentIndex: false`.** That opts a
|
|
13
|
+
* dependency out of both edges at once: it is a Foundry dependency only, cited
|
|
14
|
+
* by neither a wikilink nor an item reference, so there is nothing here for
|
|
15
|
+
* `deps fetch` to fill and no cache this build will ever read.
|
|
16
|
+
*
|
|
12
17
|
* The declaration is the one already in the emitted `system.json` /
|
|
13
18
|
* `module.json`, so it cannot drift from what Foundry itself installs, and
|
|
14
19
|
* there is no new configuration key to keep in step. Each entry carries the
|
|
@@ -25,6 +30,23 @@ export function metadataRelationships(config: object): Array<{
|
|
|
25
30
|
kind: string;
|
|
26
31
|
verified: string | undefined;
|
|
27
32
|
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Every package a relationship declares `contentIndex: false` on, keyed by
|
|
35
|
+
* the content package name a link into it would use.
|
|
36
|
+
*
|
|
37
|
+
* A separate set from {@link metadataRelationships}, which answers "what does
|
|
38
|
+
* `deps fetch` fill" — this answers "what does the link resolver recognise as
|
|
39
|
+
* a package with no fetched index", which a wikilink checker or pack compiler
|
|
40
|
+
* needs to tell that case apart from a package nobody declared at all.
|
|
41
|
+
*
|
|
42
|
+
* Walked across every relationship kind, not only the citable ones: the
|
|
43
|
+
* config validation refuses the flag nowhere by kind, so a resolver reading it
|
|
44
|
+
* back should not assume one either.
|
|
45
|
+
*
|
|
46
|
+
* @param {object} config - The resolved build configuration.
|
|
47
|
+
* @returns {ReadonlySet<string>} The content package names.
|
|
48
|
+
*/
|
|
49
|
+
export function noContentIndexPackages(config: object): ReadonlySet<string>;
|
|
28
50
|
/**
|
|
29
51
|
* The cache directory for one dependency's index at one version.
|
|
30
52
|
*
|
|
@@ -50,6 +50,18 @@ 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;
|
|
53
65
|
/**
|
|
54
66
|
* Whether a note is tagged as an unfinished **draft**.
|
|
55
67
|
*
|
|
@@ -105,8 +105,8 @@ export function collectHomepages(contentBase: string, ctx: object): {
|
|
|
105
105
|
* has. Nothing is written at `/<package>/` itself: that becomes a redirect the
|
|
106
106
|
* package's own repository authors, which is a routing fact rather than a page.
|
|
107
107
|
*
|
|
108
|
-
* @param {string} outRoot - The package's site root — the
|
|
109
|
-
* one level above the
|
|
108
|
+
* @param {string} outRoot - The package's site root — the content mount's
|
|
109
|
+
* root, `build/hugo/content`, one level above the mount itself.
|
|
110
110
|
* @param {readonly object[]} pages - From {@link collectHomepages}.
|
|
111
111
|
* @param {object} config - The resolved configuration, for the package name and
|
|
112
112
|
* the default title.
|
|
@@ -379,26 +379,6 @@ export function resolveSitePass(name: string | undefined, options: object): {
|
|
|
379
379
|
beforeLinks?: Function;
|
|
380
380
|
afterLinks?: Function;
|
|
381
381
|
};
|
|
382
|
-
/**
|
|
383
|
-
* The output root, having established that it is safe to delete.
|
|
384
|
-
*
|
|
385
|
-
* The whole tree is a build artifact and is wiped on every run, so this
|
|
386
|
-
* resolution is the difference between clearing a build directory and clearing
|
|
387
|
-
* the repository. An unset `site.out` resolves to `rootDir` itself, and the
|
|
388
|
-
* wipe then deletes the working tree — which is not a hypothetical: it happened
|
|
389
|
-
* while this module was being written, on a configuration that simply had no
|
|
390
|
-
* `site` section yet.
|
|
391
|
-
*
|
|
392
|
-
* So the path is refused unless it is **strictly inside** the repository root.
|
|
393
|
-
* Both failing shapes are ordinary rather than exotic — an absent setting, and a
|
|
394
|
-
* `..` that climbs out — and neither should be recoverable by being careful.
|
|
395
|
-
*
|
|
396
|
-
* @param {string} rootDir - The repository root.
|
|
397
|
-
* @param {string} out - The configured `site.out`.
|
|
398
|
-
* @returns {string} The absolute output root.
|
|
399
|
-
* @throws {Error} When it is unset, or is not below `rootDir`.
|
|
400
|
-
*/
|
|
401
|
-
export function resolveOutputRoot(rootDir: string, out: string): string;
|
|
402
382
|
/**
|
|
403
383
|
* Builds a Hugo content tree from a content tree, and reports what it found.
|
|
404
384
|
*
|
|
@@ -410,18 +390,19 @@ export function resolveOutputRoot(rootDir: string, out: string): string;
|
|
|
410
390
|
* @param {object} [options] - Options.
|
|
411
391
|
* @param {object} [options.config] - A resolved configuration; loaded when
|
|
412
392
|
* omitted.
|
|
413
|
-
* @param {string} [options.outRoot] - Override the configured output mount.
|
|
414
393
|
* @param {Map<string, object[]>} [options.sqlTables] - Prepared `sql` results,
|
|
415
394
|
* keyed by the note's absolute file, from
|
|
416
395
|
* {@link module:engine/sql-tables.prepareSqlTables}. A page authoring an
|
|
417
396
|
* `sql` directive with none prepared is a table error: nothing here runs a
|
|
418
397
|
* query.
|
|
419
398
|
* @returns {{gates: object, stats: object|null, tableErrors: object[],
|
|
420
|
-
* 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.
|
|
421
403
|
*/
|
|
422
|
-
export function buildSite({ config,
|
|
404
|
+
export function buildSite({ config, sqlTables }?: {
|
|
423
405
|
config?: object | undefined;
|
|
424
|
-
outRoot?: string | undefined;
|
|
425
406
|
sqlTables?: Map<string, object[]> | undefined;
|
|
426
407
|
}): {
|
|
427
408
|
gates: object;
|
|
@@ -430,6 +411,7 @@ export function buildSite({ config, outRoot, sqlTables }?: {
|
|
|
430
411
|
wikiErrors: object[];
|
|
431
412
|
imageErrors: object[];
|
|
432
413
|
manifests: object | null;
|
|
414
|
+
hasTags: boolean;
|
|
433
415
|
};
|
|
434
416
|
export { formatUnaddressableFinding };
|
|
435
417
|
import { formatUnaddressableFinding } from "./metadata-index.mjs";
|