@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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 22.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f02b25a: **A relationship may declare `contentIndex: false`.** A `requires` or
|
|
8
|
+
`systems` entry naming a package Foundry installs but the content tree never
|
|
9
|
+
cites by wikilink no longer needs a fetched index just to satisfy
|
|
10
|
+
`deps fetch`. `contentIndex` (default `true`) narrows a relationship declaring
|
|
11
|
+
it `false` to the Foundry manifest only: `deps fetch` fetches nothing for it,
|
|
12
|
+
and a wikilink into it fails at the link, naming the key, rather than
|
|
13
|
+
resolving against a stale declaration or an index nobody fetched. It cannot be
|
|
14
|
+
combined with `itemCatalog: true`, which extracts items from the same index
|
|
15
|
+
this declares there is none of.
|
|
16
|
+
- 07bf15d: **The generated Hugo configuration emits tag pages for a site whose notes carry `tags:`.** `content-build site` reads whether any note in the tree carries `tags:` and, when at least one does, writes `[taxonomies] tag = "tags"` and `[outputs] taxonomy = ["HTML"], term = ["HTML"]` into `build/hugo/hugo.toml`, and leaves `taxonomy` and `term` enabled among `disableKinds`. A site whose notes carry no `tags:` gets the same configuration as before — `taxonomy`, `term` and `RSS` all disabled, no `[taxonomies]` or `[outputs]` block. `site.hugo.disableKinds`, `.taxonomies` and `.outputs` stay refused under `site.hugo`, each naming this derivation as the source.
|
|
17
|
+
|
|
18
|
+
## 22.1.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- b0ec919: **The site build generates the Hugo configuration.** `content-build site`
|
|
23
|
+
writes the whole Hugo source tree under `build/hugo/` — a generated
|
|
24
|
+
`hugo.toml`, the content mount at `build/hugo/content/`, Hugo's cache —
|
|
25
|
+
beside the deployment root `build/site/`, and the repository carries no Hugo
|
|
26
|
+
configuration of its own. Every value in the generated file has one source:
|
|
27
|
+
`package.json` (`homepage`, `description`, `author`),
|
|
28
|
+
`package-build.config.yaml` (`packageBuild.manifest.title`, `site.assets`,
|
|
29
|
+
`site.list`, `site.notfound`), the installed `@heroiclands/hugo-theme`, and
|
|
30
|
+
the organisation's brand links and navigation. `package.json`'s `homepage`
|
|
31
|
+
is checked on every site build: it must be
|
|
32
|
+
`https://www.heroiclands.org/<contentPackage>/`.
|
|
33
|
+
|
|
34
|
+
**`deps fetch` also fetches the navigation.** The header menu every site
|
|
35
|
+
renders comes from `https://www.heroiclands.org/nav.json`, cached under
|
|
36
|
+
`build/cache/navigation/` by `content-build deps fetch` and read from the
|
|
37
|
+
cache by the site build — a cold cache fails naming `deps fetch`, so a
|
|
38
|
+
package with no other dependency now runs `deps fetch` before `site` too.
|
|
39
|
+
|
|
40
|
+
**To migrate a repository:**
|
|
41
|
+
|
|
42
|
+
- Delete `site/` and its `.gitignore` entries (`site/content`, `site/public`,
|
|
43
|
+
`site/resources`), and any `packageBuild.clean.extra` entry naming them.
|
|
44
|
+
- Delete `site.out` from `package-build.config.yaml`; the location is fixed.
|
|
45
|
+
- Move the `[params.notfound]` block from the old `hugo.toml` to
|
|
46
|
+
`site.notfound` (`tagline`, `sitenoun`, optional `heroimage` and
|
|
47
|
+
`links[]` of `{title, url, text}`), `params.list.shortcodes` to
|
|
48
|
+
`site.list.shortcodes`, and `params.cdnBaseURL` to `site.assets` where it
|
|
49
|
+
was not already there. Anything else the file carried that the generator
|
|
50
|
+
does not write — `markup.goldmark.extensions.linkify`, say — goes under
|
|
51
|
+
`site.hugo`, which is deep-merged last; every key the generator writes is
|
|
52
|
+
refused there, naming its source.
|
|
53
|
+
- Point the npm scripts at the generated tree:
|
|
54
|
+
`hugo --source build/hugo --minify --gc --cleanDestinationDir` and
|
|
55
|
+
`hugo server --source build/hugo`.
|
|
56
|
+
- Make sure `package.json` declares `homepage`, `description` and `author`,
|
|
57
|
+
and that `@heroiclands/hugo-theme` is under `devDependencies`.
|
|
58
|
+
- a5e83fd: **A manifest's `description` comes from `package.json`.**
|
|
59
|
+
`packageBuild.manifest.description` is refused, the same way `id` and
|
|
60
|
+
`version` are — delete it; the manifest carries `package.json`'s own
|
|
61
|
+
`description`.
|
|
62
|
+
|
|
63
|
+
**`package.json`'s `homepage` and `author` are read and normalised.**
|
|
64
|
+
`homepage` names the address every package's site is served at — an
|
|
65
|
+
absolute URL ending `/<contentPackage>/` — and `author` is accepted in
|
|
66
|
+
either of npm's forms, a string or `{name, email, url}`, and normalised to
|
|
67
|
+
the object form.
|
|
68
|
+
|
|
3
69
|
## 22.0.3
|
|
4
70
|
|
|
5
71
|
### Patch Changes
|
package/CONTENT.md
CHANGED
|
@@ -234,8 +234,9 @@ publish:
|
|
|
234
234
|
site: content
|
|
235
235
|
address: { prefix: guide/ }
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
packageBuild:
|
|
238
|
+
manifest:
|
|
239
|
+
title: The Toolkit
|
|
239
240
|
|
|
240
241
|
pdf:
|
|
241
242
|
title: The Toolkit
|
|
@@ -1781,6 +1782,28 @@ asked for — a build that downloads silently is not reproducible and fails
|
|
|
1781
1782
|
strangely offline. The cache is keyed by version, so changing the pinned version
|
|
1782
1783
|
is a miss rather than a silent overwrite.
|
|
1783
1784
|
|
|
1785
|
+
### A relationship may be a Foundry dependency only
|
|
1786
|
+
|
|
1787
|
+
`requires` and `systems` install with Foundry whether or not the tree cites
|
|
1788
|
+
them, and a package may need the one without the other — thalornaaltart
|
|
1789
|
+
`requires` Thalorna so Foundry installs the base module, and its one homepage
|
|
1790
|
+
note links nowhere. Declare `contentIndex: false` on that entry to say so:
|
|
1791
|
+
|
|
1792
|
+
```yaml
|
|
1793
|
+
relationships:
|
|
1794
|
+
requires:
|
|
1795
|
+
- id: thalorna
|
|
1796
|
+
type: module
|
|
1797
|
+
manifest: https://github.com/HeroicLands/thalorna/releases/latest/download/module.json
|
|
1798
|
+
contentIndex: false
|
|
1799
|
+
```
|
|
1800
|
+
|
|
1801
|
+
`deps fetch` fetches nothing for it — no cache directory, nothing to go stale —
|
|
1802
|
+
and a wikilink into it fails at the link, naming `contentIndex`, rather than
|
|
1803
|
+
resolving against a stale declaration or an index nobody fetched. It cannot be
|
|
1804
|
+
combined with `itemCatalog: true`, which extracts items from the same index
|
|
1805
|
+
this declares there is none of.
|
|
1806
|
+
|
|
1784
1807
|
### `packagebuild` needs no declaration
|
|
1785
1808
|
|
|
1786
1809
|
package-build ships a set of images of its own — section banners chiefly — and a
|
|
@@ -2260,22 +2283,22 @@ address anyone links to. A package publishes its content index regardless — th
|
|
|
2260
2283
|
licensing constraint is against publishing _pages_, not against the artifact
|
|
2261
2284
|
existing — but nothing may declare it as a dependency.
|
|
2262
2285
|
|
|
2263
|
-
The homepage's file is written at the root of
|
|
2264
|
-
site root, one level above the
|
|
2265
|
-
`publish.address.prefix` puts everything else —
|
|
2266
|
-
it, `homepage-root.md`. As with every other page, the front matter's `url`
|
|
2286
|
+
The homepage's file is written at the root of the content mount,
|
|
2287
|
+
`build/hugo/content/` — the package's own site root, one level above the
|
|
2288
|
+
content mount, which is where `publish.address.prefix` puts everything else —
|
|
2289
|
+
under the name its address gives it, `homepage-root.md`. As with every other page, the front matter's `url`
|
|
2267
2290
|
decides where it publishes, and states it relative to the site root — `site.base`
|
|
2268
2291
|
does not reach it.
|
|
2269
2292
|
|
|
2270
2293
|
**What it does not do is decide addresses.** Those come from `publish.address`,
|
|
2271
2294
|
the same setting the content index reads, so a page and its index record cannot
|
|
2272
2295
|
disagree about where the page is. Everything under `site:` is _framing_ —
|
|
2273
|
-
|
|
2274
|
-
|
|
2296
|
+
what a section is called, which extra trees are published beside the content,
|
|
2297
|
+
and the residue of the generated Hugo configuration that is this repository's
|
|
2298
|
+
own:
|
|
2275
2299
|
|
|
2276
2300
|
```yaml
|
|
2277
2301
|
site:
|
|
2278
|
-
out: kb/content # required; wiped on every run
|
|
2279
2302
|
base: /sohl/ # default: /<contentPackage>/ — hrefs only, never a page's `url:`
|
|
2280
2303
|
packages: [sohl, thalorna] # default: just contentPackage
|
|
2281
2304
|
backfillSections: true
|
|
@@ -2294,11 +2317,16 @@ site:
|
|
|
2294
2317
|
description: Folk, animals and the things that walk the world.
|
|
2295
2318
|
readmeSections:
|
|
2296
2319
|
dev-docs: { title: Developer Documentation, banner: banners/dev-docs.webp }
|
|
2320
|
+
list: { shortcodes: true }
|
|
2321
|
+
notfound:
|
|
2322
|
+
tagline: Song of Heroic Lands has no page at
|
|
2323
|
+
sitenoun: site
|
|
2324
|
+
links:
|
|
2325
|
+
- { title: Knowledgebase, url: kb/, text: Every section, with the full content catalog. }
|
|
2297
2326
|
```
|
|
2298
2327
|
|
|
2299
2328
|
| Key | What it decides |
|
|
2300
2329
|
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
2301
|
-
| `out` | The Hugo content root. **Required** in both modes, and wiped on every run — see below. |
|
|
2302
2330
|
| `base` | Where the package is served: the prefix on every rendered `href`, and what a manifest `path` is measured against. It reaches no page's own `url:` — see [A page's URL is its address](#a-pages-url-is-its-address). Defaults to `/<contentPackage>/`. |
|
|
2303
2331
|
| `packages` | Which content packages this site renders. Defaults to its own. |
|
|
2304
2332
|
| `sections` | The Hugo sections this site declares, and what each says about itself — see below. |
|
|
@@ -2308,6 +2336,17 @@ site:
|
|
|
2308
2336
|
| `trees` | Extra source trees published beside the content, preserving their source layout below a section. |
|
|
2309
2337
|
| `pass` | A named bundle of this repository's own body rewrites. |
|
|
2310
2338
|
| `passOptions` | That bundle's options. |
|
|
2339
|
+
| `assets` | The host every package's imagery is served from; the generated `params.cdnBaseURL`. |
|
|
2340
|
+
| `list` | How a listing page renders; the generated `params.list`. |
|
|
2341
|
+
| `notfound` | The wording of the "page not found" page; the generated `params.notfound`. |
|
|
2342
|
+
| `hugo` | A mapping deep-merged over the generated Hugo configuration, last. Every key the generator writes is refused here — see `docs/configuration.md`. |
|
|
2343
|
+
|
|
2344
|
+
Where the tree is written is not among them. `content-build site` writes the
|
|
2345
|
+
whole Hugo source tree under `build/hugo/` — the generated `hugo.toml`, the
|
|
2346
|
+
content mount at `build/hugo/content/`, Hugo's cache — and the consumer's
|
|
2347
|
+
script runs `hugo --source build/hugo` over it. The generated file's every
|
|
2348
|
+
value has a source the repository already states; `docs/configuration.md`
|
|
2349
|
+
lists them.
|
|
2311
2350
|
|
|
2312
2351
|
### What a section may declare
|
|
2313
2352
|
|
|
@@ -2409,15 +2448,14 @@ The **writers** name no keys: a section's `_index.md` is whatever the entry
|
|
|
2409
2448
|
resolved to, `title` first. So extending the vocabulary is a change to the
|
|
2410
2449
|
schema alone, and the two can no longer drift apart.
|
|
2411
2450
|
|
|
2412
|
-
### Why
|
|
2451
|
+
### Why the output location is fixed
|
|
2413
2452
|
|
|
2414
|
-
The
|
|
2415
|
-
page whose note was renamed cannot linger and keep publishing.
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
the repository root.
|
|
2453
|
+
The content mount is a build artifact and is **deleted on every run**, so that a
|
|
2454
|
+
page whose note was renamed cannot linger and keep publishing. A configurable
|
|
2455
|
+
location is a location that can be unset — and an unset one resolves to the
|
|
2456
|
+
repository root, where the wipe deletes the working tree. A fixed one under
|
|
2457
|
+
`build/` can point nowhere else, so `site.out` is refused by name and the wipe
|
|
2458
|
+
needs no guard.
|
|
2421
2459
|
|
|
2422
2460
|
### Consumer passes are named, not imported
|
|
2423
2461
|
|
package/README.md
CHANGED
package/bin/content-build.mjs
CHANGED
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
unaddressableForeignPackages,
|
|
80
80
|
formatUnaddressableFinding,
|
|
81
81
|
} from "../engine/metadata-index.mjs";
|
|
82
|
+
import { fetchNavigation, generateHugoConfig, writeHugoConfig } from "../engine/site-config.mjs";
|
|
82
83
|
import { renderItemFieldReference } from "../engine/field-reference.mjs";
|
|
83
84
|
import { lintContentTree } from "../engine/content-lint.mjs";
|
|
84
85
|
import { lintContentCharset } from "../engine/content-charset.mjs";
|
|
@@ -1484,7 +1485,17 @@ function pdfCommand() {
|
|
|
1484
1485
|
* compiled into packs. Everything a consumer would otherwise write for itself —
|
|
1485
1486
|
* the walk, the address derivation, the address index, table expansion,
|
|
1486
1487
|
* wikilink resolution, code-fence protection, the foreign-manifest merge and
|
|
1487
|
-
* the section-landing backfill — happens here, from configuration.
|
|
1488
|
+
* the section-landing backfill — happens here, from configuration. So does the
|
|
1489
|
+
* Hugo configuration: the whole source tree Hugo reads lands under
|
|
1490
|
+
* `build/hugo/`, and the consumer's script runs Hugo over it.
|
|
1491
|
+
*
|
|
1492
|
+
* **The Hugo configuration is generated before anything is written.** Its
|
|
1493
|
+
* sources — `package.json`'s `homepage`, the cached navigation, the installed
|
|
1494
|
+
* theme — are each a way the build can fail, and failing before the output
|
|
1495
|
+
* tree is cleared leaves the last good site in place to be looked at. It is
|
|
1496
|
+
* generated again once the site walk completes, because whether the site
|
|
1497
|
+
* emits taxonomy pages is read from the walk — whether any note carries
|
|
1498
|
+
* `tags:` — and that is not known until then.
|
|
1488
1499
|
*
|
|
1489
1500
|
* **Each gate is reported and the run stops at the first that fires.** They are
|
|
1490
1501
|
* ordered so the report names the cause rather than its symptoms: an unusable
|
|
@@ -1497,20 +1508,24 @@ function pdfCommand() {
|
|
|
1497
1508
|
function siteCommand() {
|
|
1498
1509
|
return {
|
|
1499
1510
|
command: "site",
|
|
1500
|
-
describe: "Build
|
|
1501
|
-
builder: (
|
|
1502
|
-
|
|
1503
|
-
describe: "Write the mount here instead of the configured `site.out`.",
|
|
1504
|
-
type: "string",
|
|
1505
|
-
});
|
|
1506
|
-
},
|
|
1507
|
-
handler: async (argv) => {
|
|
1511
|
+
describe: "Build the Hugo source tree from the content tree",
|
|
1512
|
+
builder: () => {},
|
|
1513
|
+
handler: async () => {
|
|
1508
1514
|
try {
|
|
1515
|
+
const config = loadPackConfig();
|
|
1516
|
+
// Generated once before the walk, purely to fail fast on a
|
|
1517
|
+
// missing or mismatched source — `homepage`, the manifest
|
|
1518
|
+
// title, the cached navigation, the installed theme — while
|
|
1519
|
+
// the last good site is still in place to be looked at. Its
|
|
1520
|
+
// `disableKinds`/`taxonomies`/`outputs` are provisional: only
|
|
1521
|
+
// the site walk below knows whether any note carries `tags:`,
|
|
1522
|
+
// so the value actually written is regenerated after it runs.
|
|
1523
|
+
generateHugoConfig(config);
|
|
1509
1524
|
const result = buildSite({
|
|
1510
|
-
|
|
1511
|
-
|
|
1525
|
+
config,
|
|
1526
|
+
sqlTables: await prepareTreeSqlTables(config.paths.content, {
|
|
1527
|
+
skipDirectories: config.skipDirectories,
|
|
1512
1528
|
}),
|
|
1513
|
-
...(argv.out ? { outRoot: argv.out } : {}),
|
|
1514
1529
|
});
|
|
1515
1530
|
const { gates } = result;
|
|
1516
1531
|
|
|
@@ -1623,6 +1638,9 @@ function siteCommand() {
|
|
|
1623
1638
|
`${s.tree ?? 0} tree page(s) + ${s.landings} ` +
|
|
1624
1639
|
`landing(s) to ${path.relative(process.cwd(), s.out)}`,
|
|
1625
1640
|
);
|
|
1641
|
+
const hugo = generateHugoConfig(config, { hasTags: result.hasTags });
|
|
1642
|
+
const { file } = writeHugoConfig(config, hugo);
|
|
1643
|
+
log.info(`wrote ${path.relative(process.cwd(), file)}`);
|
|
1626
1644
|
} catch (err) {
|
|
1627
1645
|
reportFailure(err);
|
|
1628
1646
|
process.exitCode = 1;
|
|
@@ -1782,16 +1800,19 @@ async function fetchFromLocalArtifact(config, argv) {
|
|
|
1782
1800
|
|
|
1783
1801
|
/**
|
|
1784
1802
|
* `deps fetch` — fill the caches this build resolves other packages through:
|
|
1785
|
-
* the **content index** of every declared dependency,
|
|
1786
|
-
*
|
|
1787
|
-
*
|
|
1788
|
-
*
|
|
1789
|
-
*
|
|
1790
|
-
*
|
|
1791
|
-
*
|
|
1792
|
-
*
|
|
1793
|
-
*
|
|
1794
|
-
*
|
|
1803
|
+
* the **content index** of every declared dependency, the **item catalogue**
|
|
1804
|
+
* of those additionally declaring `itemCatalog: true`, and the **site
|
|
1805
|
+
* navigation** heroiclands.org publishes, which the site build writes its
|
|
1806
|
+
* menu from.
|
|
1807
|
+
*
|
|
1808
|
+
* The two dependency sets differ deliberately. Citing another package's
|
|
1809
|
+
* *addresses* and embedding its *items* are separate edges, and a package may
|
|
1810
|
+
* have either without the other — `harn-ensemble` cites no foreign address and
|
|
1811
|
+
* embeds 324,016 item references. The navigation is fetched for every package,
|
|
1812
|
+
* because every package publishes a site.
|
|
1813
|
+
*
|
|
1814
|
+
* Its own command rather than a step of `package compile` or `site`, so that
|
|
1815
|
+
* neither reaches the network. A build that downloads silently is not
|
|
1795
1816
|
* reproducible, breaks offline, and hides a dependency's version change behind
|
|
1796
1817
|
* a passing run.
|
|
1797
1818
|
*
|
|
@@ -1838,11 +1859,34 @@ function depsCommand() {
|
|
|
1838
1859
|
await fetchFromLocalArtifact(config, argv);
|
|
1839
1860
|
return;
|
|
1840
1861
|
}
|
|
1862
|
+
// First, because every package needs it and it depends on
|
|
1863
|
+
// nothing a repository declares: a dependency whose release
|
|
1864
|
+
// cannot be read stops the run after the navigation is cached,
|
|
1865
|
+
// not before.
|
|
1866
|
+
const navigation = await fetchNavigation(config);
|
|
1867
|
+
log.info(
|
|
1868
|
+
`Fetched the site navigation to ${path.relative(process.cwd(), navigation)}.`,
|
|
1869
|
+
);
|
|
1841
1870
|
const indexes = await fetchAllMetadata(config);
|
|
1842
1871
|
if (indexes) log.info(`Fetched ${indexes} dependency content index(es).`);
|
|
1843
1872
|
const count = await fetchAllCatalogs(config);
|
|
1844
1873
|
if (count) log.info(`Fetched ${count} dependency catalogue(s).`);
|
|
1845
|
-
if (!indexes && !count)
|
|
1874
|
+
if (!indexes && !count) {
|
|
1875
|
+
// Distinguished from a package declaring nothing at all: a
|
|
1876
|
+
// relationship may still be declared, just narrowed to the
|
|
1877
|
+
// Foundry manifest by `contentIndex: false` — reporting
|
|
1878
|
+
// "no dependencies" there would read as though the
|
|
1879
|
+
// declaration itself had gone missing.
|
|
1880
|
+
const declared = Object.values(config.relationships ?? {}).some(
|
|
1881
|
+
(entries) => entries?.length,
|
|
1882
|
+
);
|
|
1883
|
+
log.info(
|
|
1884
|
+
declared ?
|
|
1885
|
+
"No declared dependency needs a fetched content index or item " +
|
|
1886
|
+
"catalogue."
|
|
1887
|
+
: "This package declares no dependencies.",
|
|
1888
|
+
);
|
|
1889
|
+
}
|
|
1846
1890
|
} catch (err) {
|
|
1847
1891
|
reportFailure(err);
|
|
1848
1892
|
process.exitCode = 1;
|
package/bin/package-build.mjs
CHANGED
|
@@ -79,6 +79,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
79
79
|
|
|
80
80
|
import { loadPackageBuildConfig } from "../config.mjs";
|
|
81
81
|
import { writeSiteRoot } from "../engine/site-root.mjs";
|
|
82
|
+
import { DEPLOY_ROOT } from "../engine/site-config.mjs";
|
|
82
83
|
import { compilesFoundryDocuments } from "../content-config.mjs";
|
|
83
84
|
import { loadPackConfig, packConfigPath } from "../engine/pack-config.mjs";
|
|
84
85
|
import { cleanBuildArtifacts, stageAssets } from "../stage.mjs";
|
|
@@ -483,12 +484,12 @@ function siteRootCommand() {
|
|
|
483
484
|
builder: (y) =>
|
|
484
485
|
y.option("out", {
|
|
485
486
|
type: "string",
|
|
486
|
-
describe:
|
|
487
|
+
describe: `The directory that is deployed (default: ${DEPLOY_ROOT})`,
|
|
487
488
|
}),
|
|
488
489
|
handler: handler(async (argv) => {
|
|
489
490
|
const config = loadPackageBuildConfig();
|
|
490
491
|
const shared = loadPackConfig();
|
|
491
|
-
const out = path.resolve(config.rootDir, argv.out ??
|
|
492
|
+
const out = path.resolve(config.rootDir, argv.out ?? DEPLOY_ROOT);
|
|
492
493
|
|
|
493
494
|
const { files } = writeSiteRoot({ pkg: shared.contentPackage, out });
|
|
494
495
|
for (const file of files) {
|
package/config.mjs
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* assetTransform: ./utils/svg-theme.mjs
|
|
47
47
|
* stageDir: build/stage
|
|
48
48
|
* clean:
|
|
49
|
-
* extra: [
|
|
49
|
+
* extra: [coverage]
|
|
50
50
|
* lang:
|
|
51
51
|
* sources: lang/*.json
|
|
52
52
|
* deploy:
|
|
@@ -91,6 +91,7 @@ const SECTION_KEYS = [
|
|
|
91
91
|
export const DERIVED_MANIFEST_KEYS = Object.freeze({
|
|
92
92
|
id: "`foundryPackage`, itself derived from package.json `name`",
|
|
93
93
|
version: "package.json `version`",
|
|
94
|
+
description: "package.json `description`",
|
|
94
95
|
url: "package.json `repository`",
|
|
95
96
|
bugs: "package.json `repository`",
|
|
96
97
|
manifest: "package.json `repository` and the release tag",
|
|
@@ -599,6 +600,56 @@ export function resolveAssetTransform(declared, rootDir) {
|
|
|
599
600
|
return path.resolve(rootDir, declared);
|
|
600
601
|
}
|
|
601
602
|
|
|
603
|
+
/**
|
|
604
|
+
* `package.json`'s `homepage`, checked against the address it must be.
|
|
605
|
+
*
|
|
606
|
+
* A package's Foundry manifest already derives its own `url` from
|
|
607
|
+
* `contentPackage` (`packageHomepage` in `manifest.mjs`); `homepage` states
|
|
608
|
+
* the same address a second time, in `package.json`, for the generated Hugo
|
|
609
|
+
* configuration to read a `baseURL` from without knowing where each
|
|
610
|
+
* repository keeps its own site configuration.
|
|
611
|
+
*
|
|
612
|
+
* Required unconditionally: every package publishes a site, so there is no
|
|
613
|
+
* package this does not apply to.
|
|
614
|
+
*
|
|
615
|
+
* **Not called by {@link resolvePackageBuildConfig}.** Every packaging
|
|
616
|
+
* command — `clean`, `deploy`, `manifest` and the rest — resolves through it,
|
|
617
|
+
* and none of them reads `homepage`: the Foundry manifest's own `url` is
|
|
618
|
+
* `packageHomepage(contentPackage)`, independent of it. The right caller is
|
|
619
|
+
* whatever reads `homepage` to write a site's `baseURL`.
|
|
620
|
+
*
|
|
621
|
+
* @param {string|null} homepage - The resolved `package.json` `homepage`, or
|
|
622
|
+
* `null` when none is declared.
|
|
623
|
+
* @param {string} contentPackage - The resolved `contentPackage`.
|
|
624
|
+
* @returns {void}
|
|
625
|
+
*/
|
|
626
|
+
export function checkHomepage(homepage, contentPackage) {
|
|
627
|
+
if (homepage === null) {
|
|
628
|
+
fail(
|
|
629
|
+
"homepage",
|
|
630
|
+
"is not declared in `package.json`, and every package needs one " +
|
|
631
|
+
"to build its site's `baseURL` from. Add " +
|
|
632
|
+
`\`https://www.heroiclands.org/${contentPackage}/\``,
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const suffix = `/${contentPackage}/`;
|
|
637
|
+
let pathname;
|
|
638
|
+
try {
|
|
639
|
+
pathname = new URL(homepage).pathname;
|
|
640
|
+
} catch {
|
|
641
|
+
fail("homepage", `is \`${homepage}\`, which is not an absolute URL`);
|
|
642
|
+
}
|
|
643
|
+
if (!pathname.endsWith(suffix)) {
|
|
644
|
+
fail(
|
|
645
|
+
"homepage",
|
|
646
|
+
`is \`${homepage}\`, but \`contentPackage\` is \`${contentPackage}\` — ` +
|
|
647
|
+
`a package's site is served at \`https://www.heroiclands.org${suffix}\`, ` +
|
|
648
|
+
`so \`package.json\`'s \`homepage\` must end \`${suffix}\``,
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
602
653
|
/**
|
|
603
654
|
* Resolve a package-build configuration from an already-loaded shared one.
|
|
604
655
|
*
|