@heroiclands/package-build 20.3.1 → 20.5.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.
- package/CHANGELOG.md +351 -0
- package/CONTENT.md +322 -110
- package/README.md +21 -10
- package/bin/content-build.mjs +204 -92
- package/bin/package-build.mjs +48 -15
- package/config.mjs +6 -8
- package/content-config.mjs +518 -151
- package/docs/api.md +1352 -0
- package/docs/commands.md +1609 -0
- package/docs/configuration.md +1432 -0
- package/docs/content-format.md +73 -74
- package/docs/diagnostics.md +356 -0
- package/docs/getting-started.md +813 -0
- package/docs/project-setup.md +469 -0
- package/e2e.mjs +4 -4
- package/engine/actor-compiler.mjs +64 -61
- package/engine/address-charset.mjs +6 -6
- package/engine/address-diff.mjs +57 -52
- package/engine/anchored-sections.mjs +1 -1
- package/engine/anchors.mjs +1 -1
- package/engine/base-compiler.mjs +42 -38
- package/engine/bundle-notes.mjs +4 -4
- package/engine/bundles.mjs +17 -8
- package/engine/code-fences.mjs +3 -3
- package/engine/compendiums.mjs +8 -8
- package/engine/compile-corpus.mjs +4 -5
- package/engine/content-address.mjs +24 -24
- package/engine/content-charset.mjs +1 -1
- package/engine/content-format-check.mjs +24 -25
- package/engine/content-format.mjs +8 -8
- package/engine/content-html.mjs +202 -0
- package/engine/content-icons.mjs +196 -165
- package/engine/content-index.mjs +61 -40
- package/engine/content-links.mjs +74 -41
- package/engine/content-lint.mjs +64 -34
- package/engine/content-package.mjs +7 -9
- package/engine/content-slug.mjs +2 -2
- package/engine/content-tables.mjs +38 -34
- package/engine/content-tree.mjs +1 -1
- package/engine/derived-fields.mjs +174 -0
- package/engine/diagnostics.mjs +3 -4
- package/engine/document-subtypes.mjs +6 -7
- package/engine/field-reference.mjs +8 -8
- package/engine/field-spec.mjs +29 -30
- package/engine/folder-notes.mjs +18 -16
- package/engine/foreign-catalog.mjs +8 -9
- package/engine/foundry-entries.mjs +19 -20
- package/engine/frontmatter-lint.mjs +95 -103
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +44 -39
- package/engine/helpers.mjs +147 -84
- package/engine/homepage.mjs +20 -22
- package/engine/ids.mjs +15 -15
- package/engine/index-records.mjs +4 -4
- package/engine/index.mjs +26 -10
- package/engine/item-compiler.mjs +54 -29
- package/engine/item-docs.mjs +11 -13
- package/engine/item-registry.mjs +13 -13
- package/engine/journals.mjs +24 -15
- package/engine/macros.mjs +3 -3
- package/engine/map-notes.mjs +6 -6
- package/engine/metadata-index.mjs +5 -5
- package/engine/note-claims.mjs +51 -41
- package/engine/note-ids.mjs +5 -5
- package/engine/note-package.mjs +4 -4
- package/engine/note-renames.mjs +3 -3
- package/engine/note-schemas.mjs +3 -8
- package/engine/note-vocabulary.mjs +56 -54
- package/engine/pack-config.mjs +39 -25
- package/engine/pack-router.mjs +0 -0
- package/engine/pdf-build.mjs +464 -0
- package/engine/pdf-fonts.mjs +420 -0
- package/engine/pdf-render.mjs +798 -0
- package/engine/pdf-toc.mjs +525 -0
- package/engine/prose-config.mjs +9 -9
- package/engine/prose-lint.mjs +12 -13
- package/engine/region-events.mjs +2 -2
- package/engine/retired-fields.mjs +24 -22
- package/engine/runtime-only-fields.mjs +1 -1
- package/engine/scene-levels.mjs +1 -1
- package/engine/scenes.mjs +33 -25
- package/engine/schema-check.mjs +21 -21
- package/engine/schema-extract.mjs +1 -1
- package/engine/site-build.mjs +66 -50
- package/engine/site-index.mjs +17 -18
- package/engine/sql-tables.mjs +21 -13
- package/engine/subtype-registry.mjs +5 -4
- package/engine/system-block.mjs +18 -19
- package/engine/systems.mjs +2 -2
- package/engine/web-wikilinks.mjs +41 -38
- package/engine/wikilink-syntax.mjs +16 -16
- package/engine/wikilinks.mjs +40 -42
- package/hm3/actors.mjs +30 -22
- package/hm3/document-subtypes.mjs +5 -5
- package/hm3/index.mjs +2 -2
- package/hm3/item-builders.mjs +1 -1
- package/hm3/item-fields.mjs +3 -3
- package/hm3/items.mjs +28 -8
- package/hm3/template-priority.mjs +2 -2
- package/lang.mjs +3 -3
- package/manifest.mjs +17 -20
- package/package.json +1 -2
- package/release.mjs +66 -6
- package/sohl/actors.mjs +36 -28
- package/sohl/affiliation-standings.mjs +2 -2
- package/sohl/being-info.mjs +5 -5
- package/sohl/default-item-art.mjs +5 -5
- package/sohl/document-subtypes.mjs +5 -5
- package/sohl/index.mjs +3 -3
- package/sohl/item-builders.mjs +7 -7
- package/sohl/item-fields.mjs +8 -9
- package/sohl/items.mjs +28 -6
- package/sohl/kb-passes.mjs +5 -5
- package/sohl/note-schemas.mjs +12 -12
- package/sohl/skill-base.mjs +1 -1
- package/types/content-config.d.mts +91 -39
- package/types/e2e.d.mts +3 -3
- package/types/engine/actor-compiler.d.mts +45 -40
- package/types/engine/address-charset.d.mts +6 -6
- package/types/engine/address-diff.d.mts +60 -6
- package/types/engine/base-compiler.d.mts +27 -21
- package/types/engine/bundle-notes.d.mts +3 -3
- package/types/engine/bundles.d.mts +10 -1
- package/types/engine/code-fences.d.mts +3 -3
- package/types/engine/compendiums.d.mts +3 -3
- package/types/engine/compile-corpus.d.mts +1 -1
- package/types/engine/content-address.d.mts +20 -20
- package/types/engine/content-format-check.d.mts +6 -6
- package/types/engine/content-format.d.mts +2 -2
- package/types/engine/content-html.d.mts +78 -0
- package/types/engine/content-icons.d.mts +139 -92
- package/types/engine/content-index.d.mts +59 -15
- package/types/engine/content-links.d.mts +8 -8
- package/types/engine/content-lint.d.mts +8 -6
- package/types/engine/content-package.d.mts +6 -8
- package/types/engine/content-tables.d.mts +49 -18
- package/types/engine/derived-fields.d.mts +101 -0
- package/types/engine/diagnostics.d.mts +2 -2
- package/types/engine/document-subtypes.d.mts +3 -3
- package/types/engine/field-spec.d.mts +37 -39
- package/types/engine/folder-notes.d.mts +4 -5
- package/types/engine/foreign-catalog.d.mts +3 -3
- package/types/engine/foundry-entries.d.mts +6 -7
- package/types/engine/frontmatter-lint.d.mts +10 -9
- package/types/engine/frontmatter.d.mts +7 -7
- package/types/engine/generate.d.mts +7 -7
- package/types/engine/helpers.d.mts +128 -56
- package/types/engine/homepage.d.mts +16 -18
- package/types/engine/ids.d.mts +13 -13
- package/types/engine/index-records.d.mts +3 -3
- package/types/engine/index.d.mts +6 -0
- package/types/engine/item-compiler.d.mts +21 -5
- package/types/engine/item-docs.d.mts +2 -2
- package/types/engine/item-registry.d.mts +6 -6
- package/types/engine/journals.d.mts +12 -3
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/metadata-index.d.mts +4 -4
- package/types/engine/note-claims.d.mts +30 -22
- package/types/engine/note-ids.d.mts +4 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-renames.d.mts +3 -3
- package/types/engine/note-vocabulary.d.mts +31 -203
- package/types/engine/pack-config.d.mts +7 -7
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/pdf-build.d.mts +42 -0
- package/types/engine/pdf-fonts.d.mts +30 -0
- package/types/engine/pdf-render.d.mts +144 -0
- package/types/engine/pdf-toc.d.mts +114 -0
- package/types/engine/prose-config.d.mts +9 -9
- package/types/engine/prose-lint.d.mts +3 -4
- package/types/engine/region-events.d.mts +2 -2
- package/types/engine/retired-fields.d.mts +10 -9
- package/types/engine/scenes.d.mts +10 -1
- package/types/engine/schema-check.d.mts +13 -13
- package/types/engine/site-build.d.mts +52 -25
- package/types/engine/site-index.d.mts +3 -4
- package/types/engine/sql-tables.d.mts +11 -5
- package/types/engine/subtype-registry.d.mts +3 -3
- package/types/engine/system-block.d.mts +3 -3
- package/types/engine/web-wikilinks.d.mts +7 -7
- package/types/engine/wikilink-syntax.d.mts +17 -17
- package/types/engine/wikilinks.d.mts +14 -14
- package/types/hm3/actors.d.mts +9 -1
- package/types/hm3/document-subtypes.d.mts +1 -1
- package/types/hm3/items.d.mts +9 -2
- package/types/hm3/template-priority.d.mts +1 -1
- package/types/manifest.d.mts +8 -8
- package/types/release.d.mts +15 -4
- package/types/sohl/actors.d.mts +12 -4
- package/types/sohl/affiliation-standings.d.mts +2 -2
- package/types/sohl/being-info.d.mts +2 -2
- package/types/sohl/document-subtypes.d.mts +1 -1
- package/types/sohl/items.d.mts +9 -2
- package/types/sohl/note-schemas.d.mts +1 -1
- package/MIGRATING.md +0 -608
package/bin/content-build.mjs
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* configuration, directory creation, reading the shipped Foundry package
|
|
21
21
|
* manifest, and the process exit code. The library itself is import-safe, so a
|
|
22
22
|
* consuming repository's build — or a test — can call it without any of this
|
|
23
|
-
* happening
|
|
23
|
+
* happening.
|
|
24
24
|
*
|
|
25
25
|
* The side effects that need *configuration* live inside the command handler,
|
|
26
26
|
* not at module scope, so `--version` and `--help` answer in a directory that
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* either is missing.
|
|
30
30
|
*
|
|
31
31
|
* Every path and pack name it hands the library comes from the consuming
|
|
32
|
-
* repository's `package-build.config.yaml
|
|
32
|
+
* repository's `package-build.config.yaml`, located by
|
|
33
33
|
* `engine/pack-config.mjs`; nothing about any one repository's layout is
|
|
34
34
|
* written here.
|
|
35
35
|
*
|
|
@@ -63,7 +63,9 @@ import prefix from "loglevel-plugin-prefix";
|
|
|
63
63
|
import yargs from "yargs";
|
|
64
64
|
import { hideBin } from "yargs/helpers";
|
|
65
65
|
import { compilePacks, cleanPacks, unpackPacks } from "../engine/compendiums.mjs";
|
|
66
|
+
import { compilesFoundryDocuments } from "../content-config.mjs";
|
|
66
67
|
import { loadPackConfig } from "../engine/pack-config.mjs";
|
|
68
|
+
import { buildPdf } from "../engine/pdf-build.mjs";
|
|
67
69
|
import {
|
|
68
70
|
fetchAllCatalogs,
|
|
69
71
|
fetchCatalogFromPath,
|
|
@@ -80,6 +82,7 @@ import {
|
|
|
80
82
|
import { renderItemFieldReference } from "../engine/field-reference.mjs";
|
|
81
83
|
import { lintContentTree } from "../engine/content-lint.mjs";
|
|
82
84
|
import { lintContentCharset } from "../engine/content-charset.mjs";
|
|
85
|
+
import { lintContentHtml } from "../engine/content-html.mjs";
|
|
83
86
|
import { lintContentIcons } from "../engine/content-icons.mjs";
|
|
84
87
|
import { declaredSystems, lintFrontmatter, systemBlocksFor } from "../engine/frontmatter-lint.mjs";
|
|
85
88
|
import { loadContentFormat } from "../engine/content-format.mjs";
|
|
@@ -96,14 +99,14 @@ import {
|
|
|
96
99
|
} from "../engine/schema-check.mjs";
|
|
97
100
|
// The one vocabulary, loaded whole. Every content project authors the full type
|
|
98
101
|
// set — an adventure module ships skills, beings and magic swords — so no
|
|
99
|
-
// consumer gets a subset
|
|
102
|
+
// consumer gets a subset.
|
|
100
103
|
import { NOTE_SCHEMAS } from "../sohl/note-schemas.mjs";
|
|
101
104
|
// The shipped declarations, so this repository can check its own specification
|
|
102
|
-
// against them without standing up a consumer's configuration
|
|
105
|
+
// against them without standing up a consumer's configuration.
|
|
103
106
|
import { ITEM_FIELDS } from "../sohl/item-fields.mjs";
|
|
104
107
|
import { HM3_ITEM_FIELDS } from "../hm3/item-fields.mjs";
|
|
105
108
|
// The engine's own types, merged under the registry's so the vocabulary stands
|
|
106
|
-
// in a package that configures no `itemBuilders` at all
|
|
109
|
+
// in a package that configures no `itemBuilders` at all.
|
|
107
110
|
import { ENGINE_NOTE_SCHEMAS } from "../engine/note-schemas.mjs";
|
|
108
111
|
import { schemaSubtypeOf } from "../engine/subtype-registry.mjs";
|
|
109
112
|
import { NOTE_VOCABULARY } from "../engine/note-vocabulary.mjs";
|
|
@@ -122,7 +125,7 @@ import {
|
|
|
122
125
|
} from "../engine/site-build.mjs";
|
|
123
126
|
import { auditLinks, buildLinkIndex, walkReachability } from "../engine/content-links.mjs";
|
|
124
127
|
import { prepareTreeSqlTables } from "../engine/sql-tables.mjs";
|
|
125
|
-
// The one place a link finding is worded, shared with both builds
|
|
128
|
+
// The one place a link finding is worded, shared with both builds.
|
|
126
129
|
import { linkFindingMessage } from "../engine/wikilink-syntax.mjs";
|
|
127
130
|
import {
|
|
128
131
|
emitDiagnostic,
|
|
@@ -144,7 +147,7 @@ import { emittedArtFor, itemPackJsonDirs } from "../engine/generate.mjs";
|
|
|
144
147
|
* The packs `unpack` extracts.
|
|
145
148
|
*
|
|
146
149
|
* From the configuration's own pack list, which is where the build already
|
|
147
|
-
* knows them. It
|
|
150
|
+
* knows them. It does not come out of the shipped manifest — a second
|
|
148
151
|
* declaration of the same list, in a second format, with nothing checking that
|
|
149
152
|
* the two agreed. The manifest is generated from this list now
|
|
150
153
|
* (package-build#9), so reading it back would be a round trip through an
|
|
@@ -166,7 +169,7 @@ function configuredPacks() {
|
|
|
166
169
|
* defaults to the *nearest* `package.json` walking up from the working
|
|
167
170
|
* directory — inside a consuming repository that is the consumer's manifest, so
|
|
168
171
|
* `content-build --version` reported the consumer's version instead of the
|
|
169
|
-
* toolchain's
|
|
172
|
+
* toolchain's.
|
|
170
173
|
*
|
|
171
174
|
* @returns {string} The `version` field of this package's manifest.
|
|
172
175
|
*/
|
|
@@ -191,8 +194,8 @@ prefix.apply(log, {
|
|
|
191
194
|
/**
|
|
192
195
|
* Report a command's failure.
|
|
193
196
|
*
|
|
194
|
-
* A configuration error carries its own `file:line:column: error: ` locator
|
|
195
|
-
*
|
|
197
|
+
* A configuration error carries its own `file:line:column: error: ` locator,
|
|
198
|
+
* and `loglevel`'s `[timestamp] [ERROR]:` prefix occupies exactly the
|
|
196
199
|
* position a parser reads the path from — so a located failure is printed
|
|
197
200
|
* unprefixed, as `emitDiagnostic` prints every other finding. Everything else
|
|
198
201
|
* is ordinary prose and keeps the log line it always had.
|
|
@@ -244,15 +247,16 @@ const argv = yargs(hideBin(process.argv))
|
|
|
244
247
|
.command(markdownCommand())
|
|
245
248
|
.command(contentIndexCommand())
|
|
246
249
|
.command(siteCommand())
|
|
250
|
+
.command(pdfCommand())
|
|
247
251
|
.command(reachabilityCommand())
|
|
248
252
|
.command(addressesCommand())
|
|
249
253
|
.version(ownVersion())
|
|
250
254
|
.help()
|
|
251
255
|
.alias("help", "h")
|
|
252
|
-
// Every invocation this CLI accepts must be one it performs
|
|
256
|
+
// Every invocation this CLI accepts must be one it performs. yargs
|
|
253
257
|
// gives neither guarantee by default: without `demandCommand` a bare
|
|
254
258
|
// `content-build` exits 0 in silence, and without `strict` an unknown
|
|
255
|
-
// command or option is ignored rather than reported. Both
|
|
259
|
+
// command or option is ignored rather than reported. Both would read as
|
|
256
260
|
// success from a `run-s` chain, so a typo in a build script passed the step
|
|
257
261
|
// it was meant to run. The sibling toolchain `@heroiclands/package-build`
|
|
258
262
|
// opts into the same two.
|
|
@@ -264,7 +268,7 @@ const argv = yargs(hideBin(process.argv))
|
|
|
264
268
|
*
|
|
265
269
|
* The page is generated from the `fields` each `itemBuilders` entry declares,
|
|
266
270
|
* so every consuming repository documents *its own* registry with the same
|
|
267
|
-
* command
|
|
271
|
+
* command.
|
|
268
272
|
*
|
|
269
273
|
* **The framing comes from configuration**, because the tables are the only
|
|
270
274
|
* part that is the same everywhere. A repository's `docs.itemFields` says what
|
|
@@ -288,10 +292,10 @@ function docsCommand() {
|
|
|
288
292
|
command: "docs <action>",
|
|
289
293
|
describe: "Generate documentation from the configured registries",
|
|
290
294
|
builder: (yargs) => {
|
|
291
|
-
// Required and honoured
|
|
295
|
+
// Required and honoured, not optional and unread:
|
|
292
296
|
// the handler rendered the item-field reference whatever it was
|
|
293
297
|
// given, so the positional constrained what could be typed and
|
|
294
|
-
// selected nothing
|
|
298
|
+
// selected nothing.
|
|
295
299
|
yargs.positional("action", {
|
|
296
300
|
describe: "The document to render.",
|
|
297
301
|
type: "string",
|
|
@@ -348,13 +352,19 @@ function docsCommand() {
|
|
|
348
352
|
if (current !== page) {
|
|
349
353
|
// Staleness belongs to the whole file, so no line is
|
|
350
354
|
// named — the diagnostics contract drops a field it
|
|
351
|
-
// cannot supply rather than guessing one.
|
|
352
|
-
log.error
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
355
|
+
// cannot supply rather than guessing one. Routed
|
|
356
|
+
// through `emitDiagnostic`, not `log.error`, so the
|
|
357
|
+
// path starts the line unprefixed by loglevel's
|
|
358
|
+
// `[timestamp] [ERROR]:` banner — the same reason
|
|
359
|
+
// every other located failure in this file uses it.
|
|
360
|
+
emitDiagnostic({
|
|
361
|
+
file: relative,
|
|
362
|
+
severity: "error",
|
|
363
|
+
message:
|
|
364
|
+
"out of date with the item-field declarations " +
|
|
365
|
+
"— run `content-build docs item-fields` and " +
|
|
366
|
+
"commit the regenerated file",
|
|
367
|
+
});
|
|
358
368
|
process.exitCode = 1;
|
|
359
369
|
return;
|
|
360
370
|
}
|
|
@@ -380,7 +390,7 @@ function docsCommand() {
|
|
|
380
390
|
}
|
|
381
391
|
|
|
382
392
|
/**
|
|
383
|
-
* `content-build content-format` — check the format specification itself
|
|
393
|
+
* `content-build content-format` — check the format specification itself.
|
|
384
394
|
*
|
|
385
395
|
* Two checks, because the specification makes claims about two different
|
|
386
396
|
* worlds, and they fail for different reasons and at different times:
|
|
@@ -389,10 +399,9 @@ function docsCommand() {
|
|
|
389
399
|
* naming system's published `schema.json`. A failure means the specification
|
|
390
400
|
* and the system disagree, which is a defect in one of the two.
|
|
391
401
|
* - `fields` compares the per-type tables against the field declarations that
|
|
392
|
-
* compile them, so the hand-written half cannot drift from the generated one
|
|
393
|
-
* (#136).
|
|
402
|
+
* compile them, so the hand-written half cannot drift from the generated one.
|
|
394
403
|
* - `notes` measures a content tree against the vocabulary the document
|
|
395
|
-
* declares per type. During
|
|
404
|
+
* declares per type. During the migration it is the progress bar rather
|
|
396
405
|
* than a gate, so it **reports** by default and `--strict` makes it fatal —
|
|
397
406
|
* turned on one class at a time as each slice lands.
|
|
398
407
|
*
|
|
@@ -535,7 +544,7 @@ function declarationsFrom(argv) {
|
|
|
535
544
|
* The specification hand-writes a `data` table under most of its type sections,
|
|
536
545
|
* covering ground {@link module:engine/field-reference} already generates from
|
|
537
546
|
* the `fields` on each `itemBuilders` entry — the duplication that module exists
|
|
538
|
-
* to prevent, one document over
|
|
547
|
+
* to prevent, one document over.
|
|
539
548
|
*
|
|
540
549
|
* **Checked, not merged.** The document's vocabulary spans note types that
|
|
541
550
|
* produce Scenes, Macros and JournalEntries, which no item registry covers, so
|
|
@@ -566,7 +575,7 @@ function contentFormatFieldsCommand() {
|
|
|
566
575
|
});
|
|
567
576
|
yargs.option("coverage", {
|
|
568
577
|
describe:
|
|
569
|
-
"List, per type, the fields only one side names. They are not findings — the two vocabularies differ by design until
|
|
578
|
+
"List, per type, the fields only one side names. They are not findings — the two vocabularies differ by design until the corpus moves.",
|
|
570
579
|
type: "boolean",
|
|
571
580
|
default: false,
|
|
572
581
|
});
|
|
@@ -627,8 +636,8 @@ function contentFormatFieldsCommand() {
|
|
|
627
636
|
*
|
|
628
637
|
* **A report, not a gate.** Every authored note predates the format, so a
|
|
629
638
|
* failing check would be red in every repository from the day it lands and
|
|
630
|
-
* would stay red for the length of
|
|
631
|
-
* `--strict` raises the findings to errors,
|
|
639
|
+
* would stay red for the length of the migration — which is a check nobody
|
|
640
|
+
* can act on. `--strict` raises the findings to errors, turned on slice by
|
|
632
641
|
* slice as each class of finding reaches zero.
|
|
633
642
|
*
|
|
634
643
|
* @returns {object} The yargs command module.
|
|
@@ -649,7 +658,7 @@ function contentFormatNotesCommand() {
|
|
|
649
658
|
});
|
|
650
659
|
yargs.option("strict", {
|
|
651
660
|
describe:
|
|
652
|
-
"Fail on the findings instead of reporting them. Turned on per slice
|
|
661
|
+
"Fail on the findings instead of reporting them. Turned on per slice, as each class reaches zero.",
|
|
653
662
|
type: "boolean",
|
|
654
663
|
default: false,
|
|
655
664
|
});
|
|
@@ -660,7 +669,7 @@ function contentFormatNotesCommand() {
|
|
|
660
669
|
const root = argv.root ?? config.paths.content;
|
|
661
670
|
const format = specFrom(argv);
|
|
662
671
|
|
|
663
|
-
// The corpus from the index, like every other check
|
|
672
|
+
// The corpus from the index, like every other check.
|
|
664
673
|
// A report measuring the tree against the declared vocabulary
|
|
665
674
|
// has to be looking at the same tree the compile will, or its
|
|
666
675
|
// counts describe a corpus nobody builds.
|
|
@@ -745,14 +754,14 @@ function lintCommand() {
|
|
|
745
754
|
const root = argv.root ?? config.paths.content;
|
|
746
755
|
|
|
747
756
|
// The corpus, enumerated once for this command and handed to
|
|
748
|
-
// every pass below, rather than derived again by each
|
|
757
|
+
// every pass below, rather than derived again by each.
|
|
749
758
|
// The address lint reads it, the `sql` tables select over it
|
|
750
759
|
// and the link index is built from it, so no two findings this
|
|
751
760
|
// command reports can be drawn from different ideas of which
|
|
752
761
|
// files the content is.
|
|
753
762
|
//
|
|
754
763
|
// A note the index cannot record is reported like any other
|
|
755
|
-
// finding rather than thrown
|
|
764
|
+
// finding rather than thrown: one malformed note must
|
|
756
765
|
// not take every other finding in the tree with it, and the
|
|
757
766
|
// reader needs a line to open, not a stack.
|
|
758
767
|
const corpusProblems = [];
|
|
@@ -768,7 +777,7 @@ function lintCommand() {
|
|
|
768
777
|
// would call the tree clean while silently omitting a note.
|
|
769
778
|
if (corpusProblems.length) process.exitCode = 1;
|
|
770
779
|
|
|
771
|
-
// The package is passed for the homepage rule
|
|
780
|
+
// The package is passed for the homepage rule, which
|
|
772
781
|
// names the address a tree with no front page fails to serve.
|
|
773
782
|
const addresses = lintContentTree(root, {
|
|
774
783
|
contentPackage: config.contentPackage,
|
|
@@ -790,7 +799,7 @@ function lintCommand() {
|
|
|
790
799
|
}),
|
|
791
800
|
});
|
|
792
801
|
// Which system blocks this tree carries, derived from what it
|
|
793
|
-
// declares it ships for
|
|
802
|
+
// declares it ships for. Read before the lint so the
|
|
794
803
|
// systems it will *not* check can be said out loud below.
|
|
795
804
|
// `schemaSystem` names whose vocabulary the `schemas` below
|
|
796
805
|
// are. They are `sohl/note-schemas.mjs`, imported here
|
|
@@ -823,18 +832,18 @@ function lintCommand() {
|
|
|
823
832
|
}
|
|
824
833
|
const frontmatter = lintFrontmatter(index, {
|
|
825
834
|
schemas: { ...ENGINE_NOTE_SCHEMAS, ...NOTE_SCHEMAS },
|
|
826
|
-
// The closed frontmatter regions
|
|
835
|
+
// The closed frontmatter regions. Passed in rather
|
|
827
836
|
// than reached for, so the linter stays a checker of
|
|
828
837
|
// whatever it is handed and this stays the one place that
|
|
829
838
|
// decides which vocabulary a tree is held to.
|
|
830
839
|
vocabulary: NOTE_VOCABULARY,
|
|
831
840
|
// The pack names, for a `data:` field keyed by pack — a
|
|
832
|
-
// folder's `parent` is one
|
|
841
|
+
// folder's `parent` is one. Companions included:
|
|
833
842
|
// the compile asks the map for whichever pack it is
|
|
834
843
|
// writing, and a companion is a pack it writes.
|
|
835
844
|
packs: config.packDirectories,
|
|
836
845
|
// What art each type actually reaches its document through,
|
|
837
|
-
// asked of the passes rather than listed here
|
|
846
|
+
// asked of the passes rather than listed here. This
|
|
838
847
|
// is the one place that decides what a tree is held to, so
|
|
839
848
|
// it is where the derivation is handed over — the linter
|
|
840
849
|
// states no list of iconless types of its own.
|
|
@@ -850,7 +859,7 @@ function lintCommand() {
|
|
|
850
859
|
});
|
|
851
860
|
|
|
852
861
|
// What the builders emit, against what the receiving system
|
|
853
|
-
// declares
|
|
862
|
+
// declares. Reported here rather than at compile: it is
|
|
854
863
|
// a property of the *declarations*, not of any one note, so it
|
|
855
864
|
// is the same answer for every document and belongs where a
|
|
856
865
|
// reader is already being told about the vocabulary.
|
|
@@ -900,7 +909,7 @@ function lintCommand() {
|
|
|
900
909
|
artifact: schema.artifact,
|
|
901
910
|
// A schema is keyed by document subtype and a field
|
|
902
911
|
// declaration by note type. Those were one string until
|
|
903
|
-
//
|
|
912
|
+
// Three are renamed, and joining them by name
|
|
904
913
|
// after that would drop `armorgear`'s findings without
|
|
905
914
|
// saying so — the seam exists for exactly this.
|
|
906
915
|
subtypeOf: (type) => schemaSubtypeOf(config.stats?.systemId, type),
|
|
@@ -924,25 +933,33 @@ function lintCommand() {
|
|
|
924
933
|
}
|
|
925
934
|
}
|
|
926
935
|
|
|
927
|
-
// The charset the tree is held to, so a book can pick its face
|
|
928
|
-
//
|
|
936
|
+
// The charset the tree is held to, so a book can pick its face.
|
|
937
|
+
// Run over the raw files rather than the parsed notes:
|
|
929
938
|
// the subject is every character authored, including the ones
|
|
930
939
|
// that stopped a note parsing at all.
|
|
931
940
|
const charset = lintContentCharset(root, {
|
|
932
941
|
skipDirectories: config.skipDirectories,
|
|
933
942
|
});
|
|
934
943
|
|
|
935
|
-
// The names the charset check leaves room for
|
|
944
|
+
// The names the charset check leaves room for. An icon
|
|
936
945
|
// the registry does not declare renders as its own literal
|
|
937
946
|
// text, which is visible but easy to publish, so it is reported
|
|
938
947
|
// here rather than left for a reader to notice.
|
|
939
948
|
//
|
|
940
|
-
// The
|
|
941
|
-
//
|
|
942
|
-
//
|
|
943
|
-
// being read here before anything declares it.
|
|
949
|
+
// The configured registry — the shipped table with this
|
|
950
|
+
// package's own entries merged over it, which is where a
|
|
951
|
+
// Game-Icons glyph becomes a name a note may write.
|
|
944
952
|
const icons = lintContentIcons(root, {
|
|
945
953
|
skipDirectories: config.skipDirectories,
|
|
954
|
+
registry: config.icons,
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
// The markup the charset check cannot see. Class names are
|
|
958
|
+
// ASCII, so a page of `<i class="fa-…">` is allowlist-clean and
|
|
959
|
+
// still unrenderable in a book — the character rule one level
|
|
960
|
+
// up.
|
|
961
|
+
const html = lintContentHtml(root, {
|
|
962
|
+
skipDirectories: config.skipDirectories,
|
|
946
963
|
});
|
|
947
964
|
|
|
948
965
|
const findings = [
|
|
@@ -951,9 +968,10 @@ function lintCommand() {
|
|
|
951
968
|
...schemaFindings,
|
|
952
969
|
...charset.findings,
|
|
953
970
|
...icons.findings,
|
|
971
|
+
...html.findings,
|
|
954
972
|
];
|
|
955
973
|
// Only an **error** fails the run. Every finding was an error
|
|
956
|
-
//
|
|
974
|
+
// by then, so this changes nothing on its own —
|
|
957
975
|
// but a field retired in favour of another is reported while
|
|
958
976
|
// both spellings still compile, and failing a build over a note
|
|
959
977
|
// that produces the correct document would red a tree that has
|
|
@@ -1002,7 +1020,7 @@ function lintCommand() {
|
|
|
1002
1020
|
* reports, as warnings, each shared convention the repository's own
|
|
1003
1021
|
* configuration resolves differently — or that it declares no configuration at
|
|
1004
1022
|
* all, which guarantees an editor and a bare `npx prettier` disagree with this
|
|
1005
|
-
* command about the same tree
|
|
1023
|
+
* command about the same tree. Nothing there fails the run: the point is
|
|
1006
1024
|
* that a local choice is deliberate rather than silent.
|
|
1007
1025
|
*
|
|
1008
1026
|
* @returns {object} The yargs command module.
|
|
@@ -1040,7 +1058,7 @@ function formatCommand() {
|
|
|
1040
1058
|
const root = process.cwd();
|
|
1041
1059
|
// Before the per-file report, because it is the context for it:
|
|
1042
1060
|
// which rules this run applied, and whether anything else in
|
|
1043
|
-
// the repository applies the same ones
|
|
1061
|
+
// the repository applies the same ones. Warnings only —
|
|
1044
1062
|
// a consumer's config wins by design, so none of this touches
|
|
1045
1063
|
// the exit code.
|
|
1046
1064
|
const conventions = await checkPrettierConventions(root);
|
|
@@ -1065,7 +1083,7 @@ function formatCommand() {
|
|
|
1065
1083
|
// `--write` collects findings too — a file Prettier cannot
|
|
1066
1084
|
// parse, or one that will not format to a fixpoint — and
|
|
1067
1085
|
// used to discard them, so a run that had left files
|
|
1068
|
-
// unformatted still reported success and exited 0
|
|
1086
|
+
// unformatted still reported success and exited 0.
|
|
1069
1087
|
for (const finding of findings) emitDiagnostic(finding);
|
|
1070
1088
|
if (findings.length) {
|
|
1071
1089
|
log.error(
|
|
@@ -1166,7 +1184,7 @@ function linksCommand() {
|
|
|
1166
1184
|
const contentBase = argv.root ?? config.paths.content;
|
|
1167
1185
|
|
|
1168
1186
|
const scope = { skipDirectories: config.skipDirectories };
|
|
1169
|
-
// Enumerated once and shared, as in `lint
|
|
1187
|
+
// Enumerated once and shared, as in `lint`, and a note
|
|
1170
1188
|
// it cannot record is reported rather than thrown.
|
|
1171
1189
|
const corpusProblems = [];
|
|
1172
1190
|
const records = indexRecordsFor({
|
|
@@ -1238,8 +1256,8 @@ function linksCommand() {
|
|
|
1238
1256
|
`heading in ${d.dest.rel} declares`,
|
|
1239
1257
|
});
|
|
1240
1258
|
}
|
|
1241
|
-
// Every link is an address
|
|
1242
|
-
// resolve
|
|
1259
|
+
// Every link is an address and every address must
|
|
1260
|
+
// resolve, so all of these are errors — but they read
|
|
1243
1261
|
// differently because the corrections differ. The wording comes
|
|
1244
1262
|
// from the shared table, so the checker cannot describe a
|
|
1245
1263
|
// defect differently from the build that also refuses it.
|
|
@@ -1265,7 +1283,7 @@ function linksCommand() {
|
|
|
1265
1283
|
// The package homepage. Its addresses are markdown links and
|
|
1266
1284
|
// `landing:` url/href fields rather than wikilinks — it is
|
|
1267
1285
|
// published verbatim, so nothing resolves a wikilink on it —
|
|
1268
|
-
// and
|
|
1286
|
+
// and nothing else looks at them.
|
|
1269
1287
|
for (const h of homepageLinks) {
|
|
1270
1288
|
emitDiagnostic({
|
|
1271
1289
|
file: h.note.file,
|
|
@@ -1307,7 +1325,7 @@ function linksCommand() {
|
|
|
1307
1325
|
*
|
|
1308
1326
|
* Every build already walks the tree and parses every note's frontmatter, then
|
|
1309
1327
|
* throws the result away, so nothing outside a build can ask a question about
|
|
1310
|
-
* the content
|
|
1328
|
+
* the content. This publishes that walk as JSON Lines: one record per
|
|
1311
1329
|
* note, carrying the whole frontmatter plus the note's place in the tree.
|
|
1312
1330
|
*
|
|
1313
1331
|
* It is a command of its own rather than only a build step because the point of
|
|
@@ -1354,11 +1372,92 @@ function contentIndexCommand() {
|
|
|
1354
1372
|
};
|
|
1355
1373
|
}
|
|
1356
1374
|
|
|
1375
|
+
/**
|
|
1376
|
+
* `content-build pdf` — build the book the content tree publishes as.
|
|
1377
|
+
*
|
|
1378
|
+
* The third surface, beside `package compile` and `site`. It takes the same
|
|
1379
|
+
* `--out` override the site command does, and reports what it found in the same
|
|
1380
|
+
* `file:line:column: severity: message` shape every other pass here uses — so
|
|
1381
|
+
* one editor, one CI annotator and one `grep` read all three.
|
|
1382
|
+
*
|
|
1383
|
+
* **Not building is a normal outcome, and it exits 0.** A package publishing
|
|
1384
|
+
* only a homepage, a package with no `pdf:` block and a package with no content
|
|
1385
|
+
* tree have each said they publish no book; saying so on stderr and failing the
|
|
1386
|
+
* command would break the release of every package that is not a book.
|
|
1387
|
+
*
|
|
1388
|
+
* @returns {object} The yargs command module.
|
|
1389
|
+
*/
|
|
1390
|
+
function pdfCommand() {
|
|
1391
|
+
return {
|
|
1392
|
+
command: "pdf",
|
|
1393
|
+
describe: "Build the content tree as a PDF",
|
|
1394
|
+
builder: (yargs) => {
|
|
1395
|
+
yargs
|
|
1396
|
+
.option("out", {
|
|
1397
|
+
describe: "Write the book here instead of the configured `pdf.out`.",
|
|
1398
|
+
type: "string",
|
|
1399
|
+
})
|
|
1400
|
+
.option("book-version", {
|
|
1401
|
+
describe: "Stamp this version on the title page and in the file name.",
|
|
1402
|
+
type: "string",
|
|
1403
|
+
})
|
|
1404
|
+
// Declared positively so yargs derives `--no-compile` from it;
|
|
1405
|
+
// an option literally named `no-compile` is rejected as unknown
|
|
1406
|
+
// when it is actually passed.
|
|
1407
|
+
.option("compile", {
|
|
1408
|
+
describe: "Run the Typst compiler. `--no-compile` emits the source and stops.",
|
|
1409
|
+
type: "boolean",
|
|
1410
|
+
default: true,
|
|
1411
|
+
});
|
|
1412
|
+
},
|
|
1413
|
+
handler: async (argv) => {
|
|
1414
|
+
try {
|
|
1415
|
+
const result = await buildPdf({
|
|
1416
|
+
...(argv.out ? { out: argv.out } : {}),
|
|
1417
|
+
...(argv.bookVersion ? { version: String(argv.bookVersion) } : {}),
|
|
1418
|
+
compile: argv.compile !== false,
|
|
1419
|
+
});
|
|
1420
|
+
|
|
1421
|
+
for (const finding of result.findings) emitDiagnostic(finding);
|
|
1422
|
+
|
|
1423
|
+
if (!result.built) {
|
|
1424
|
+
// A reason is a deliberate no-op — the fence, an absent
|
|
1425
|
+
// block, an absent tree. No reason means the findings above
|
|
1426
|
+
// say what went wrong, and those decide the exit code.
|
|
1427
|
+
if (result.reason) {
|
|
1428
|
+
log.info(`No book built: ${result.reason}`);
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
process.exitCode = 1;
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
const { stats } = result;
|
|
1436
|
+
log.info(
|
|
1437
|
+
`${stats.notes} entr(ies) and ${stats.prose} prose file(s) across ` +
|
|
1438
|
+
`${stats.sections} section(s)` +
|
|
1439
|
+
(stats.repeated ?
|
|
1440
|
+
`, ${stats.repeated} of them printed more than once`
|
|
1441
|
+
: ""),
|
|
1442
|
+
);
|
|
1443
|
+
log.info(`Typst source: ${result.typ}`);
|
|
1444
|
+
if (result.pdf) log.info(`Book: ${result.pdf}`);
|
|
1445
|
+
// Findings are reported, never fatal — a filter that selected
|
|
1446
|
+
// nothing is worth fixing and is not worth refusing to publish
|
|
1447
|
+
// the other two thousand entries over.
|
|
1448
|
+
} catch (err) {
|
|
1449
|
+
reportFailure(err);
|
|
1450
|
+
process.exitCode = 1;
|
|
1451
|
+
}
|
|
1452
|
+
},
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1357
1456
|
/**
|
|
1358
1457
|
* `content-build site` — publish the content tree as a website.
|
|
1359
1458
|
*
|
|
1360
1459
|
* The sibling of `package compile`: the same tree, rendered as pages instead of
|
|
1361
|
-
* compiled into packs
|
|
1460
|
+
* compiled into packs. Everything a consumer would otherwise write for itself —
|
|
1362
1461
|
* the walk, the address derivation, the address index, table expansion,
|
|
1363
1462
|
* wikilink resolution, code-fence protection, the foreign-manifest merge and
|
|
1364
1463
|
* the section-landing backfill — happens here, from configuration.
|
|
@@ -1394,7 +1493,7 @@ function siteCommand() {
|
|
|
1394
1493
|
// First, because it is decided before the tree is walked and
|
|
1395
1494
|
// before the output is cleared: a package with no front page,
|
|
1396
1495
|
// or two competing for it, has nothing to say about its pages
|
|
1397
|
-
// yet
|
|
1496
|
+
// yet.
|
|
1398
1497
|
for (const f of gates.homepages) emitDiagnostic(f);
|
|
1399
1498
|
for (const f of gates.frontmatterLinks) {
|
|
1400
1499
|
emitDiagnostic({
|
|
@@ -1440,7 +1539,7 @@ function siteCommand() {
|
|
|
1440
1539
|
// was prose with a timestamp where a parser reads the path,
|
|
1441
1540
|
// which made one authored table produce a machine-readable
|
|
1442
1541
|
// diagnostic from one build and something ungreppable from the
|
|
1443
|
-
// other
|
|
1542
|
+
// other.
|
|
1444
1543
|
for (const e of result.tableErrors) {
|
|
1445
1544
|
emitDiagnostic({
|
|
1446
1545
|
file: e.source,
|
|
@@ -1452,7 +1551,7 @@ function siteCommand() {
|
|
|
1452
1551
|
}
|
|
1453
1552
|
// Reported the way the pack build reports the very same
|
|
1454
1553
|
// finding: `file:line:column: error: message`, path first, and
|
|
1455
|
-
// the message from the shared table
|
|
1554
|
+
// the message from the shared table, not a
|
|
1456
1555
|
// `log.error` whose timestamp prefix sat where a parser reads
|
|
1457
1556
|
// the path from, and whose text named a `reason` code rather
|
|
1458
1557
|
// than saying what to do — so one authored link produced a
|
|
@@ -1531,7 +1630,7 @@ function reachabilityCommand() {
|
|
|
1531
1630
|
try {
|
|
1532
1631
|
// Resolved once and passed on, so every pass below runs
|
|
1533
1632
|
// against the configuration this command resolved rather than
|
|
1534
|
-
// whichever one the working directory answers with
|
|
1633
|
+
// whichever one the working directory answers with.
|
|
1535
1634
|
const config = loadPackConfig();
|
|
1536
1635
|
const contentBase = argv.root ?? config.paths.content;
|
|
1537
1636
|
const dir = String(argv.dir).replace(/\/+$/, "");
|
|
@@ -1602,30 +1701,6 @@ function reachabilityCommand() {
|
|
|
1602
1701
|
}
|
|
1603
1702
|
|
|
1604
1703
|
// eslint-disable-next-line
|
|
1605
|
-
/**
|
|
1606
|
-
* `deps fetch` — fill the caches this build resolves other packages through:
|
|
1607
|
-
* the **content index** of every declared dependency (#239), and the **item
|
|
1608
|
-
* catalogue** of those additionally declaring `itemCatalog: true`.
|
|
1609
|
-
*
|
|
1610
|
-
* The two sets differ deliberately. Citing another package's *addresses* and
|
|
1611
|
-
* embedding its *items* are separate edges, and a package may have either
|
|
1612
|
-
* without the other — `harn-ensemble` cites no foreign address and embeds
|
|
1613
|
-
* 324,016 item references.
|
|
1614
|
-
*
|
|
1615
|
-
* Its own command rather than a step of `package compile`, so that a compile
|
|
1616
|
-
* never reaches the network. A build that downloads silently is not
|
|
1617
|
-
* reproducible, breaks offline, and hides a dependency's version change behind
|
|
1618
|
-
* a passing run.
|
|
1619
|
-
*
|
|
1620
|
-
* `--from` fills the cache from a locally built artifact instead of a release,
|
|
1621
|
-
* which is what makes iterating across packages possible: change the system,
|
|
1622
|
-
* build it, and see the effect on every consumer **before** any of it ships.
|
|
1623
|
-
* Otherwise testing a dependency change against its consumers costs a release
|
|
1624
|
-
* round-trip, which makes releasing a debugging tool rather than a publishing
|
|
1625
|
-
* decision.
|
|
1626
|
-
*
|
|
1627
|
-
* @returns {object} The yargs command module.
|
|
1628
|
-
*/
|
|
1629
1704
|
/**
|
|
1630
1705
|
* Resolve which declared dependency `--from` supplies, and cache it.
|
|
1631
1706
|
*
|
|
@@ -1659,12 +1734,36 @@ async function fetchFromLocalArtifact(config, argv) {
|
|
|
1659
1734
|
}
|
|
1660
1735
|
}
|
|
1661
1736
|
|
|
1737
|
+
/**
|
|
1738
|
+
* `deps fetch` — fill the caches this build resolves other packages through:
|
|
1739
|
+
* the **content index** of every declared dependency, and the **item
|
|
1740
|
+
* catalogue** of those additionally declaring `itemCatalog: true`.
|
|
1741
|
+
*
|
|
1742
|
+
* The two sets differ deliberately. Citing another package's *addresses* and
|
|
1743
|
+
* embedding its *items* are separate edges, and a package may have either
|
|
1744
|
+
* without the other — `harn-ensemble` cites no foreign address and embeds
|
|
1745
|
+
* 324,016 item references.
|
|
1746
|
+
*
|
|
1747
|
+
* Its own command rather than a step of `package compile`, so that a compile
|
|
1748
|
+
* never reaches the network. A build that downloads silently is not
|
|
1749
|
+
* reproducible, breaks offline, and hides a dependency's version change behind
|
|
1750
|
+
* a passing run.
|
|
1751
|
+
*
|
|
1752
|
+
* `--from` fills the cache from a locally built artifact instead of a release,
|
|
1753
|
+
* which is what makes iterating across packages possible: change the system,
|
|
1754
|
+
* build it, and see the effect on every consumer **before** any of it ships.
|
|
1755
|
+
* Otherwise testing a dependency change against its consumers costs a release
|
|
1756
|
+
* round-trip, which makes releasing a debugging tool rather than a publishing
|
|
1757
|
+
* decision.
|
|
1758
|
+
*
|
|
1759
|
+
* @returns {object} The yargs command module.
|
|
1760
|
+
*/
|
|
1662
1761
|
function depsCommand() {
|
|
1663
1762
|
return {
|
|
1664
1763
|
command: "deps <action>",
|
|
1665
1764
|
describe: "Manage build-time dependencies on other packages",
|
|
1666
1765
|
builder: (yargs) => {
|
|
1667
|
-
// Required, for the reason `package <action>` is
|
|
1766
|
+
// Required, for the reason `package <action>` is: an optional
|
|
1668
1767
|
// action exits 0 having done nothing.
|
|
1669
1768
|
yargs.positional("action", {
|
|
1670
1769
|
describe: "The action to perform.",
|
|
@@ -1761,7 +1860,7 @@ async function diffAddresses(config, argv) {
|
|
|
1761
1860
|
);
|
|
1762
1861
|
}
|
|
1763
1862
|
|
|
1764
|
-
// Stated by the caller, like every other corpus read in this file
|
|
1863
|
+
// Stated by the caller, like every other corpus read in this file:
|
|
1765
1864
|
// the two tree reads below must agree with each other and with the compile
|
|
1766
1865
|
// about which files are the corpus. They now do so by construction — the
|
|
1767
1866
|
// corpus is derived once, here, and handed to both.
|
|
@@ -1823,7 +1922,7 @@ function addressesCommand() {
|
|
|
1823
1922
|
command: "addresses <action>",
|
|
1824
1923
|
describe: "Compare the addresses this build publishes against a release's",
|
|
1825
1924
|
builder: (yargs) => {
|
|
1826
|
-
// Required, for the reason every other action is
|
|
1925
|
+
// Required, for the reason every other action is: an
|
|
1827
1926
|
// optional one exits 0 having compared nothing.
|
|
1828
1927
|
yargs.positional("action", {
|
|
1829
1928
|
describe: "The action to perform.",
|
|
@@ -1875,7 +1974,7 @@ function packageCommand() {
|
|
|
1875
1974
|
builder: (yargs) => {
|
|
1876
1975
|
// Required, not optional: the action *is* the work, and an
|
|
1877
1976
|
// optional one meant `content-build package` fell through the
|
|
1878
|
-
// switch below and exited 0 having compiled nothing
|
|
1977
|
+
// switch below and exited 0 having compiled nothing.
|
|
1879
1978
|
yargs.positional("action", {
|
|
1880
1979
|
describe: "The action to perform.",
|
|
1881
1980
|
type: "string",
|
|
@@ -1897,17 +1996,30 @@ function packageCommand() {
|
|
|
1897
1996
|
// an unhandled-rejection stack trace. Report the message and set a
|
|
1898
1997
|
// failing exit code, so a build guard reads as a build failure.
|
|
1899
1998
|
try {
|
|
1999
|
+
const config = loadPackConfig();
|
|
2000
|
+
// The compile passes do not run for a package that declares no
|
|
2001
|
+
// packs by rule. Refused rather than exiting 0 having compiled
|
|
2002
|
+
// nothing: a build that succeeds and produces no documents is
|
|
2003
|
+
// the quiet failure this toolchain reports everywhere else.
|
|
2004
|
+
if (!compilesFoundryDocuments(config)) {
|
|
2005
|
+
throw new Error(
|
|
2006
|
+
`\`packageKind: ${config.packageKind}\` compiles no ` +
|
|
2007
|
+
`compendium, so there is nothing to ${action}. Build ` +
|
|
2008
|
+
`its site with \`content-build site\` and its book ` +
|
|
2009
|
+
`with \`content-build pdf\`.`,
|
|
2010
|
+
);
|
|
2011
|
+
}
|
|
1900
2012
|
// The one directory the pipeline creates rather than expects:
|
|
1901
2013
|
// `unpack` writes the extracted JSON there and `compile` reads
|
|
1902
2014
|
// it back. Created here rather than at module scope so that
|
|
1903
2015
|
// asking the CLI its version needs no configuration (#2).
|
|
1904
|
-
fs.mkdirSync(
|
|
2016
|
+
fs.mkdirSync(config.paths.unpack, {
|
|
1905
2017
|
recursive: true,
|
|
1906
2018
|
});
|
|
1907
2019
|
switch (action) {
|
|
1908
2020
|
// Every path and pack list the library needs is defaulted
|
|
1909
2021
|
// from the resolved configuration, so nothing is restated
|
|
1910
|
-
// here
|
|
2022
|
+
// here.
|
|
1911
2023
|
case "compile":
|
|
1912
2024
|
return await compilePacks({ packName: pack });
|
|
1913
2025
|
case "clean":
|