@heroiclands/package-build 23.1.0 → 23.2.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 +71 -0
- package/bin/content-commands.mjs +68 -149
- package/bin/package-build.mjs +56 -10
- package/ci/check-banners.mjs +42 -6
- package/ci/confirm-npm-version.mjs +135 -0
- package/ci/content-format-reference.mjs +14 -5
- package/config.mjs +1 -0
- package/container.mjs +185 -4
- package/content-config.mjs +333 -210
- package/deploy.mjs +116 -10
- package/docs/api.md +238 -246
- package/docs/authoring/assets.md +11 -5
- package/docs/authoring/frontmatter.md +1 -1
- package/docs/authoring/links-and-markup.md +87 -0
- package/docs/commands.md +138 -99
- package/docs/configuration.md +277 -125
- package/docs/content-format.md +2 -0
- package/docs/diagnostics.md +48 -13
- package/docs/guides/book.md +341 -21
- package/docs/guides/e2e.md +13 -2
- package/docs/guides/icons.md +14 -4
- package/docs/guides/module-project.md +18 -8
- package/docs/guides/release-and-deploy.md +54 -6
- package/docs/guides/site.md +5 -2
- package/docs/project-setup.md +30 -10
- package/docs/reference/format-details.md +373 -170
- package/docs/reference/note-types.md +128 -109
- package/docs/reference/theme-pages.md +31 -6
- package/e2e.mjs +140 -28
- package/engine/actor-compiler.mjs +22 -31
- package/engine/address-charset.mjs +4 -17
- package/engine/address-fields.mjs +1 -1
- package/engine/address-render.mjs +12 -1
- package/engine/address-values.mjs +6 -0
- package/engine/address.mjs +46 -33
- package/engine/art-fields.mjs +30 -5
- package/engine/art-slots.mjs +10 -1
- package/engine/asset-bindings.mjs +12 -1
- package/engine/base-compiler.mjs +34 -65
- package/engine/being-age.mjs +2 -7
- package/engine/being-measurements.mjs +12 -1
- package/engine/calendar-artifacts.mjs +6 -0
- package/engine/calendar-choice.mjs +12 -1
- package/engine/calendar-format.mjs +12 -1
- package/engine/calendar-human.mjs +12 -1
- package/engine/compile-corpus.mjs +3 -1
- package/engine/content-address.mjs +9 -12
- package/engine/content-alerts.mjs +13 -1
- package/engine/content-blocks.mjs +14 -3
- package/engine/content-embeds.mjs +11 -3
- package/engine/content-figures.mjs +9 -0
- package/engine/content-footnotes.mjs +12 -1
- package/engine/content-format-check.mjs +11 -262
- package/engine/content-format.yaml +5 -2
- package/engine/content-images.mjs +3 -0
- package/engine/content-index.mjs +443 -20
- package/engine/content-links.mjs +29 -35
- package/engine/content-lint.mjs +2 -3
- package/engine/content-poetry.mjs +12 -1
- package/engine/content-slug.mjs +2 -14
- package/engine/content-spans.mjs +13 -1
- package/engine/content-tables.mjs +12 -1
- package/engine/culture-choice.mjs +210 -13
- package/engine/data-keys.mjs +19 -16
- package/engine/date-conversion.mjs +12 -1
- package/engine/declaration-check.mjs +9 -0
- package/engine/derived-fields.mjs +6 -7
- package/engine/diagnostics.mjs +34 -4
- package/engine/docs-checks.mjs +9 -0
- package/engine/document-subtypes.mjs +47 -34
- package/engine/event-views.mjs +139 -14
- package/engine/exported-scene.mjs +92 -28
- package/engine/extension-attributes.mjs +12 -1
- package/engine/field-spec.mjs +11 -102
- package/engine/folder-notes.mjs +0 -64
- package/engine/foreign-catalog.mjs +2 -1
- package/engine/format-generated.mjs +9 -0
- package/engine/foundry-entries.mjs +10 -28
- package/engine/frontmatter-lint.mjs +83 -392
- package/engine/frontmatter.mjs +20 -70
- package/engine/generate.mjs +10 -15
- package/engine/heading-attributes.mjs +12 -1
- package/engine/helpers.mjs +41 -102
- package/engine/holdings.mjs +1 -1
- package/engine/homepage.mjs +3 -10
- package/engine/ids.mjs +1 -167
- package/engine/index-records.mjs +6 -4
- package/engine/index.mjs +0 -3
- package/engine/infobox-render.mjs +15 -3
- package/engine/infobox.mjs +13 -14
- package/engine/item-compiler.mjs +4 -10
- package/engine/item-docs.mjs +3 -5
- package/engine/item-registry.mjs +2 -10
- package/engine/journals.mjs +1 -5
- package/engine/literature-notes.mjs +4 -12
- package/engine/macros.mjs +1 -2
- package/engine/map-graphviz.mjs +12 -1
- package/engine/markdown-expressions.mjs +12 -1
- package/engine/markdownlint-run.mjs +567 -0
- package/engine/metadata-index.mjs +42 -12
- package/engine/note-addresses.mjs +143 -35
- package/engine/note-claims.mjs +14 -28
- package/engine/note-dates.mjs +3 -3
- package/engine/note-frontmatter.mjs +6 -0
- package/engine/note-ids.mjs +8 -14
- package/engine/note-package.mjs +8 -25
- package/engine/note-state.mjs +1 -3
- package/engine/note-vocabulary.mjs +148 -84
- package/engine/number-words.mjs +12 -1
- package/engine/pack-config.mjs +15 -25
- package/engine/pack-router.mjs +10 -16
- package/engine/pathnames.mjs +8 -22
- package/engine/pdf-build.mjs +773 -121
- package/engine/pdf-coverage.mjs +188 -0
- package/engine/pdf-index.mjs +54 -7
- package/engine/pdf-pages.mjs +247 -0
- package/engine/pdf-render.mjs +114 -4
- package/engine/pdf-toc.mjs +29 -32
- package/engine/project-init.mjs +46 -6
- package/engine/prose-config.mjs +1 -1
- package/engine/prose-lint.mjs +52 -88
- package/engine/readability-lint.mjs +9 -0
- package/engine/reckoning-markers.mjs +12 -1
- package/engine/reference-targets.mjs +7 -0
- package/engine/runtime-only-fields.mjs +5 -8
- package/engine/scene-levels.mjs +2 -2
- package/engine/scenes.mjs +1 -1
- package/engine/shortcode-references.mjs +7 -0
- package/engine/site-build.mjs +30 -16
- package/engine/site-index.mjs +10 -16
- package/engine/site-preview.mjs +6 -0
- package/engine/site-root.mjs +8 -1
- package/engine/social-tie-terms.mjs +12 -1
- package/engine/social-ties.mjs +3 -0
- package/engine/sql-tables.mjs +56 -20
- package/engine/standing-terms.mjs +11 -1
- package/engine/standings.mjs +11 -27
- package/engine/system-block.mjs +39 -141
- package/engine/system-vocabulary.mjs +6 -0
- package/engine/walk-files.mjs +69 -0
- package/engine/web-wikilinks.mjs +23 -3
- package/engine/wikilink-syntax.mjs +32 -21
- package/engine/wikilinks.mjs +27 -16
- package/engine/yaml-lint.mjs +7 -4
- package/githooks/attribution.mjs +8 -0
- package/githooks/commit-message.mjs +9 -0
- package/hm3/actors.mjs +9 -48
- package/hm3/default-item-art.mjs +9 -9
- package/hm3/item-fields.mjs +2 -9
- package/hm3/template-priority.mjs +6 -7
- package/hugo-theme/data/banner-kinds.yaml +78 -0
- package/hugo-theme/data/banners.yaml +2 -3
- package/hugo-theme/layouts/404.html +3 -3
- package/hugo-theme/layouts/partials/banner-url.html +31 -7
- package/hugo-theme/layouts/partials/hero-banner.html +13 -14
- package/hugo-theme/layouts/partials/related.html +1 -1
- package/hugo-theme/layouts/partials/warn-missing-banner.html +1 -1
- package/hugo-theme/static/css/style.css +1 -1
- package/manifest.mjs +11 -4
- package/markdownlint-config.mjs +1 -1
- package/package.json +6 -3
- package/release.mjs +83 -18
- package/sohl/actors.mjs +16 -27
- package/sohl/default-item-art.mjs +3 -3
- package/sohl/document-subtypes.mjs +1 -16
- package/sohl/infobox.mjs +2 -3
- package/sohl/item-builders.mjs +5 -8
- package/sohl/item-fields.mjs +5 -35
- package/sohl/items.mjs +0 -4
- package/sohl/kb-passes.mjs +3 -3
- package/types/container.d.mts +116 -5
- package/types/content-config.d.mts +83 -35
- package/types/deploy.d.mts +42 -6
- package/types/e2e.d.mts +35 -3
- package/types/engine/address-charset.d.mts +4 -17
- package/types/engine/address.d.mts +17 -8
- package/types/engine/art-fields.d.mts +7 -4
- package/types/engine/art-slots.d.mts +6 -0
- package/types/engine/base-compiler.d.mts +15 -17
- package/types/engine/content-address.d.mts +9 -12
- package/types/engine/content-embeds.d.mts +4 -2
- package/types/engine/content-format-check.d.mts +0 -64
- package/types/engine/content-index.d.mts +82 -3
- package/types/engine/content-links.d.mts +2 -4
- package/types/engine/culture-choice.d.mts +51 -8
- package/types/engine/data-keys.d.mts +2 -2
- package/types/engine/derived-fields.d.mts +1 -2
- package/types/engine/diagnostics.d.mts +27 -4
- package/types/engine/document-subtypes.d.mts +12 -31
- package/types/engine/event-views.d.mts +14 -2
- package/types/engine/exported-scene.d.mts +3 -2
- package/types/engine/field-spec.d.mts +13 -122
- package/types/engine/folder-notes.d.mts +0 -39
- package/types/engine/foreign-catalog.d.mts +2 -1
- package/types/engine/foundry-entries.d.mts +4 -5
- package/types/engine/frontmatter-lint.d.mts +2 -2
- package/types/engine/frontmatter.d.mts +19 -45
- package/types/engine/generate.d.mts +1 -1
- package/types/engine/helpers.d.mts +25 -42
- package/types/engine/homepage.d.mts +3 -10
- package/types/engine/ids.d.mts +0 -114
- package/types/engine/index-records.d.mts +6 -4
- package/types/engine/index.d.mts +0 -1
- package/types/engine/infobox-render.d.mts +7 -1
- package/types/engine/infobox.d.mts +3 -2
- package/types/engine/item-docs.d.mts +1 -1
- package/types/engine/item-registry.d.mts +2 -4
- package/types/engine/literature-notes.d.mts +1 -1
- package/types/engine/markdownlint-run.d.mts +40 -0
- package/types/engine/metadata-index.d.mts +9 -1
- package/types/engine/note-addresses.d.mts +27 -2
- package/types/engine/note-claims.d.mts +3 -5
- package/types/engine/note-ids.d.mts +2 -4
- package/types/engine/note-package.d.mts +1 -1
- package/types/engine/note-state.d.mts +1 -3
- package/types/engine/note-vocabulary.d.mts +28 -21
- package/types/engine/pack-config.d.mts +2 -6
- package/types/engine/pack-router.d.mts +4 -4
- package/types/engine/pathnames.d.mts +3 -3
- package/types/engine/pdf-build.d.mts +98 -12
- package/types/engine/pdf-coverage.d.mts +60 -0
- package/types/engine/pdf-index.d.mts +34 -5
- package/types/engine/pdf-pages.d.mts +143 -0
- package/types/engine/pdf-render.d.mts +45 -1
- package/types/engine/pdf-toc.d.mts +12 -14
- package/types/engine/prose-config.d.mts +1 -1
- package/types/engine/prose-lint.d.mts +11 -10
- package/types/engine/runtime-only-fields.d.mts +2 -2
- package/types/engine/site-build.d.mts +9 -5
- package/types/engine/site-index.d.mts +4 -5
- package/types/engine/site-root.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +31 -2
- package/types/engine/standing-terms.d.mts +2 -1
- package/types/engine/standings.d.mts +7 -9
- package/types/engine/system-block.d.mts +10 -44
- package/types/engine/walk-files.d.mts +15 -0
- package/types/engine/wikilink-syntax.d.mts +18 -19
- package/types/engine/yaml-lint.d.mts +5 -4
- package/types/hm3/actors.d.mts +1 -2
- package/types/hm3/item-fields.d.mts +2 -4
- package/types/hm3/template-priority.d.mts +6 -7
- package/types/manifest.d.mts +3 -2
- package/types/release.d.mts +12 -7
- package/types/sohl/actors.d.mts +2 -1
- package/types/sohl/document-subtypes.d.mts +1 -2
- package/types/sohl/item-fields.d.mts +3 -7
- package/engine/retired-fields.mjs +0 -631
- package/types/engine/retired-fields.d.mts +0 -354
package/sohl/kb-passes.mjs
CHANGED
|
@@ -51,9 +51,9 @@ import log from "loglevel";
|
|
|
51
51
|
* code spans rather than refuse to build.
|
|
52
52
|
*
|
|
53
53
|
* **Configuring one that cannot be used is a defect, and it fails the build.**
|
|
54
|
-
* A missing file, a malformed one, a permissions error and a path typo
|
|
54
|
+
* A missing file, a malformed one, a permissions error and a path typo would
|
|
55
55
|
* be indistinguishable from each other *and* from a correctly configured build
|
|
56
|
-
* with no symbols
|
|
56
|
+
* with no symbols, were a bare `catch` to return `{}` for all of them. Nothing then
|
|
57
57
|
* compares an emitted page against what its source asked for, so the first
|
|
58
58
|
* observer of a broken map was a reader who clicked nothing, because every
|
|
59
59
|
* `{@link}` on the published site had quietly become a code span.
|
|
@@ -112,7 +112,7 @@ function readSymbolMap(file, repoRoot) {
|
|
|
112
112
|
|
|
113
113
|
// Reported because a map that loaded and a map that loaded empty are
|
|
114
114
|
// otherwise indistinguishable without reading the emitted HTML — and an
|
|
115
|
-
// empty one degrades every tag exactly as a missing one
|
|
115
|
+
// empty one degrades every tag exactly as a missing one does.
|
|
116
116
|
log.info(`resolved ${Object.keys(parsed).length} API symbols from ${file}`);
|
|
117
117
|
return parsed;
|
|
118
118
|
}
|
package/types/container.d.mts
CHANGED
|
@@ -91,10 +91,12 @@ export function resolveFoundryVersion(stage: string, { env, stages, compatibilit
|
|
|
91
91
|
/**
|
|
92
92
|
* The image a run uses.
|
|
93
93
|
*
|
|
94
|
-
* `FOUNDRYVTT_CONTAINER_IMAGE` wins, then `packageBuild.container.image
|
|
95
|
-
* felddy's
|
|
96
|
-
*
|
|
97
|
-
*
|
|
94
|
+
* `FOUNDRYVTT_CONTAINER_IMAGE` wins, then `packageBuild.container.image`. A
|
|
95
|
+
* pinned exact build takes felddy's tag for that build: each image installs its
|
|
96
|
+
* own build by default and warns that a different `FOUNDRY_VERSION` "may not
|
|
97
|
+
* function properly". Otherwise felddy's major tag for whichever version the
|
|
98
|
+
* package implies — the pin, or failing that the compatibility floor. Only a
|
|
99
|
+
* package that claims neither floats.
|
|
98
100
|
*
|
|
99
101
|
* @param {object} [opts]
|
|
100
102
|
* @param {NodeJS.ProcessEnv} [opts.env] - Environment to read.
|
|
@@ -162,6 +164,37 @@ export function resolveDataRoot(stage: string, { env }?: {
|
|
|
162
164
|
* @returns {[string, string][]} The pairs to pass through.
|
|
163
165
|
*/
|
|
164
166
|
export function passthroughEnv(env?: NodeJS.ProcessEnv): [string, string][];
|
|
167
|
+
/**
|
|
168
|
+
* Whether the image has to sign in to foundryvtt.com to start.
|
|
169
|
+
*
|
|
170
|
+
* Given `FOUNDRY_USERNAME` and `FOUNDRY_PASSWORD`, the image signs in and asks
|
|
171
|
+
* for a download URL on every container it creates, even when the release is
|
|
172
|
+
* already in its cache. Each of those is a request foundryvtt.com rate-limits,
|
|
173
|
+
* and one refused with HTTP 429 stops the container before Foundry starts. The
|
|
174
|
+
* account serves two purposes only: downloading a release that is not cached,
|
|
175
|
+
* and fetching a licence key for an unlicensed data root. When neither applies
|
|
176
|
+
* the account is withheld, and the release installs from the cache with no
|
|
177
|
+
* network request.
|
|
178
|
+
*
|
|
179
|
+
* The image caches `foundryvtt-<version>.zip` in the mounted cache, or in
|
|
180
|
+
* `container_cache` beneath the data root when no cache is mounted.
|
|
181
|
+
*
|
|
182
|
+
* @param {object} opts
|
|
183
|
+
* @param {string|null} [opts.cacheDir] - The host cache mounted into the container.
|
|
184
|
+
* @param {string} opts.dataRoot - The host data root mounted at `/data`.
|
|
185
|
+
* @param {string|null} [opts.version] - The pinned build; with none, the
|
|
186
|
+
* archive's name is unknown.
|
|
187
|
+
* @param {string|null} [opts.licenseKey] - The licence key the image is given.
|
|
188
|
+
* @param {(file: string) => boolean} [opts.fileExists] - Replaceable for tests.
|
|
189
|
+
* @returns {boolean} Whether to pass the account through.
|
|
190
|
+
*/
|
|
191
|
+
export function needsFoundryAccount({ cacheDir, dataRoot, version, licenseKey, fileExists, }: {
|
|
192
|
+
cacheDir?: string | null | undefined;
|
|
193
|
+
dataRoot: string;
|
|
194
|
+
version?: string | null | undefined;
|
|
195
|
+
licenseKey?: string | null | undefined;
|
|
196
|
+
fileExists?: ((file: string) => boolean) | undefined;
|
|
197
|
+
}): boolean;
|
|
165
198
|
/**
|
|
166
199
|
* The full `docker run` argument vector for a stage's container.
|
|
167
200
|
*
|
|
@@ -179,9 +212,16 @@ export function passthroughEnv(env?: NodeJS.ProcessEnv): [string, string][];
|
|
|
179
212
|
* @param {string|null} [opts.version] - Exact build to pin.
|
|
180
213
|
* @param {string|null} [opts.world] - World to auto-launch; `""` forces none.
|
|
181
214
|
* @param {string|null} [opts.licenseKey] - Dedicated licence key.
|
|
215
|
+
* @param {boolean} [opts.account] - Whether to pass `FOUNDRY_USERNAME` and
|
|
216
|
+
* `FOUNDRY_PASSWORD` through; see {@link needsFoundryAccount}.
|
|
217
|
+
* @param {string|null} [opts.user] - `--user` value to run the container as.
|
|
218
|
+
* `felddy/foundryvtt` runs Foundry as user 1000 and ignores `FOUNDRY_UID` and
|
|
219
|
+
* `FOUNDRY_GID`; under rootless Docker, container root is the host user, so
|
|
220
|
+
* `0:0` makes every file under the data root theirs. Blank or `null` leaves
|
|
221
|
+
* the image's own user.
|
|
182
222
|
* @returns {string[]} Arguments after `docker`.
|
|
183
223
|
*/
|
|
184
|
-
export function dockerRunArgs({ name, image, port, dataRoot, env, cacheDir, version, world, licenseKey, }: {
|
|
224
|
+
export function dockerRunArgs({ name, image, port, dataRoot, env, cacheDir, version, world, licenseKey, account, user, }: {
|
|
185
225
|
name: string;
|
|
186
226
|
image: string;
|
|
187
227
|
port: number;
|
|
@@ -191,6 +231,8 @@ export function dockerRunArgs({ name, image, port, dataRoot, env, cacheDir, vers
|
|
|
191
231
|
version?: string | null | undefined;
|
|
192
232
|
world?: string | null | undefined;
|
|
193
233
|
licenseKey?: string | null | undefined;
|
|
234
|
+
account?: boolean | undefined;
|
|
235
|
+
user?: string | null | undefined;
|
|
194
236
|
}): string[];
|
|
195
237
|
/**
|
|
196
238
|
* Run the `docker` CLI, inheriting stdio.
|
|
@@ -200,6 +242,70 @@ export function dockerRunArgs({ name, image, port, dataRoot, env, cacheDir, vers
|
|
|
200
242
|
* @throws {Error} When `docker` is not on `PATH`.
|
|
201
243
|
*/
|
|
202
244
|
export function runDocker(args: string[]): number;
|
|
245
|
+
/**
|
|
246
|
+
* The `docker run` argument vector for a short-lived container that runs a
|
|
247
|
+
* shell script against a stage's data root.
|
|
248
|
+
*
|
|
249
|
+
* It uses the stage's own image and mounts the data root at `/data`, so the
|
|
250
|
+
* script sees files exactly as the Foundry container does. Under rootless
|
|
251
|
+
* Docker, only the container's user namespace can unlink what the container's
|
|
252
|
+
* user wrote, and only it can hand files to that user.
|
|
253
|
+
*
|
|
254
|
+
* @param {object} opts
|
|
255
|
+
* @param {string} opts.image - Image reference.
|
|
256
|
+
* @param {string} opts.dataRoot - Host directory to mount at `/data`.
|
|
257
|
+
* @param {string} opts.script - A `sh` script; `$1`, `$2` … are `args`.
|
|
258
|
+
* @param {string[]} [opts.args] - Positional arguments for the script.
|
|
259
|
+
* @param {string|null} [opts.user] - `--user` value; `null` runs as the image's
|
|
260
|
+
* own user.
|
|
261
|
+
* @returns {string[]} Arguments after `docker`.
|
|
262
|
+
*/
|
|
263
|
+
export function dataRootScriptArgs({ image, dataRoot, script, args, user }: {
|
|
264
|
+
image: string;
|
|
265
|
+
dataRoot: string;
|
|
266
|
+
script: string;
|
|
267
|
+
args?: string[] | undefined;
|
|
268
|
+
user?: string | null | undefined;
|
|
269
|
+
}): string[];
|
|
270
|
+
/**
|
|
271
|
+
* Run a shell script against a stage's data root in a throwaway container.
|
|
272
|
+
*
|
|
273
|
+
* @param {object} opts - As for {@link dataRootScriptArgs}.
|
|
274
|
+
* @returns {string} The script's standard output.
|
|
275
|
+
* @throws {Error} When `docker` is missing or the script exits non-zero.
|
|
276
|
+
*/
|
|
277
|
+
export function runDataRootScript(opts: object): string;
|
|
278
|
+
/**
|
|
279
|
+
* A remover for trees under a stage's data root that the container's user
|
|
280
|
+
* owns, run as root in a throwaway container on that data root — the same
|
|
281
|
+
* mechanism that hands an end-to-end install to the container's user.
|
|
282
|
+
*
|
|
283
|
+
* @param {object} opts
|
|
284
|
+
* @param {ResolvedContainer} opts.container - The stage's container.
|
|
285
|
+
* @param {(opts: object) => string} [opts.runScript] - Throwaway-container runner.
|
|
286
|
+
* @returns {(tree: string, where: {dataRoot: string}) => void} Removes one tree.
|
|
287
|
+
*/
|
|
288
|
+
export function containerTreeRemover({ container, runScript }: {
|
|
289
|
+
container: ResolvedContainer;
|
|
290
|
+
runScript?: ((opts: object) => string) | undefined;
|
|
291
|
+
}): (tree: string, where: {
|
|
292
|
+
dataRoot: string;
|
|
293
|
+
}) => void;
|
|
294
|
+
/**
|
|
295
|
+
* The command {@link containerTreeRemover} runs, written out for a person to
|
|
296
|
+
* paste when the deploy could not run it.
|
|
297
|
+
*
|
|
298
|
+
* @param {object} opts
|
|
299
|
+
* @param {string} opts.image - Image reference.
|
|
300
|
+
* @param {string} opts.dataRoot - Host directory mounted at `/data`.
|
|
301
|
+
* @param {string} opts.tree - The tree to remove, beneath the data root.
|
|
302
|
+
* @returns {string} A `docker run` command line.
|
|
303
|
+
*/
|
|
304
|
+
export function containerRemovalCommand({ image, dataRoot, tree }: {
|
|
305
|
+
image: string;
|
|
306
|
+
dataRoot: string;
|
|
307
|
+
tree: string;
|
|
308
|
+
}): string;
|
|
203
309
|
/**
|
|
204
310
|
* Run the `docker` CLI and capture its output, tolerating failure.
|
|
205
311
|
*
|
|
@@ -255,6 +361,7 @@ export function clearStaleLock(dataRoot: string, log?: (message: string) => void
|
|
|
255
361
|
* @property {string|null} world
|
|
256
362
|
* @property {string|null} licenseKey
|
|
257
363
|
* @property {string|null} cacheDir
|
|
364
|
+
* @property {string|null} user - From `FOUNDRYVTT_CONTAINER_USER`.
|
|
258
365
|
*/
|
|
259
366
|
/**
|
|
260
367
|
* Resolve a stage's container settings.
|
|
@@ -367,4 +474,8 @@ export type ResolvedContainer = {
|
|
|
367
474
|
world: string | null;
|
|
368
475
|
licenseKey: string | null;
|
|
369
476
|
cacheDir: string | null;
|
|
477
|
+
/**
|
|
478
|
+
* - From `FOUNDRYVTT_CONTAINER_USER`.
|
|
479
|
+
*/
|
|
480
|
+
user: string | null;
|
|
370
481
|
};
|
|
@@ -87,28 +87,6 @@ export namespace DEFAULT_PATHS {
|
|
|
87
87
|
* @satisfies {readonly PackDocumentType[]}
|
|
88
88
|
*/
|
|
89
89
|
export const PACK_DOCUMENT_TYPES: readonly ["Actor", "Adventure", "Item", "JournalEntry", "Macro", "Scene"];
|
|
90
|
-
/**
|
|
91
|
-
* Address-scheme keys a configuration may no longer declare.
|
|
92
|
-
*
|
|
93
|
-
* A retired key has exactly two possible fates, and only one of them is honest
|
|
94
|
-
* — the same reasoning `engine/retired-fields.mjs` applies to a retired
|
|
95
|
-
* frontmatter field. Left honoured, it keeps doing whatever it did, which is
|
|
96
|
-
* why it was retired. Left *ignored*, it reads to its author as though it still
|
|
97
|
-
* works: the configuration says one thing and the build does another, and
|
|
98
|
-
* nothing says so. This module has no third option, because it has no warning
|
|
99
|
-
* channel — every finding goes through `fail()`, which throws. So a retired
|
|
100
|
-
* key is **refused**, at the line it was written on, with a message that says
|
|
101
|
-
* the mechanism is gone rather than naming a value to correct.
|
|
102
|
-
*
|
|
103
|
-
* **`landing` is one such key.** It named which note addressed a whole section
|
|
104
|
-
* rather than a page within one — a *landing page*, which therefore had no slug
|
|
105
|
-
* of its own. There are no sections to address: a section is a Hugo content
|
|
106
|
-
* directory the note format does not carry, a page's address names no
|
|
107
|
-
* directory, and so no note lands anything.
|
|
108
|
-
*
|
|
109
|
-
* @type {Readonly<Record<string, string>>}
|
|
110
|
-
*/
|
|
111
|
-
export const RETIRED_ADDRESS_KEYS: Readonly<Record<string, string>>;
|
|
112
90
|
/**
|
|
113
91
|
* A repository's address scheme, with the defaults an unconfigured one gets.
|
|
114
92
|
*
|
|
@@ -119,9 +97,7 @@ export const RETIRED_ADDRESS_KEYS: Readonly<Record<string, string>>;
|
|
|
119
97
|
* knowledge, held in `PACKAGE_BASE` (`engine/content-address.mjs`) and prefixed at
|
|
120
98
|
* resolve time, so it is never recorded here.
|
|
121
99
|
*
|
|
122
|
-
* It is the whole scheme
|
|
123
|
-
* whole section, is retired with the sections themselves — see
|
|
124
|
-
* {@link RETIRED_ADDRESS_KEYS}.
|
|
100
|
+
* It is the whole scheme.
|
|
125
101
|
*/
|
|
126
102
|
export const DEFAULT_ADDRESS_SCHEME: Readonly<{
|
|
127
103
|
prefix: "";
|
|
@@ -136,6 +112,16 @@ export const DEFAULT_ADDRESS_SCHEME: Readonly<{
|
|
|
136
112
|
* @type {readonly string[]}
|
|
137
113
|
*/
|
|
138
114
|
export const RELATIONSHIP_KEYS: readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* The closed list a person's `role` in `authors` is drawn from.
|
|
117
|
+
*
|
|
118
|
+
* One role per entry: a person with two roles is listed twice. Printed in
|
|
119
|
+
* title case after the name on a book's title page; the Foundry manifest,
|
|
120
|
+
* whose author schema has no role, never receives it.
|
|
121
|
+
*
|
|
122
|
+
* @type {readonly string[]}
|
|
123
|
+
*/
|
|
124
|
+
export const AUTHOR_ROLES: readonly string[];
|
|
139
125
|
/**
|
|
140
126
|
* How the loader hands {@link defineConfig} the system version it resolved.
|
|
141
127
|
*
|
|
@@ -164,6 +150,44 @@ export const DERIVED_SYSTEM_VERSION: symbol;
|
|
|
164
150
|
* @type {Readonly<Record<string, string>>}
|
|
165
151
|
*/
|
|
166
152
|
export const DERIVED_HUGO_KEYS: Readonly<Record<string, string>>;
|
|
153
|
+
/**
|
|
154
|
+
* One declared book, resolved.
|
|
155
|
+
*/
|
|
156
|
+
export type ResolvedPdfBook = {
|
|
157
|
+
/**
|
|
158
|
+
* Its name on the command line, `--book <id>`.
|
|
159
|
+
*/
|
|
160
|
+
id: string;
|
|
161
|
+
title: string;
|
|
162
|
+
/**
|
|
163
|
+
* `""` when none is declared.
|
|
164
|
+
*/
|
|
165
|
+
subtitle: string;
|
|
166
|
+
/**
|
|
167
|
+
* Absolute; `""` when none is declared.
|
|
168
|
+
* Whether the file exists is checked when the
|
|
169
|
+
* book is built, not here.
|
|
170
|
+
*/
|
|
171
|
+
coverImage: string;
|
|
172
|
+
/**
|
|
173
|
+
* Absolute paths of the front matter.
|
|
174
|
+
*/
|
|
175
|
+
front: readonly string[];
|
|
176
|
+
/**
|
|
177
|
+
* The file stem; the version is appended.
|
|
178
|
+
*/
|
|
179
|
+
out: string;
|
|
180
|
+
/**
|
|
181
|
+
* The tree written inline, or
|
|
182
|
+
* `null` when `document` names a file.
|
|
183
|
+
*/
|
|
184
|
+
contents: readonly object[] | null;
|
|
185
|
+
/**
|
|
186
|
+
* Absolute path of the tree's file, or `""`
|
|
187
|
+
* when the tree is written inline.
|
|
188
|
+
*/
|
|
189
|
+
document: string;
|
|
190
|
+
};
|
|
167
191
|
export type PackageKind = "systems" | "modules" | "documentation";
|
|
168
192
|
export type PackDocumentType = "Actor" | "Adventure" | "Item" | "JournalEntry" | "Macro" | "Scene";
|
|
169
193
|
/**
|
|
@@ -573,6 +597,26 @@ export type ItemRegistrySpec = {
|
|
|
573
597
|
*/
|
|
574
598
|
builders: Record<string, ItemBuilderEntry>;
|
|
575
599
|
};
|
|
600
|
+
/**
|
|
601
|
+
* One person in the top-level `authors` list.
|
|
602
|
+
*/
|
|
603
|
+
export type AuthorSpec = {
|
|
604
|
+
/**
|
|
605
|
+
* As printed.
|
|
606
|
+
*/
|
|
607
|
+
name: string;
|
|
608
|
+
email?: string | undefined;
|
|
609
|
+
url?: string | undefined;
|
|
610
|
+
/**
|
|
611
|
+
* A Discord handle, as Foundry's author schema
|
|
612
|
+
* carries one.
|
|
613
|
+
*/
|
|
614
|
+
discord?: string | undefined;
|
|
615
|
+
/**
|
|
616
|
+
* One of {@link AUTHOR_ROLES}.
|
|
617
|
+
*/
|
|
618
|
+
role?: string | undefined;
|
|
619
|
+
};
|
|
576
620
|
/**
|
|
577
621
|
* The configuration a consumer writes.
|
|
578
622
|
*/
|
|
@@ -606,14 +650,12 @@ export type ContentBuildConfigInput = {
|
|
|
606
650
|
*/
|
|
607
651
|
homepage?: string | undefined;
|
|
608
652
|
/**
|
|
609
|
-
*
|
|
610
|
-
*
|
|
653
|
+
* The people who made the
|
|
654
|
+
* package. The Foundry manifest's
|
|
655
|
+
* `authors` and the site's byline
|
|
656
|
+
* are generated from it.
|
|
611
657
|
*/
|
|
612
|
-
|
|
613
|
-
name: string;
|
|
614
|
-
email?: string;
|
|
615
|
-
url?: string;
|
|
616
|
-
} | undefined;
|
|
658
|
+
authors?: AuthorSpec[] | undefined;
|
|
617
659
|
/**
|
|
618
660
|
* Whether the package is a system, a
|
|
619
661
|
* module, or documentation — the kind
|
|
@@ -720,9 +762,15 @@ export type ContentBuildConfig = {
|
|
|
720
762
|
*/
|
|
721
763
|
homepage: string | null;
|
|
722
764
|
/**
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
765
|
+
* The people who made
|
|
766
|
+
* the package, in the order declared; `[]`
|
|
767
|
+
* when none are.
|
|
768
|
+
*/
|
|
769
|
+
authors: readonly Readonly<AuthorSpec>[];
|
|
770
|
+
/**
|
|
771
|
+
* Derived: the first of `authors`, in npm's
|
|
772
|
+
* `author` shape — the site's byline.
|
|
773
|
+
* `null` when no author is declared.
|
|
726
774
|
*/
|
|
727
775
|
author: Readonly<{
|
|
728
776
|
name: string;
|
package/types/deploy.d.mts
CHANGED
|
@@ -85,9 +85,17 @@ export function buildConnection(stageUpper: string, remote: {
|
|
|
85
85
|
*
|
|
86
86
|
* @param {string} srcAbs - The staged tree.
|
|
87
87
|
* @param {string} destDir - Where the package installs.
|
|
88
|
-
* @
|
|
88
|
+
* @param {object} [opts]
|
|
89
|
+
* @param {(tree: string) => void|Promise<void>} [opts.removeTree] - Removes a
|
|
90
|
+
* previous tree the host user is refused permission to remove.
|
|
91
|
+
* @returns {Promise<{leftovers: LeftoverTree[]}>} The previous trees that
|
|
92
|
+
* could not be removed; the new one is installed either way.
|
|
89
93
|
*/
|
|
90
|
-
export function deployLocal(srcAbs: string, destDir: string
|
|
94
|
+
export function deployLocal(srcAbs: string, destDir: string, { removeTree }?: {
|
|
95
|
+
removeTree?: ((tree: string) => void | Promise<void>) | undefined;
|
|
96
|
+
}): Promise<{
|
|
97
|
+
leftovers: LeftoverTree[];
|
|
98
|
+
}>;
|
|
91
99
|
/**
|
|
92
100
|
* Mirror the staged build into a remote directory over SFTP, with the same
|
|
93
101
|
* staged swap {@link deployLocal} performs.
|
|
@@ -100,11 +108,14 @@ export function deployLocal(srcAbs: string, destDir: string): Promise<void>;
|
|
|
100
108
|
* @param {string} remoteDir - Where the package installs on the host.
|
|
101
109
|
* @param {object} [opts]
|
|
102
110
|
* @param {(uploaded: string) => void} [opts.onUpload] - Per-file progress.
|
|
103
|
-
* @returns {Promise<
|
|
111
|
+
* @returns {Promise<{leftovers: LeftoverTree[]}>} The previous tree when it
|
|
112
|
+
* could not be removed; the new one is installed either way.
|
|
104
113
|
*/
|
|
105
114
|
export function deployRemote(conn: object, srcAbs: string, remoteDir: string, { onUpload }?: {
|
|
106
115
|
onUpload?: ((uploaded: string) => void) | undefined;
|
|
107
|
-
}): Promise<
|
|
116
|
+
}): Promise<{
|
|
117
|
+
leftovers: LeftoverTree[];
|
|
118
|
+
}>;
|
|
108
119
|
/**
|
|
109
120
|
* Deploy a staged package to one stage, choosing the transport from the
|
|
110
121
|
* configured destination.
|
|
@@ -117,10 +128,13 @@ export function deployRemote(conn: object, srcAbs: string, remoteDir: string, {
|
|
|
117
128
|
* @param {NodeJS.ProcessEnv} [opts.env] - The environment to read.
|
|
118
129
|
* @param {string} [opts.prefix] - Fallback variable prefix for SFTP overrides.
|
|
119
130
|
* @param {(message: string) => void} [opts.log] - Progress reporting.
|
|
120
|
-
* @
|
|
131
|
+
* @param {RemoveTree} [opts.removeTree] - Removes a previous local tree the
|
|
132
|
+
* host user is refused permission to remove.
|
|
133
|
+
* @returns {Promise<{stage: string, destination: string, remote: boolean, leftovers: LeftoverTree[]}>}
|
|
134
|
+
* `leftovers` names each previous tree the deploy installed past but could not remove.
|
|
121
135
|
* @throws {Error} On an unknown stage, or one with no destination configured.
|
|
122
136
|
*/
|
|
123
|
-
export function deployStage({ stage, source, packageKind, packageId, env, prefix, log, }: {
|
|
137
|
+
export function deployStage({ stage, source, packageKind, packageId, env, prefix, log, removeTree, }: {
|
|
124
138
|
stage: string;
|
|
125
139
|
source: string;
|
|
126
140
|
packageKind: "systems" | "modules";
|
|
@@ -128,10 +142,12 @@ export function deployStage({ stage, source, packageKind, packageId, env, prefix
|
|
|
128
142
|
env?: NodeJS.ProcessEnv | undefined;
|
|
129
143
|
prefix?: string | undefined;
|
|
130
144
|
log?: ((message: string) => void) | undefined;
|
|
145
|
+
removeTree?: RemoveTree | undefined;
|
|
131
146
|
}): Promise<{
|
|
132
147
|
stage: string;
|
|
133
148
|
destination: string;
|
|
134
149
|
remote: boolean;
|
|
150
|
+
leftovers: LeftoverTree[];
|
|
135
151
|
}>;
|
|
136
152
|
/**
|
|
137
153
|
* The environment variable naming each stage's Foundry data root.
|
|
@@ -146,3 +162,23 @@ export const STAGE_ENV_MAP: Readonly<{
|
|
|
146
162
|
prod: "FOUNDRYVTT_PROD_DATA";
|
|
147
163
|
test: "FOUNDRYVTT_TEST_DATA";
|
|
148
164
|
}>;
|
|
165
|
+
/**
|
|
166
|
+
* A previous package tree a deploy could not remove after the swap.
|
|
167
|
+
*/
|
|
168
|
+
export type LeftoverTree = {
|
|
169
|
+
/**
|
|
170
|
+
* - The tree, still under its `….old-<pid>` name.
|
|
171
|
+
*/
|
|
172
|
+
path: string;
|
|
173
|
+
/**
|
|
174
|
+
* - Why the last attempt to remove it failed.
|
|
175
|
+
*/
|
|
176
|
+
reason: string;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Removes a tree the host user cannot, typically by acting as the user that
|
|
180
|
+
* owns its files. Receives the tree and the stage's data root.
|
|
181
|
+
*/
|
|
182
|
+
export type RemoveTree = (tree: string, where: {
|
|
183
|
+
dataRoot: string;
|
|
184
|
+
}) => void | Promise<void>;
|
package/types/e2e.d.mts
CHANGED
|
@@ -146,25 +146,57 @@ export function parseFastArgs(argv: string[], build: Record<string, {
|
|
|
146
146
|
*
|
|
147
147
|
* Writes `world.json` and compiles each LevelDB collection from JSON, so the
|
|
148
148
|
* result is a genuine world Foundry launches without migration or setup. The
|
|
149
|
-
* world directory is
|
|
150
|
-
*
|
|
149
|
+
* world directory is replaced each time, which is what makes a run repeatable.
|
|
150
|
+
*
|
|
151
|
+
* The world is built in a staging directory beside the worlds, then moved into
|
|
152
|
+
* place and handed to the Foundry container's user by a throwaway container
|
|
153
|
+
* mounting the same data root. Replacing the old world happens there too. Both
|
|
154
|
+
* halves matter: a database the host user wrote cannot be locked by the
|
|
155
|
+
* container's user, and a directory the container's user wrote (such as the
|
|
156
|
+
* `lost/` folder Foundry's repair makes) cannot be unlinked by the host user.
|
|
151
157
|
*
|
|
152
158
|
* @param {object} opts
|
|
153
159
|
* @param {object} opts.config - The resolved package-build configuration.
|
|
154
160
|
* @param {object} opts.packageJson - The repository's `package.json`.
|
|
155
161
|
* @param {NodeJS.ProcessEnv} [opts.env] - Environment to read.
|
|
156
162
|
* @param {(message: string) => void} [opts.log] - Progress reporting.
|
|
163
|
+
* @param {(opts: object) => string} [opts.runScript] - Runs a shell script in a
|
|
164
|
+
* throwaway container on the data root; replaceable for tests.
|
|
157
165
|
* @returns {Promise<{worldDir: string, world: E2EWorld}>} Where it landed.
|
|
158
166
|
*/
|
|
159
|
-
export function seedTestWorld({ config, packageJson, env, log }: {
|
|
167
|
+
export function seedTestWorld({ config, packageJson, env, log, runScript, }: {
|
|
160
168
|
config: object;
|
|
161
169
|
packageJson: object;
|
|
162
170
|
env?: NodeJS.ProcessEnv | undefined;
|
|
163
171
|
log?: ((message: string) => void) | undefined;
|
|
172
|
+
runScript?: ((opts: object) => string) | undefined;
|
|
164
173
|
}): Promise<{
|
|
165
174
|
worldDir: string;
|
|
166
175
|
world: E2EWorld;
|
|
167
176
|
}>;
|
|
177
|
+
/**
|
|
178
|
+
* Deploy the staged package to the end-to-end stage so the container's user
|
|
179
|
+
* can run it.
|
|
180
|
+
*
|
|
181
|
+
* The package's databases (compendium packs) are written by the host user, and
|
|
182
|
+
* Foundry cannot lock them unless it owns them; a pack Foundry has repaired
|
|
183
|
+
* holds directories the host user cannot unlink. So the previous install is
|
|
184
|
+
* removed, and the new one handed over, by a throwaway container on the same
|
|
185
|
+
* data root. A remote destination is deployed as {@link deployStage} does.
|
|
186
|
+
*
|
|
187
|
+
* @param {object} opts
|
|
188
|
+
* @param {object} opts.config - The resolved package-build configuration.
|
|
189
|
+
* @param {NodeJS.ProcessEnv} [opts.env] - Environment to read.
|
|
190
|
+
* @param {(message: string) => void} [opts.log] - Progress reporting.
|
|
191
|
+
* @param {(opts: object) => string} [opts.runScript] - Throwaway-container runner.
|
|
192
|
+
* @returns {Promise<void>}
|
|
193
|
+
*/
|
|
194
|
+
export function deployForContainer({ config, env, log, runScript, }: {
|
|
195
|
+
config: object;
|
|
196
|
+
env?: NodeJS.ProcessEnv | undefined;
|
|
197
|
+
log?: ((message: string) => void) | undefined;
|
|
198
|
+
runScript?: ((opts: object) => string) | undefined;
|
|
199
|
+
}): Promise<void>;
|
|
168
200
|
/**
|
|
169
201
|
* Poll until the world is active, or fail with a diagnosis.
|
|
170
202
|
*
|
|
@@ -40,26 +40,13 @@ export function isAddressSegment(value: unknown): boolean;
|
|
|
40
40
|
* The shape every address segment must match: **lowercase** ASCII letters and
|
|
41
41
|
* digits only.
|
|
42
42
|
*
|
|
43
|
-
* Case *was* deliberately unconstrained, on the reasoning that case has no
|
|
44
|
-
* bearing on the separator — which is true, and beside the point.
|
|
45
|
-
*
|
|
46
43
|
* **Two names that differ only in case are two names nobody can tell apart.** A
|
|
47
44
|
* shortcode is how a person names a thing when writing a reference —
|
|
48
45
|
* `model: weapongear-dgr`, `[[skill-melee|…]]` — and `Dgr` beside `dgr` is a
|
|
49
|
-
* distinction you cannot say out loud and can only see by looking twice.
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* `sohl-sohl-weapongear-clb` and its `_id` derived from that. The authored name
|
|
54
|
-
* and its address disagreed, and everything downstream keys on the address —
|
|
55
|
-
* which left two notes differing only in case sharing one address, one `_id` and
|
|
56
|
-
* one URL, with nothing to report it. It also forces two exceptions elsewhere:
|
|
57
|
-
* the shortcode has to be exempted from the lowercase rule pinned on every
|
|
58
|
-
* other segment, and its case has to be folded in the item catalogue because
|
|
59
|
-
* an address is lowercased when read.
|
|
60
|
-
*
|
|
61
|
-
* One case, one spelling, no exceptions. Every tree already complies but two,
|
|
62
|
-
* and nothing in any of them collides when folded.
|
|
46
|
+
* distinction you cannot say out loud and can only see by looking twice. So the
|
|
47
|
+
* shortcode is held to the same rule as every other segment: a note declaring
|
|
48
|
+
* `shortcode: Dgr` is refused, and so is a declared Address spelling one with a
|
|
49
|
+
* capital.
|
|
63
50
|
*
|
|
64
51
|
* @type {RegExp}
|
|
65
52
|
*/
|
|
@@ -21,11 +21,16 @@
|
|
|
21
21
|
* - `no-content-index` — the package named publishes no content index, so there
|
|
22
22
|
* is nothing to resolve the rest of the target against.
|
|
23
23
|
* - `not-lowercase` — a package, system or type segment carries a capital.
|
|
24
|
+
* - `shortcode-not-lowercase` — the Address spells its shortcode with a
|
|
25
|
+
* capital and is otherwise well formed. `shortcode` carries the segment as
|
|
26
|
+
* written, and `lowercase` the reading of the lowercase spelling: complete
|
|
27
|
+
* for a declared Address, and as partial as the written value otherwise.
|
|
24
28
|
* - `invalid-segment` — a declared Address contains a malformed segment.
|
|
25
29
|
* - `no-package` — a declared Address cannot supply its package.
|
|
26
30
|
* - `invalid-system` — a declared Address cannot supply a registered system.
|
|
27
31
|
*
|
|
28
|
-
* @typedef {{reason: string, package?: string
|
|
32
|
+
* @typedef {{reason: string, package?: string, shortcode?: string,
|
|
33
|
+
* lowercase?: AddressTuple}} AddressProblem
|
|
29
34
|
*/
|
|
30
35
|
/**
|
|
31
36
|
* The configured types whose prose compiles into a separate JournalEntry.
|
|
@@ -94,17 +99,15 @@ export function resolveItemDocType(qualifier: string, types: Set<string>): strin
|
|
|
94
99
|
* label already removed.
|
|
95
100
|
* @param {AddressDefaults} [defaults] - The position's defaults and the tree's
|
|
96
101
|
* vocabularies.
|
|
97
|
-
* @param {{declared?: boolean
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* completed tuple contains their canonical lowercase identity.
|
|
102
|
+
* @param {{declared?: boolean}} [options] - A declared Address is validated as
|
|
103
|
+
* written: every segment, the shortcode included, is lowercase, and the
|
|
104
|
+
* defaults must be complete. Package membership is a separate resolution
|
|
105
|
+
* question in this mode; prose recognition keeps its vocabulary checks.
|
|
102
106
|
* @returns {AddressTuple|AddressProblem} The complete Address, or why there is
|
|
103
107
|
* none.
|
|
104
108
|
*/
|
|
105
|
-
export function parseAddress(written: unknown, defaults?: AddressDefaults, { declared
|
|
109
|
+
export function parseAddress(written: unknown, defaults?: AddressDefaults, { declared }?: {
|
|
106
110
|
declared?: boolean;
|
|
107
|
-
legacyShortcodeCase?: boolean;
|
|
108
111
|
}): AddressTuple | AddressProblem;
|
|
109
112
|
/**
|
|
110
113
|
* Split a written value at its anchor.
|
|
@@ -343,6 +346,10 @@ export type AddressTuple = {
|
|
|
343
346
|
* - `no-content-index` — the package named publishes no content index, so there
|
|
344
347
|
* is nothing to resolve the rest of the target against.
|
|
345
348
|
* - `not-lowercase` — a package, system or type segment carries a capital.
|
|
349
|
+
* - `shortcode-not-lowercase` — the Address spells its shortcode with a
|
|
350
|
+
* capital and is otherwise well formed. `shortcode` carries the segment as
|
|
351
|
+
* written, and `lowercase` the reading of the lowercase spelling: complete
|
|
352
|
+
* for a declared Address, and as partial as the written value otherwise.
|
|
346
353
|
* - `invalid-segment` — a declared Address contains a malformed segment.
|
|
347
354
|
* - `no-package` — a declared Address cannot supply its package.
|
|
348
355
|
* - `invalid-system` — a declared Address cannot supply a registered system.
|
|
@@ -350,6 +357,8 @@ export type AddressTuple = {
|
|
|
350
357
|
export type AddressProblem = {
|
|
351
358
|
reason: string;
|
|
352
359
|
package?: string;
|
|
360
|
+
shortcode?: string;
|
|
361
|
+
lowercase?: AddressTuple;
|
|
353
362
|
};
|
|
354
363
|
/**
|
|
355
364
|
* The vocabularies a written Address is read against.
|
|
@@ -106,7 +106,8 @@ export function assetImageInfoByPathname(records?: readonly object[]): Map<strin
|
|
|
106
106
|
* slot's. Omitted, any asset type is taken, which is an embed's rule: it
|
|
107
107
|
* draws a file, and every asset type is a file.
|
|
108
108
|
* @returns {{record: {package: string, asset: {path: string}}, pathname: string}
|
|
109
|
-
* |{record: null, reason: string, type?: string
|
|
109
|
+
* |{record: null, reason: string, type?: string, shortcode?: string,
|
|
110
|
+
* declared?: string}} The asset and the pathname
|
|
110
111
|
* it is at, or a reason from
|
|
111
112
|
* {@link module:engine/wikilink-syntax.LINK_FINDING_REASONS}, or `not-accepted`
|
|
112
113
|
* when `accepts` is given and the parsed type falls outside it.
|
|
@@ -123,6 +124,8 @@ export function readAssetAddress(index: object, value: unknown, defaultType: str
|
|
|
123
124
|
record: null;
|
|
124
125
|
reason: string;
|
|
125
126
|
type?: string;
|
|
127
|
+
shortcode?: string;
|
|
128
|
+
declared?: string;
|
|
126
129
|
};
|
|
127
130
|
/**
|
|
128
131
|
* The index record an art value resolves to, or `null`.
|
|
@@ -184,9 +187,9 @@ export function checkArtSlotSizes(records?: readonly object[], { config, assetsB
|
|
|
184
187
|
* The pathname an art value names, in the form an authored one takes.
|
|
185
188
|
*
|
|
186
189
|
* Handing the result to {@link module:engine/helpers.resolveImg} is what puts an
|
|
187
|
-
* art address and a body image through one ownership rule.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
+
* art address and a body image through one ownership rule. `null` and an
|
|
191
|
+
* absent key mean *no art named, apply the default*; an empty string names
|
|
192
|
+
* nothing and is unresolved like any other address nothing answers.
|
|
190
193
|
*
|
|
191
194
|
* @param {object} index - From {@link module:engine/wikilinks.buildWikilinkIndex}.
|
|
192
195
|
* @param {unknown} value - The value as authored.
|
|
@@ -34,6 +34,12 @@ export type ArtSlot = {
|
|
|
34
34
|
* - Whether the slot reaches a compiled document.
|
|
35
35
|
*/
|
|
36
36
|
document: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* - The literal value that declines the slot's
|
|
39
|
+
* art on purpose. It is never read as an Address: it resolves to no image and
|
|
40
|
+
* is emitted as a blank, which a theme reads as "draw none".
|
|
41
|
+
*/
|
|
42
|
+
declines?: string | undefined;
|
|
37
43
|
/**
|
|
38
44
|
* - One line, for the author-facing reference.
|
|
39
45
|
*/
|