@heroiclands/package-build 23.13.0 → 24.0.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 +50 -0
- package/README.md +2 -1
- package/assets/preview/gitea.ini +12 -7
- package/assets/styles/content-base.css +150 -1
- package/bin/content-commands.mjs +356 -210
- package/bin/package-build.mjs +3 -2
- package/ci/check-banners.mjs +7 -7
- package/config.mjs +21 -6
- package/content-config.mjs +199 -80
- package/docs/api.md +93 -72
- package/docs/authoring/links-and-markup.md +316 -78
- package/docs/commands.md +248 -80
- package/docs/configuration.md +210 -102
- package/docs/content-format.md +2 -2
- package/docs/diagnostics.md +2 -2
- package/docs/getting-started.md +1 -1
- package/docs/guides/icons.md +1 -1
- package/docs/guides/module-project.md +5 -8
- package/docs/guides/release-and-deploy.md +2 -2
- package/docs/guides/site.md +155 -23
- package/docs/guides/system-project.md +1 -1
- package/docs/guides/writing-in-invented-scripts.md +1247 -0
- package/docs/index.md +1 -0
- package/docs/project-setup.md +28 -30
- package/docs/reference/format-details.md +589 -308
- package/docs/reference/note-types.md +40 -10
- package/docs/reference/theme-pages.md +127 -108
- package/docs/source-preview.md +15 -1
- package/engine/asset-shipping.mjs +22 -10
- package/engine/base-compiler.mjs +62 -104
- package/engine/changelog-lint.mjs +1 -1
- package/engine/content-address.mjs +1 -1
- package/engine/content-alerts.mjs +8 -4
- package/engine/content-blocks.mjs +26 -11
- package/engine/content-embeds.mjs +1 -1
- package/engine/content-expand.mjs +376 -0
- package/engine/content-figures.mjs +13 -6
- package/engine/content-format.yaml +8 -0
- package/engine/content-glyphs.mjs +213 -0
- package/engine/content-images.mjs +6 -7
- package/engine/content-links.mjs +3 -3
- package/engine/content-lint.mjs +1 -1
- package/engine/content-render.mjs +453 -0
- package/engine/content-scripts.mjs +326 -27
- package/engine/content-spans.mjs +4 -1
- package/engine/content-styles.mjs +91 -0
- package/engine/content-symbols.mjs +186 -0
- package/engine/content-verse.mjs +6 -18
- package/engine/core-report.mjs +169 -0
- package/engine/core-vocabulary.mjs +208 -0
- package/engine/dictionary-html.mjs +119 -0
- package/engine/field-reference.mjs +1 -1
- package/engine/frontmatter-lint.mjs +1 -1
- package/engine/heading-attributes.mjs +89 -0
- package/engine/helpers.mjs +61 -101
- package/engine/homepage.mjs +17 -29
- package/engine/html-minify.mjs +70 -0
- package/engine/index.mjs +8 -5
- package/engine/language-rows.mjs +8 -2
- package/engine/language-terms.mjs +115 -14
- package/engine/language-words.mjs +12 -0
- package/engine/logographic.mjs +255 -0
- package/engine/map-lexicon.mjs +221 -25
- package/engine/map-places.mjs +5 -4
- package/engine/markdown-expressions.mjs +0 -2
- package/engine/markdownlint-run.mjs +9 -3
- package/engine/markup-validation.mjs +21 -0
- package/engine/metre-declaration.mjs +134 -0
- package/engine/note-matter.mjs +2 -2
- package/engine/note-vocabulary.mjs +187 -3
- package/engine/pdf-build.mjs +68 -133
- package/engine/pdf-render.mjs +102 -44
- package/engine/post-fields.mjs +157 -0
- package/engine/preview-index.mjs +130 -0
- package/engine/preview-source.mjs +450 -0
- package/engine/project-init.mjs +5 -12
- package/engine/prose-config.mjs +3 -3
- package/engine/run-words.mjs +3 -2
- package/engine/script-emphasis-terms.mjs +38 -0
- package/engine/script-emphasis.mjs +295 -0
- package/engine/script-font-delivery.mjs +4 -4
- package/engine/site-build.mjs +265 -313
- package/engine/site-config.mjs +26 -238
- package/engine/site-files.mjs +175 -0
- package/engine/site-index.mjs +9 -4
- package/engine/site-preview.mjs +50 -523
- package/engine/site-reach.mjs +213 -0
- package/engine/site-render.mjs +668 -0
- package/engine/site-root.mjs +90 -39
- package/engine/site-search.mjs +161 -0
- package/engine/site-serve.mjs +274 -0
- package/engine/site-theme-banner.mjs +154 -0
- package/engine/site-theme-urls.mjs +125 -0
- package/engine/site-theme.mjs +939 -0
- package/engine/sql-tables.mjs +9 -6
- package/engine/text-maps.mjs +57 -10
- package/engine/typographer.mjs +248 -0
- package/engine/verse-metre.mjs +357 -0
- package/engine/wikilink-syntax.mjs +29 -47
- package/engine/wikilinks.mjs +758 -279
- package/engine/word-forms.mjs +39 -24
- package/engine/word-rows.mjs +12 -2
- package/engine/word-terms.mjs +29 -4
- package/manifest.mjs +3 -4
- package/package.json +10 -7
- package/{hugo-theme → site-theme}/data/banners.yaml +6 -10
- package/site-theme/layouts/base.hbs +31 -0
- package/site-theme/layouts/blog-list.hbs +30 -0
- package/site-theme/layouts/blog-post.hbs +40 -0
- package/site-theme/layouts/home.hbs +35 -0
- package/site-theme/layouts/list.hbs +20 -0
- package/site-theme/layouts/not-found.hbs +31 -0
- package/site-theme/layouts/page.hbs +7 -0
- package/site-theme/partials/copy-buttons.hbs +37 -0
- package/site-theme/partials/draft-notice.hbs +5 -0
- package/site-theme/partials/exturl.hbs +2 -0
- package/{hugo-theme/layouts/partials/footer.html → site-theme/partials/footer.hbs} +10 -7
- package/site-theme/partials/header.hbs +44 -0
- package/site-theme/partials/hero-banner.hbs +11 -0
- package/site-theme/partials/infobox-entry.hbs +2 -0
- package/site-theme/partials/infobox-section.hbs +31 -0
- package/site-theme/partials/infobox-value.hbs +2 -0
- package/site-theme/partials/infobox.hbs +18 -0
- package/site-theme/partials/list-members.hbs +9 -0
- package/site-theme/partials/nav-links.hbs +5 -0
- package/site-theme/partials/page-body.hbs +48 -0
- package/site-theme/partials/page-list.hbs +14 -0
- package/site-theme/partials/related.hbs +24 -0
- package/site-theme/partials/search-meta.hbs +6 -0
- package/site-theme/partials/search-names.hbs +2 -0
- package/site-theme/partials/search.hbs +52 -0
- package/site-theme/partials/tags.hbs +4 -0
- package/site-theme/partials/toc.hbs +7 -0
- package/{hugo-theme → site-theme}/static/css/style.css +14 -0
- package/stage.mjs +1 -2
- package/types/config.d.mts +8 -4
- package/types/content-config.d.mts +15 -15
- package/types/engine/asset-shipping.d.mts +5 -2
- package/types/engine/base-compiler.d.mts +20 -2
- package/types/engine/content-address.d.mts +1 -1
- package/types/engine/content-alerts.d.mts +8 -2
- package/types/engine/content-blocks.d.mts +11 -4
- package/types/engine/content-expand.d.mts +288 -0
- package/types/engine/content-figures.d.mts +11 -3
- package/types/engine/content-glyphs.d.mts +85 -0
- package/types/engine/content-images.d.mts +6 -7
- package/types/engine/content-links.d.mts +1 -1
- package/types/engine/content-render.d.mts +199 -0
- package/types/engine/content-scripts.d.mts +62 -0
- package/types/engine/content-spans.d.mts +1 -1
- package/types/engine/content-styles.d.mts +33 -0
- package/types/engine/content-symbols.d.mts +35 -0
- package/types/engine/core-report.d.mts +45 -0
- package/types/engine/core-vocabulary.d.mts +53 -0
- package/types/engine/dictionary-html.d.mts +8 -0
- package/types/engine/field-reference.d.mts +1 -1
- package/types/engine/heading-attributes.d.mts +20 -0
- package/types/engine/helpers.d.mts +3 -10
- package/types/engine/homepage.d.mts +11 -24
- package/types/engine/html-minify.d.mts +9 -0
- package/types/engine/index.d.mts +2 -1
- package/types/engine/language-terms.d.mts +24 -2
- package/types/engine/logographic.d.mts +45 -0
- package/types/engine/map-lexicon.d.mts +48 -8
- package/types/engine/map-places.d.mts +8 -0
- package/types/engine/markdown-expressions.d.mts +0 -2
- package/types/engine/metre-declaration.d.mts +39 -0
- package/types/engine/pdf-render.d.mts +6 -2
- package/types/engine/post-fields.d.mts +44 -0
- package/types/engine/preview-index.d.mts +72 -0
- package/types/engine/preview-source.d.mts +51 -0
- package/types/engine/script-emphasis-terms.d.mts +21 -0
- package/types/engine/script-emphasis.d.mts +84 -0
- package/types/engine/script-font-delivery.d.mts +4 -4
- package/types/engine/site-build.d.mts +71 -113
- package/types/engine/site-config.d.mts +14 -134
- package/types/engine/site-files.d.mts +73 -0
- package/types/engine/site-index.d.mts +11 -3
- package/types/engine/site-preview.d.mts +15 -19
- package/types/engine/site-reach.d.mts +76 -0
- package/types/engine/site-render.d.mts +173 -0
- package/types/engine/site-root.d.mts +14 -4
- package/types/engine/site-search.d.mts +54 -0
- package/types/engine/site-serve.d.mts +44 -0
- package/types/engine/site-theme-banner.d.mts +51 -0
- package/types/engine/site-theme-urls.d.mts +60 -0
- package/types/engine/site-theme.d.mts +127 -0
- package/types/engine/text-maps.d.mts +17 -3
- package/types/engine/typographer.d.mts +11 -0
- package/types/engine/verse-metre.d.mts +131 -0
- package/types/engine/wikilink-syntax.d.mts +30 -48
- package/types/engine/wikilinks.d.mts +330 -14
- package/types/engine/word-forms.d.mts +3 -2
- package/types/manifest.d.mts +3 -4
- package/types/stage.d.mts +1 -2
- package/types/vendor/markdownlint.d.mts +8 -0
- package/vendor/markdownlint.mjs +20388 -0
- package/engine/web-wikilinks.mjs +0 -594
- package/hugo-theme/layouts/404.html +0 -85
- package/hugo-theme/layouts/_default/baseof.html +0 -67
- package/hugo-theme/layouts/_default/list.html +0 -139
- package/hugo-theme/layouts/_default/single.html +0 -4
- package/hugo-theme/layouts/blog/list.html +0 -54
- package/hugo-theme/layouts/blog-post/single.html +0 -36
- package/hugo-theme/layouts/index.html +0 -75
- package/hugo-theme/layouts/partials/banner-url.html +0 -141
- package/hugo-theme/layouts/partials/cdn-url.html +0 -36
- package/hugo-theme/layouts/partials/dictionary-lists.html +0 -58
- package/hugo-theme/layouts/partials/draft-notice.html +0 -41
- package/hugo-theme/layouts/partials/draft-state.html +0 -26
- package/hugo-theme/layouts/partials/header.html +0 -35
- package/hugo-theme/layouts/partials/hero-banner.html +0 -85
- package/hugo-theme/layouts/partials/infobox/entry.html +0 -18
- package/hugo-theme/layouts/partials/infobox/items.html +0 -26
- package/hugo-theme/layouts/partials/infobox/section.html +0 -56
- package/hugo-theme/layouts/partials/infobox/value.html +0 -43
- package/hugo-theme/layouts/partials/infobox.html +0 -57
- package/hugo-theme/layouts/partials/page-body.html +0 -152
- package/hugo-theme/layouts/partials/related.html +0 -138
- package/hugo-theme/layouts/partials/search.html +0 -84
- package/hugo-theme/layouts/partials/site-url.html +0 -32
- package/hugo-theme/layouts/partials/tags.html +0 -30
- package/hugo-theme/layouts/partials/toc.html +0 -28
- package/hugo-theme/layouts/partials/warn-missing-banner.html +0 -3
- package/hugo-theme/layouts/shortcodes/cartouche.html +0 -64
- package/hugo-theme/layouts/shortcodes/exturl.html +0 -12
- package/hugo-theme/layouts/shortcodes/glyph.html +0 -43
- package/hugo-theme/layouts/shortcodes/pagelist.html +0 -63
- package/hugo-theme/theme.toml +0 -11
- package/types/engine/web-wikilinks.d.mts +0 -107
- /package/{hugo-theme → site-theme}/data/banner-kinds.yaml +0 -0
- /package/{hugo-theme → site-theme}/static/css/sohl-icons.css +0 -0
- /package/{hugo-theme → site-theme}/static/fonts/game-icons-kb.woff2 +0 -0
- /package/{hugo-theme → site-theme}/static/img/banners/takheperu-hieroglyphs.svg +0 -0
- /package/{hugo-theme → site-theme}/static/img/cartouches/takheperu.svg +0 -0
- /package/{hugo-theme → site-theme}/static/js/inline-spoilers.js +0 -0
package/bin/content-commands.mjs
CHANGED
|
@@ -47,7 +47,7 @@ import log from "loglevel";
|
|
|
47
47
|
import prefix from "loglevel-plugin-prefix";
|
|
48
48
|
import { readStdin } from "../engine/read-stdin.mjs";
|
|
49
49
|
import { compilePacks, cleanPacks, unpackPacks } from "../engine/compendiums.mjs";
|
|
50
|
-
import { compilesFoundryDocuments, publishesContentPages } from "../content-config.mjs";
|
|
50
|
+
import { compilesFoundryDocuments, publishesContentPages, siteBase } from "../content-config.mjs";
|
|
51
51
|
import { loadPackConfig, packConfigPath } from "../engine/pack-config.mjs";
|
|
52
52
|
import { buildPdf, listBookAssets } from "../engine/pdf-build.mjs";
|
|
53
53
|
import { summaryLines } from "../engine/pdf-coverage.mjs";
|
|
@@ -65,19 +65,7 @@ import {
|
|
|
65
65
|
unaddressableForeignPackages,
|
|
66
66
|
formatUnaddressableFinding,
|
|
67
67
|
} from "../engine/metadata-index.mjs";
|
|
68
|
-
import {
|
|
69
|
-
fetchNavigation,
|
|
70
|
-
generateHugoConfig,
|
|
71
|
-
HUGO_SOURCE,
|
|
72
|
-
writeHugoConfig,
|
|
73
|
-
} from "../engine/site-config.mjs";
|
|
74
|
-
import {
|
|
75
|
-
checkScriptFonts,
|
|
76
|
-
copyScriptFonts,
|
|
77
|
-
scriptFontFiles,
|
|
78
|
-
SITE_FONTS_DIR,
|
|
79
|
-
siteFontsDestination,
|
|
80
|
-
} from "../engine/script-font-delivery.mjs";
|
|
68
|
+
import { DEPLOY_ROOT, fetchNavigation } from "../engine/site-config.mjs";
|
|
81
69
|
import { renderItemFieldReference, renderItemFieldsPage } from "../engine/field-reference.mjs";
|
|
82
70
|
import { checkDocLinks, checkDocIndex } from "../engine/docs-checks.mjs";
|
|
83
71
|
import { checkArtSlotSizes } from "../engine/art-fields.mjs";
|
|
@@ -118,6 +106,8 @@ import { schemaSubtypeOf } from "../engine/subtype-registry.mjs";
|
|
|
118
106
|
import { NOTE_VOCABULARY } from "../engine/note-vocabulary.mjs";
|
|
119
107
|
import { markupFindings } from "../engine/markup-validation.mjs";
|
|
120
108
|
import { runContext } from "../engine/content-scripts.mjs";
|
|
109
|
+
import { coreReport, coreReportText } from "../engine/core-report.mjs";
|
|
110
|
+
import { checkScriptNoteFonts } from "../engine/script-emphasis.mjs";
|
|
121
111
|
import {
|
|
122
112
|
checkLexiconNatives,
|
|
123
113
|
checkMapFonts,
|
|
@@ -137,8 +127,12 @@ import {
|
|
|
137
127
|
import {
|
|
138
128
|
buildSite,
|
|
139
129
|
gatesFailed,
|
|
130
|
+
siteBuildFailed,
|
|
140
131
|
formatUnaddressableFinding as formatUnaddressable,
|
|
141
132
|
} from "../engine/site-build.mjs";
|
|
133
|
+
import { buildPackageSite, siteDirectory } from "../engine/site-render.mjs";
|
|
134
|
+
import { serveSite } from "../engine/site-serve.mjs";
|
|
135
|
+
import { writeSiteRoot } from "../engine/site-root.mjs";
|
|
142
136
|
import { auditLinks, buildLinkIndex, walkReachability } from "../engine/content-links.mjs";
|
|
143
137
|
import { prepareLinkSqlTables, prepareTreeSqlTables } from "../engine/sql-tables.mjs";
|
|
144
138
|
import { createContentSession, CONTENT_TARGETS } from "../engine/content-session.mjs";
|
|
@@ -325,6 +319,7 @@ export function registerContentCommands(cli) {
|
|
|
325
319
|
.command(withIndexPreflight(reachabilityCommand()))
|
|
326
320
|
.command(transliterateCommand())
|
|
327
321
|
.command(lexiconCommand())
|
|
322
|
+
.command(coreCommand())
|
|
328
323
|
.command(addressesCommand())
|
|
329
324
|
.command(withIndexPreflight(npcCommand()));
|
|
330
325
|
}
|
|
@@ -1293,6 +1288,7 @@ function lintCommand() {
|
|
|
1293
1288
|
// Each mapping note's faces, each language's native forms
|
|
1294
1289
|
// and each language's `note`, against the faces and maps.
|
|
1295
1290
|
...index.notes.flatMap((note) => checkMapFonts(note, runs)),
|
|
1291
|
+
...index.notes.flatMap((note) => checkScriptNoteFonts(note, runs)),
|
|
1296
1292
|
...index.notes.flatMap((note) => checkLexiconNatives(note, runs)),
|
|
1297
1293
|
...languageNoteFindings({ ...config, configFile: packConfigPath() }, records),
|
|
1298
1294
|
...index.notes.flatMap(firstUseChecker),
|
|
@@ -1926,60 +1922,123 @@ function pdfCommand() {
|
|
|
1926
1922
|
}
|
|
1927
1923
|
|
|
1928
1924
|
/**
|
|
1929
|
-
*
|
|
1930
|
-
*
|
|
1931
|
-
*
|
|
1932
|
-
* A package that has not installed `@heroiclands/fonts`, or sets no text in
|
|
1933
|
-
* one of its faces, gets no copy; a package missing a file its fonts depend on
|
|
1934
|
-
* gets a located error and a non-zero exit.
|
|
1925
|
+
* Report what a site build found, in the order {@link siteCommand} sets out:
|
|
1926
|
+
* the gates first, stopping at the first that fired, then each note's findings,
|
|
1927
|
+
* then what drawing the maps found.
|
|
1935
1928
|
*
|
|
1936
|
-
* @param {object}
|
|
1937
|
-
* @returns {
|
|
1929
|
+
* @param {object} result - From `buildSite`.
|
|
1930
|
+
* @returns {boolean} Whether the build may be written: no gate fired and no
|
|
1931
|
+
* note is in error.
|
|
1938
1932
|
*/
|
|
1939
|
-
function
|
|
1940
|
-
const
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1933
|
+
function reportSiteBuild(result) {
|
|
1934
|
+
const { gates } = result;
|
|
1935
|
+
|
|
1936
|
+
// First, because it is decided before the tree is walked and
|
|
1937
|
+
// before the output is cleared: a package with no front page,
|
|
1938
|
+
// or two competing for it, has nothing to say about its pages
|
|
1939
|
+
// yet.
|
|
1940
|
+
for (const f of gates.homepages) emitDiagnostic(f);
|
|
1941
|
+
for (const f of gates.frontmatterLinks) {
|
|
1942
|
+
emitDiagnostic({
|
|
1943
|
+
file: f.file,
|
|
1944
|
+
severity: "error",
|
|
1945
|
+
message:
|
|
1946
|
+
`wikilink ${f.link} authored in frontmatter at ` +
|
|
1947
|
+
`${f.path} — frontmatter is data, is copied to the ` +
|
|
1948
|
+
`page verbatim, and reaches the reader as brackets`,
|
|
1949
|
+
});
|
|
1949
1950
|
}
|
|
1950
|
-
const
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1951
|
+
for (const f of gates.addressErrors) {
|
|
1952
|
+
emitDiagnostic({
|
|
1953
|
+
file: f.file,
|
|
1954
|
+
severity: "error",
|
|
1955
|
+
message: `cannot derive a URL: ${f.reason}`,
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1958
|
+
reportSiteFindings(gates.sections ?? []);
|
|
1959
|
+
for (const s of gates.staleManifests) {
|
|
1960
|
+
emitDiagnostic({
|
|
1961
|
+
file: cachedIndexPath(loadPackConfig(), s.package),
|
|
1962
|
+
severity: "error",
|
|
1963
|
+
message: `unusable content index: ${s.reason}`,
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
for (const f of gates.unaddressable) {
|
|
1967
|
+
console.error(formatUnaddressable(f, loadPackConfig()));
|
|
1968
|
+
}
|
|
1969
|
+
if (gatesFailed(gates)) {
|
|
1970
|
+
return false;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
// Every note's findings are reported together: stopping at the first
|
|
1974
|
+
// would make a single bad table hide every other problem in the tree.
|
|
1975
|
+
// Each is `file:line:column: error: message`, path first — the shape
|
|
1976
|
+
// the pack build reports the same findings in.
|
|
1977
|
+
for (const e of result.tableErrors) {
|
|
1978
|
+
emitDiagnostic({
|
|
1979
|
+
file: e.source,
|
|
1980
|
+
line: typeof e.line === "number" ? e.line + 1 : undefined,
|
|
1981
|
+
column: e.column,
|
|
1982
|
+
severity: "error",
|
|
1983
|
+
message: e.reason,
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
for (const e of result.expressionErrors) {
|
|
1987
|
+
emitDiagnostic(e);
|
|
1988
|
+
}
|
|
1989
|
+
for (const e of result.secretErrors) {
|
|
1990
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1991
|
+
}
|
|
1992
|
+
for (const e of result.captionErrors) {
|
|
1993
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1994
|
+
}
|
|
1995
|
+
for (const e of result.headingErrors) {
|
|
1996
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1997
|
+
}
|
|
1998
|
+
for (const e of result.footnoteErrors) {
|
|
1999
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
2000
|
+
}
|
|
2001
|
+
for (const e of result.embedErrors) {
|
|
2002
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
2003
|
+
}
|
|
2004
|
+
// Worded by the shared table the pack build words the same finding
|
|
2005
|
+
// with, and located by searching the note for the link.
|
|
2006
|
+
for (const e of result.wikiErrors) {
|
|
2007
|
+
emitDiagnostic({
|
|
2008
|
+
file: e.file,
|
|
2009
|
+
...positionOfLiteral(readRawNote(e.file), e.link, e.occurrence),
|
|
2010
|
+
severity: "error",
|
|
2011
|
+
// An embed's directive speaks the image vocabulary
|
|
2012
|
+
// rather than the link one, and carries its own
|
|
2013
|
+
// sentence; everything else is worded by the shared
|
|
2014
|
+
// table.
|
|
2015
|
+
message: e.message ?? linkFindingMessage(e),
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
2018
|
+
// An image whose pathname the site cannot resolve, located the
|
|
2019
|
+
// way a wikilink finding is: by searching the note for the
|
|
2020
|
+
// literal the resolver was handed.
|
|
2021
|
+
for (const e of result.imageErrors) {
|
|
2022
|
+
emitDiagnostic({
|
|
2023
|
+
file: e.file,
|
|
2024
|
+
...positionOfLiteral(readRawNote(e.file), e.src, e.occurrence),
|
|
2025
|
+
severity: "error",
|
|
2026
|
+
message: e.message,
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
if (siteBuildFailed(result)) return false;
|
|
2030
|
+
|
|
2031
|
+
// Relation warnings do not fail a site build.
|
|
2032
|
+
for (const f of result.mapFindings) emitDiagnostic(f);
|
|
2033
|
+
return true;
|
|
1958
2034
|
}
|
|
1959
2035
|
|
|
1960
2036
|
/**
|
|
1961
|
-
* `package-build site` —
|
|
2037
|
+
* `package-build site` — the website commands.
|
|
1962
2038
|
*
|
|
1963
2039
|
* The sibling of `package compile`: the same tree, rendered as pages instead of
|
|
1964
|
-
* compiled into packs.
|
|
1965
|
-
*
|
|
1966
|
-
* wikilink resolution, code-fence protection and the foreign-manifest merge —
|
|
1967
|
-
* happens here, from configuration. So does the Hugo configuration: the whole
|
|
1968
|
-
* source tree Hugo reads lands under `build/hugo/`, and the consumer's script
|
|
1969
|
-
* runs Hugo over it. With `site.maps` on, every place
|
|
1970
|
-
* page with a border or a route carries the map from that place.
|
|
1971
|
-
*
|
|
1972
|
-
* **The Hugo configuration is generated before anything is written.** Its
|
|
1973
|
-
* sources — `package.json`'s `homepage`, the cached navigation, the installed
|
|
1974
|
-
* theme — are each a way the build can fail, and failing before the output
|
|
1975
|
-
* tree is cleared leaves the last good site in place to be looked at. Nothing
|
|
1976
|
-
* the walk reads changes it: a site renders its homepage and its pages, and
|
|
1977
|
-
* the kinds Hugo disables are the same on every site.
|
|
1978
|
-
*
|
|
1979
|
-
* **Each gate is reported and the run stops at the first that fires.** They are
|
|
1980
|
-
* ordered so the report names the cause rather than its symptoms: an unusable
|
|
1981
|
-
* manifest, reported after the links that failed because of it, reads as a pile
|
|
1982
|
-
* of broken notes.
|
|
2040
|
+
* compiled into packs. `site build` renders the tree and `site serve` serves it
|
|
2041
|
+
* with live rebuilds; a bare `site` names them.
|
|
1983
2042
|
*
|
|
1984
2043
|
* @returns {object} The yargs command module.
|
|
1985
2044
|
*/
|
|
@@ -1987,163 +2046,185 @@ function stageSiteFonts(config) {
|
|
|
1987
2046
|
function siteCommand() {
|
|
1988
2047
|
return {
|
|
1989
2048
|
command: "site",
|
|
1990
|
-
describe: "
|
|
1991
|
-
builder: () =>
|
|
1992
|
-
|
|
2049
|
+
describe: "Render the content tree as a website",
|
|
2050
|
+
builder: (yargs) =>
|
|
2051
|
+
yargs
|
|
2052
|
+
.command(
|
|
2053
|
+
withIndexPreflight(
|
|
2054
|
+
withBodyPreflight(siteBuildCommand()),
|
|
2055
|
+
publishesContentPages,
|
|
2056
|
+
),
|
|
2057
|
+
)
|
|
2058
|
+
.command(
|
|
2059
|
+
withIndexPreflight(
|
|
2060
|
+
withBodyPreflight(siteServeCommand()),
|
|
2061
|
+
publishesContentPages,
|
|
2062
|
+
),
|
|
2063
|
+
)
|
|
2064
|
+
.demandCommand(1, "Name a site command: build or serve."),
|
|
2065
|
+
};
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
/**
|
|
2069
|
+
* Report what the layouts, or the build's section gate, found about a site.
|
|
2070
|
+
*
|
|
2071
|
+
* A finding about a site parameter is located at the configuration's
|
|
2072
|
+
* `site.<param>` entry; one about a page, at the note the page was written
|
|
2073
|
+
* from.
|
|
2074
|
+
*
|
|
2075
|
+
* @param {readonly object[]} findings - The findings.
|
|
2076
|
+
*/
|
|
2077
|
+
function reportSiteFindings(findings) {
|
|
2078
|
+
const configFile = packConfigPath();
|
|
2079
|
+
const configText = fs.existsSync(configFile) ? fs.readFileSync(configFile, "utf8") : "";
|
|
2080
|
+
for (const finding of findings) {
|
|
2081
|
+
if (finding.param) {
|
|
2082
|
+
emitDiagnostic({
|
|
2083
|
+
file: path.relative(process.cwd(), configFile),
|
|
2084
|
+
...positionOfYamlPath(configText, ["site", ...finding.param]),
|
|
2085
|
+
severity: finding.severity,
|
|
2086
|
+
message: finding.message,
|
|
2087
|
+
});
|
|
2088
|
+
} else {
|
|
2089
|
+
emitDiagnostic({
|
|
2090
|
+
file: finding.file ?? finding.page,
|
|
2091
|
+
severity: finding.severity,
|
|
2092
|
+
message: finding.message,
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
/**
|
|
2099
|
+
* `package-build site build` — render the content tree as a website.
|
|
2100
|
+
*
|
|
2101
|
+
* Every page is drawn by the site theme from the shared renderer's HTML and
|
|
2102
|
+
* written under `<out>/<package>/`, with `404.html`, `sitemap.xml`, the
|
|
2103
|
+
* theme's stylesheets, scripts and fonts and the package's script fonts.
|
|
2104
|
+
* `_headers` is then written beside it and the search index built inside it,
|
|
2105
|
+
* as `package-build site-root` does. The site's settings and cached menu are
|
|
2106
|
+
* read before the tree, so a site that cannot be described fails with the
|
|
2107
|
+
* last good one still in place.
|
|
2108
|
+
*
|
|
2109
|
+
* @returns {object} The yargs command module.
|
|
2110
|
+
*/
|
|
2111
|
+
function siteBuildCommand() {
|
|
2112
|
+
return {
|
|
2113
|
+
command: "build",
|
|
2114
|
+
describe: "Render the content tree as a website and index it for search",
|
|
2115
|
+
builder: (yargs) =>
|
|
2116
|
+
yargs.option("out", {
|
|
2117
|
+
type: "string",
|
|
2118
|
+
describe: `The directory that is deployed (default: ${DEPLOY_ROOT})`,
|
|
2119
|
+
}),
|
|
2120
|
+
handler: async (argv) => {
|
|
1993
2121
|
try {
|
|
1994
|
-
const config = loadPackConfig();
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
//
|
|
1999
|
-
//
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
config,
|
|
2003
|
-
sqlTables: await prepareTreeSqlTables(config.paths.content, {
|
|
2004
|
-
skipDirectories: config.skipDirectories,
|
|
2005
|
-
config,
|
|
2006
|
-
audience: "public",
|
|
2007
|
-
}),
|
|
2008
|
-
});
|
|
2009
|
-
const { gates } = result;
|
|
2010
|
-
|
|
2011
|
-
// First, because it is decided before the tree is walked and
|
|
2012
|
-
// before the output is cleared: a package with no front page,
|
|
2013
|
-
// or two competing for it, has nothing to say about its pages
|
|
2014
|
-
// yet.
|
|
2015
|
-
for (const f of gates.homepages) emitDiagnostic(f);
|
|
2016
|
-
for (const f of gates.frontmatterLinks) {
|
|
2017
|
-
emitDiagnostic({
|
|
2018
|
-
file: f.file,
|
|
2019
|
-
severity: "error",
|
|
2020
|
-
message:
|
|
2021
|
-
`wikilink ${f.link} authored in frontmatter at ` +
|
|
2022
|
-
`${f.path} — frontmatter is data, is copied to the ` +
|
|
2023
|
-
`page verbatim, and reaches the reader as brackets`,
|
|
2024
|
-
});
|
|
2025
|
-
}
|
|
2026
|
-
for (const f of gates.addressErrors) {
|
|
2027
|
-
emitDiagnostic({
|
|
2028
|
-
file: f.file,
|
|
2029
|
-
severity: "error",
|
|
2030
|
-
message: `cannot derive a URL: ${f.reason}`,
|
|
2031
|
-
});
|
|
2032
|
-
}
|
|
2033
|
-
for (const s of gates.staleManifests) {
|
|
2034
|
-
emitDiagnostic({
|
|
2035
|
-
file: cachedIndexPath(loadPackConfig(), s.package),
|
|
2036
|
-
severity: "error",
|
|
2037
|
-
message: `unusable content index: ${s.reason}`,
|
|
2038
|
-
});
|
|
2039
|
-
}
|
|
2040
|
-
for (const f of gates.unaddressable) {
|
|
2041
|
-
console.error(formatUnaddressable(f, loadPackConfig()));
|
|
2042
|
-
}
|
|
2043
|
-
if (gatesFailed(gates)) {
|
|
2122
|
+
const config = argv[CONTENT_CONFIG] ?? loadPackConfig();
|
|
2123
|
+
const root = path.resolve(config.rootDir, argv.out ?? DEPLOY_ROOT);
|
|
2124
|
+
const out = siteDirectory(config, root);
|
|
2125
|
+
const result = await buildPackageSite({ config, out });
|
|
2126
|
+
// A note in error is written as its page shows it, and the
|
|
2127
|
+
// build fails without indexing a site that is not to be
|
|
2128
|
+
// deployed.
|
|
2129
|
+
if (!reportSiteBuild(result.built) || !result.written) {
|
|
2044
2130
|
process.exitCode = 1;
|
|
2045
2131
|
return;
|
|
2046
2132
|
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
// before anything is emitted would make a single bad table
|
|
2051
|
-
// hide every other problem in the tree.
|
|
2052
|
-
// `file:line:column: error: message`, path first — the same
|
|
2053
|
-
// shape the pack build and the wikilink findings below use. It
|
|
2054
|
-
// was prose with a timestamp where a parser reads the path,
|
|
2055
|
-
// which made one authored table produce a machine-readable
|
|
2056
|
-
// diagnostic from one build and something ungreppable from the
|
|
2057
|
-
// other.
|
|
2058
|
-
for (const e of result.tableErrors) {
|
|
2059
|
-
emitDiagnostic({
|
|
2060
|
-
file: e.source,
|
|
2061
|
-
line: typeof e.line === "number" ? e.line + 1 : undefined,
|
|
2062
|
-
column: e.column,
|
|
2063
|
-
severity: "error",
|
|
2064
|
-
message: e.reason,
|
|
2065
|
-
});
|
|
2066
|
-
}
|
|
2067
|
-
for (const e of result.expressionErrors) {
|
|
2068
|
-
emitDiagnostic(e);
|
|
2069
|
-
}
|
|
2070
|
-
for (const e of result.secretErrors) {
|
|
2071
|
-
emitDiagnostic({ ...e, severity: "error" });
|
|
2072
|
-
}
|
|
2073
|
-
for (const e of result.captionErrors) {
|
|
2074
|
-
emitDiagnostic({ ...e, severity: "error" });
|
|
2075
|
-
}
|
|
2076
|
-
for (const e of result.headingErrors) {
|
|
2077
|
-
emitDiagnostic({ ...e, severity: "error" });
|
|
2078
|
-
}
|
|
2079
|
-
for (const e of result.footnoteErrors) {
|
|
2080
|
-
emitDiagnostic({ ...e, severity: "error" });
|
|
2081
|
-
}
|
|
2082
|
-
for (const e of result.embedErrors) {
|
|
2083
|
-
emitDiagnostic({ ...e, severity: "error" });
|
|
2084
|
-
}
|
|
2085
|
-
// Reported the way the pack build reports the very same
|
|
2086
|
-
// finding: `file:line:column: error: message`, path first, and
|
|
2087
|
-
// the message from the shared table, not a
|
|
2088
|
-
// `log.error` whose timestamp prefix sat where a parser reads
|
|
2089
|
-
// the path from, and whose text named a `reason` code rather
|
|
2090
|
-
// than saying what to do — so one authored link produced a
|
|
2091
|
-
// machine-readable diagnostic from one build and prose from
|
|
2092
|
-
// another.
|
|
2093
|
-
for (const e of result.wikiErrors) {
|
|
2094
|
-
emitDiagnostic({
|
|
2095
|
-
file: e.file,
|
|
2096
|
-
...positionOfLiteral(readRawNote(e.file), e.link, e.occurrence),
|
|
2097
|
-
severity: "error",
|
|
2098
|
-
// An embed's directive speaks the image vocabulary
|
|
2099
|
-
// rather than the link one, and carries its own
|
|
2100
|
-
// sentence; everything else is worded by the shared
|
|
2101
|
-
// table.
|
|
2102
|
-
message: e.message ?? linkFindingMessage(e),
|
|
2103
|
-
});
|
|
2104
|
-
}
|
|
2105
|
-
// An image whose pathname the site cannot resolve, located the
|
|
2106
|
-
// way a wikilink finding is: by searching the note for the
|
|
2107
|
-
// literal the resolver was handed. The page is written either
|
|
2108
|
-
// way — a missing picture is visible, and stopping before the
|
|
2109
|
-
// write would hide every other finding in the tree behind one
|
|
2110
|
-
// address.
|
|
2111
|
-
for (const e of result.imageErrors) {
|
|
2112
|
-
emitDiagnostic({
|
|
2113
|
-
file: e.file,
|
|
2114
|
-
...positionOfLiteral(readRawNote(e.file), e.src, e.occurrence),
|
|
2115
|
-
severity: "error",
|
|
2116
|
-
message: e.message,
|
|
2117
|
-
});
|
|
2118
|
-
}
|
|
2119
|
-
if (
|
|
2120
|
-
result.tableErrors.length ||
|
|
2121
|
-
result.expressionErrors.length ||
|
|
2122
|
-
result.secretErrors.length ||
|
|
2123
|
-
result.captionErrors.length ||
|
|
2124
|
-
result.headingErrors.length ||
|
|
2125
|
-
result.footnoteErrors.length ||
|
|
2126
|
-
result.wikiErrors.length ||
|
|
2127
|
-
result.imageErrors.length ||
|
|
2128
|
-
result.embedErrors.length
|
|
2129
|
-
) {
|
|
2133
|
+
reportSiteFindings(result.written.findings);
|
|
2134
|
+
for (const finding of result.fonts.findings) emitDiagnostic(finding);
|
|
2135
|
+
if (result.fonts.findings.length) {
|
|
2130
2136
|
process.exitCode = 1;
|
|
2131
2137
|
return;
|
|
2132
2138
|
}
|
|
2133
|
-
|
|
2134
|
-
// Relation warnings do not fail a site build.
|
|
2135
|
-
for (const f of result.mapFindings) emitDiagnostic(f);
|
|
2136
|
-
|
|
2137
|
-
const s = result.stats;
|
|
2138
2139
|
log.info(
|
|
2139
|
-
`wrote ${
|
|
2140
|
-
`${
|
|
2141
|
-
`${s.maps ?? 0} with a map, to ` +
|
|
2142
|
-
`${path.relative(process.cwd(), s.out)}`,
|
|
2140
|
+
`wrote ${result.written.pages.length} page(s) to ` +
|
|
2141
|
+
`${path.relative(process.cwd(), out)}`,
|
|
2143
2142
|
);
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2143
|
+
if (result.fonts.count)
|
|
2144
|
+
log.info(
|
|
2145
|
+
`wrote ${result.fonts.count} script font file(s) to ` +
|
|
2146
|
+
`${path.relative(process.cwd(), result.fonts.dest)}`,
|
|
2147
|
+
);
|
|
2148
|
+
const { search } = await writeSiteRoot({
|
|
2149
|
+
pkg: config.contentPackage,
|
|
2150
|
+
base: siteBase(config),
|
|
2151
|
+
out: root,
|
|
2152
|
+
search: config.site.search,
|
|
2153
|
+
});
|
|
2154
|
+
if (search) {
|
|
2155
|
+
log.info(
|
|
2156
|
+
`indexed ${search.pages} page(s) for search into ` +
|
|
2157
|
+
`${path.relative(process.cwd(), search.dir)}`,
|
|
2158
|
+
);
|
|
2159
|
+
}
|
|
2160
|
+
} catch (err) {
|
|
2161
|
+
reportFailure(err);
|
|
2162
|
+
process.exitCode = 1;
|
|
2163
|
+
}
|
|
2164
|
+
},
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
/**
|
|
2169
|
+
* `package-build site serve` — serve the website, and keep it current.
|
|
2170
|
+
*
|
|
2171
|
+
* The site is built as `site build` builds it, served from the deployed root,
|
|
2172
|
+
* and written again as the content tree or the theme changes; every open page
|
|
2173
|
+
* reloads when it is. Runs until interrupted.
|
|
2174
|
+
*
|
|
2175
|
+
* @returns {object} The yargs command module.
|
|
2176
|
+
*/
|
|
2177
|
+
function siteServeCommand() {
|
|
2178
|
+
return {
|
|
2179
|
+
command: "serve",
|
|
2180
|
+
describe: "Serve the website, and rebuild and reload it as its sources change",
|
|
2181
|
+
builder: (yargs) =>
|
|
2182
|
+
yargs
|
|
2183
|
+
.option("port", {
|
|
2184
|
+
type: "number",
|
|
2185
|
+
default: 1313,
|
|
2186
|
+
describe: "The port to listen on",
|
|
2187
|
+
})
|
|
2188
|
+
.option("host", {
|
|
2189
|
+
type: "string",
|
|
2190
|
+
default: "127.0.0.1",
|
|
2191
|
+
describe: "The address to listen on",
|
|
2192
|
+
})
|
|
2193
|
+
.option("out", {
|
|
2194
|
+
type: "string",
|
|
2195
|
+
describe: `The directory the site is written to (default: ${DEPLOY_ROOT})`,
|
|
2196
|
+
}),
|
|
2197
|
+
handler: async (argv) => {
|
|
2198
|
+
try {
|
|
2199
|
+
const config = argv[CONTENT_CONFIG] ?? loadPackConfig();
|
|
2200
|
+
const root = path.resolve(config.rootDir, argv.out ?? DEPLOY_ROOT);
|
|
2201
|
+
const served = await serveSite({
|
|
2202
|
+
config,
|
|
2203
|
+
root,
|
|
2204
|
+
out: siteDirectory(config, root),
|
|
2205
|
+
host: argv.host,
|
|
2206
|
+
port: argv.port,
|
|
2207
|
+
report: (event) => {
|
|
2208
|
+
if (event.kind === "error") reportFailure(event.error);
|
|
2209
|
+
else if (event.kind === "failed") {
|
|
2210
|
+
if (event.built) reportSiteBuild(event.built);
|
|
2211
|
+
for (const finding of event.findings ?? []) emitDiagnostic(finding);
|
|
2212
|
+
} else {
|
|
2213
|
+
reportSiteFindings(event.findings ?? []);
|
|
2214
|
+
log.info(
|
|
2215
|
+
event.kind === "built" ? "built the site"
|
|
2216
|
+
: event.kind === "theme" ? "drew every page again"
|
|
2217
|
+
: `wrote ${event.files.map((f) => path.relative(process.cwd(), f)).join(", ")}`,
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
},
|
|
2221
|
+
});
|
|
2222
|
+
log.info(`serving ${served.url} — interrupt to stop`);
|
|
2223
|
+
await new Promise((resolve) => {
|
|
2224
|
+
process.once("SIGINT", resolve);
|
|
2225
|
+
process.once("SIGTERM", resolve);
|
|
2226
|
+
});
|
|
2227
|
+
await served.close();
|
|
2147
2228
|
} catch (err) {
|
|
2148
2229
|
reportFailure(err);
|
|
2149
2230
|
process.exitCode = 1;
|
|
@@ -2440,7 +2521,9 @@ function transliterateCommand() {
|
|
|
2440
2521
|
* `package-build lexicon <language> --map <map>` — every word of a language's
|
|
2441
2522
|
* lexicon with its native form under a map, as the build writes it; with
|
|
2442
2523
|
* `--derived`, the forms its rules derive follow, each naming its word in a
|
|
2443
|
-
* sixth column.
|
|
2524
|
+
* sixth column. Under a logographic map the third column says where a
|
|
2525
|
+
* word's writing comes from, `own` or `parts`, or marks it `none` or
|
|
2526
|
+
* `ambiguous`.
|
|
2444
2527
|
*
|
|
2445
2528
|
* @returns {object} The yargs command module.
|
|
2446
2529
|
*/
|
|
@@ -2499,7 +2582,12 @@ function lexiconCommand() {
|
|
|
2499
2582
|
[
|
|
2500
2583
|
entry.form,
|
|
2501
2584
|
entry.native,
|
|
2502
|
-
entry.
|
|
2585
|
+
entry.source === undefined ?
|
|
2586
|
+
entry.exception ?
|
|
2587
|
+
"exception"
|
|
2588
|
+
: "rows"
|
|
2589
|
+
: entry.ambiguous ? "ambiguous"
|
|
2590
|
+
: entry.source,
|
|
2503
2591
|
entry.class ?? "",
|
|
2504
2592
|
entry.gloss ?? "",
|
|
2505
2593
|
...(argv.derived ? [entry.from ?? ""] : []),
|
|
@@ -2513,6 +2601,64 @@ function lexiconCommand() {
|
|
|
2513
2601
|
};
|
|
2514
2602
|
}
|
|
2515
2603
|
|
|
2604
|
+
/**
|
|
2605
|
+
* `package-build core [--language <name>] [--json]` — the concepts of the core
|
|
2606
|
+
* vocabulary each covering language has no word for, by group.
|
|
2607
|
+
*
|
|
2608
|
+
* @returns {object} The yargs command module.
|
|
2609
|
+
*/
|
|
2610
|
+
// eslint-disable-next-line
|
|
2611
|
+
function coreCommand() {
|
|
2612
|
+
return {
|
|
2613
|
+
command: "core",
|
|
2614
|
+
describe: "List the core concepts each covering language has no word for",
|
|
2615
|
+
builder: (yargs) =>
|
|
2616
|
+
yargs
|
|
2617
|
+
.option("language", {
|
|
2618
|
+
type: "string",
|
|
2619
|
+
describe:
|
|
2620
|
+
"Report this language alone, by its name, shortcode or reference, whether or not it states `data.core`",
|
|
2621
|
+
})
|
|
2622
|
+
.option("json", {
|
|
2623
|
+
type: "boolean",
|
|
2624
|
+
default: false,
|
|
2625
|
+
describe: "Print the report as JSON",
|
|
2626
|
+
}),
|
|
2627
|
+
handler: (argv) => {
|
|
2628
|
+
try {
|
|
2629
|
+
const config = loadPackConfig();
|
|
2630
|
+
const problems = [];
|
|
2631
|
+
const records = indexRecordsFor({
|
|
2632
|
+
contentBase: config.paths.content,
|
|
2633
|
+
config,
|
|
2634
|
+
skipDirectories: config.skipDirectories,
|
|
2635
|
+
problems,
|
|
2636
|
+
});
|
|
2637
|
+
for (const problem of problems) emitDiagnostic(problem);
|
|
2638
|
+
if (problems.length) {
|
|
2639
|
+
process.exitCode = 1;
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2642
|
+
const report = coreReport(records, { language: argv.language });
|
|
2643
|
+
if ("problem" in report) {
|
|
2644
|
+
emitDiagnostic({
|
|
2645
|
+
file: config.paths.content,
|
|
2646
|
+
severity: "error",
|
|
2647
|
+
message: report.problem,
|
|
2648
|
+
});
|
|
2649
|
+
process.exitCode = 1;
|
|
2650
|
+
return;
|
|
2651
|
+
}
|
|
2652
|
+
if (argv.json) console.log(JSON.stringify(report, null, 2));
|
|
2653
|
+
else process.stdout.write(coreReportText(report));
|
|
2654
|
+
} catch (err) {
|
|
2655
|
+
reportFailure(err);
|
|
2656
|
+
process.exitCode = 1;
|
|
2657
|
+
}
|
|
2658
|
+
},
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2516
2662
|
/**
|
|
2517
2663
|
* `package-build reachability <dir> [file]` — check that a corpus reads through.
|
|
2518
2664
|
*
|