@heroiclands/package-build 22.3.0 → 22.3.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 +12 -0
- package/bin/content-build.mjs +25 -3
- package/content-config.mjs +12 -1
- package/docs/commands.md +23 -0
- package/docs/configuration.md +12 -6
- package/engine/field-reference.mjs +135 -0
- package/package.json +1 -1
- package/types/content-config.d.mts +8 -0
- package/types/engine/field-reference.d.mts +78 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 22.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b2bb2b2: **`content-build docs item-fields`.** A destination under the content tree
|
|
8
|
+
(`assets/content/`) now writes a complete note — `type: doc`,
|
|
9
|
+
`subType: reference`, a derived `shortcode`, `name.full` and `pack: none` —
|
|
10
|
+
rather than a typeless page the content walk silently drops. A consumer
|
|
11
|
+
declares further note frontmatter under `docs.itemFields.frontmatter`,
|
|
12
|
+
deep-merged over the generated envelope; `--check` compares the whole file.
|
|
13
|
+
A destination outside the content tree is unaffected.
|
|
14
|
+
|
|
3
15
|
## 22.3.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/bin/content-build.mjs
CHANGED
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
formatUnaddressableFinding,
|
|
81
81
|
} from "../engine/metadata-index.mjs";
|
|
82
82
|
import { fetchNavigation, generateHugoConfig, writeHugoConfig } from "../engine/site-config.mjs";
|
|
83
|
-
import { renderItemFieldReference } from "../engine/field-reference.mjs";
|
|
83
|
+
import { renderItemFieldReference, renderItemFieldsPage } from "../engine/field-reference.mjs";
|
|
84
84
|
import { lintContentTree } from "../engine/content-lint.mjs";
|
|
85
85
|
import { lintContentCharset } from "../engine/content-charset.mjs";
|
|
86
86
|
import { lintContentHtml } from "../engine/content-html.mjs";
|
|
@@ -284,6 +284,14 @@ const argv = yargs(hideBin(process.argv))
|
|
|
284
284
|
* second implementation of the comparison. Staleness is a property of the whole
|
|
285
285
|
* generated file, so there is no line to name.
|
|
286
286
|
*
|
|
287
|
+
* **A destination under the content tree gets a note envelope**, so the walk
|
|
288
|
+
* that collects every note by its `type:` picks this one up too, rather than
|
|
289
|
+
* silently dropping it — `type: doc`, `subType: reference`, a `shortcode`
|
|
290
|
+
* derived from the destination's basename, `name.full` from the title, and
|
|
291
|
+
* `pack: none`; `docs.itemFields.frontmatter` deep-merges over it. `--check`
|
|
292
|
+
* compares the whole file, envelope included. A destination outside the
|
|
293
|
+
* content tree gets the page body alone, as before.
|
|
294
|
+
*
|
|
287
295
|
* `--out` and `--title` still override, for a one-off render.
|
|
288
296
|
*
|
|
289
297
|
* @returns {object} The yargs command module.
|
|
@@ -332,13 +340,27 @@ function docsCommand() {
|
|
|
332
340
|
const spec = config.docs?.itemFields ?? {};
|
|
333
341
|
const destination =
|
|
334
342
|
argv.out ?? (spec.out ? path.resolve(config.rootDir, spec.out) : null);
|
|
343
|
+
const pageTitle = title ?? spec.title ?? "Item Note Frontmatter";
|
|
335
344
|
|
|
336
|
-
const
|
|
337
|
-
|
|
345
|
+
const body = `${renderItemFieldReference({
|
|
346
|
+
title: pageTitle,
|
|
338
347
|
...(spec.preamble ? { preamble: spec.preamble } : {}),
|
|
339
348
|
generatedBy: "`content-build docs item-fields`",
|
|
340
349
|
config,
|
|
341
350
|
})}\n`;
|
|
351
|
+
// A page filed under the content tree is walked for its
|
|
352
|
+
// `type:` like any other note, so it needs the envelope; one
|
|
353
|
+
// filed anywhere else — a repository's own `docs/` — is not,
|
|
354
|
+
// and gets exactly the body it always did.
|
|
355
|
+
const page =
|
|
356
|
+
destination ?
|
|
357
|
+
renderItemFieldsPage(body, {
|
|
358
|
+
title: pageTitle,
|
|
359
|
+
destination,
|
|
360
|
+
contentRoot: config.paths.content,
|
|
361
|
+
frontmatter: spec.frontmatter,
|
|
362
|
+
})
|
|
363
|
+
: body;
|
|
342
364
|
|
|
343
365
|
if (check) {
|
|
344
366
|
if (!destination) {
|
package/content-config.mjs
CHANGED
|
@@ -528,6 +528,11 @@ export function publishesContentPages(config) {
|
|
|
528
528
|
* Without it the page goes to stdout.
|
|
529
529
|
* @property {string[]} [preamble] Lines between the generated banner and the
|
|
530
530
|
* first table. Markdown, emitted verbatim.
|
|
531
|
+
* @property {Record<string, unknown>} [frontmatter] Further note frontmatter,
|
|
532
|
+
* deep-merged over the generated envelope
|
|
533
|
+
* (`type: doc`, `subType: reference`,
|
|
534
|
+
* `shortcode`, `name.full`, `pack: none`)
|
|
535
|
+
* when `out` is under the content tree.
|
|
531
536
|
*/
|
|
532
537
|
|
|
533
538
|
/**
|
|
@@ -777,7 +782,7 @@ const PDF_KEYS = ["title", "subtitle", "document", "out", "front", "fonts", "ico
|
|
|
777
782
|
const PDF_FONT_KEYS = ["serif", "sans", "mono", "path"];
|
|
778
783
|
const EMPTY_PDF_FONTS = Object.freeze({ serif: "", sans: "", mono: "", path: "" });
|
|
779
784
|
const SECTION_META_KEYS = ["title", "banner", "description", "listType", "listSubType"];
|
|
780
|
-
const DOC_PAGE_KEYS = ["title", "out", "preamble"];
|
|
785
|
+
const DOC_PAGE_KEYS = ["title", "out", "preamble", "frontmatter"];
|
|
781
786
|
const RELATIONSHIP_KINDS = ["systems", "requires", "recommends", "conflicts"];
|
|
782
787
|
const RELATIONSHIP_KEYS = [
|
|
783
788
|
"id",
|
|
@@ -1435,6 +1440,12 @@ function normalizeDocPage(value, where) {
|
|
|
1435
1440
|
}),
|
|
1436
1441
|
);
|
|
1437
1442
|
}
|
|
1443
|
+
if (input.frontmatter !== undefined) {
|
|
1444
|
+
if (!isPlainObject(input.frontmatter)) {
|
|
1445
|
+
fail(`${where}.frontmatter`, "must be a mapping");
|
|
1446
|
+
}
|
|
1447
|
+
out.frontmatter = deepFreeze({ .../** @type {object} */ (input.frontmatter) });
|
|
1448
|
+
}
|
|
1438
1449
|
return Object.freeze(out);
|
|
1439
1450
|
}
|
|
1440
1451
|
|
package/docs/commands.md
CHANGED
|
@@ -1064,6 +1064,29 @@ named. Reads the configured `itemBuilders` registries; writes (or checks)
|
|
|
1064
1064
|
the destination file, or prints to stdout when none is configured and
|
|
1065
1065
|
`--out` is not given.
|
|
1066
1066
|
|
|
1067
|
+
**A destination under `paths.content` gets a complete note, not a typeless
|
|
1068
|
+
page.** The content-tree walk collects every published page by its `type:`,
|
|
1069
|
+
so a generated page filed there needs the envelope every other note carries
|
|
1070
|
+
or the walk drops it silently — no build failure, no page, every wikilink
|
|
1071
|
+
into it dead. So when `--out` (or `docs.itemFields.out`) resolves inside the
|
|
1072
|
+
content tree, the written file carries:
|
|
1073
|
+
|
|
1074
|
+
- `type: doc`, `subType: reference` — out-of-world lookup material, like
|
|
1075
|
+
every other generated reference page;
|
|
1076
|
+
- `shortcode`, derived from the destination's basename — lowercase
|
|
1077
|
+
alphanumerics only, so `item-frontmatter.md` derives `itemfrontmatter` —
|
|
1078
|
+
unless `docs.itemFields.frontmatter.shortcode` gives one;
|
|
1079
|
+
- `name.full`, from the page's title;
|
|
1080
|
+
- `pack: none` — the page publishes to the website and compiles into no
|
|
1081
|
+
compendium document.
|
|
1082
|
+
|
|
1083
|
+
`docs.itemFields.frontmatter` is deep-merged over that envelope, so a
|
|
1084
|
+
consumer may add keys (`description`, `tags`) or override any of the derived
|
|
1085
|
+
ones. `--check` then compares the **whole** file, envelope included — a page
|
|
1086
|
+
committed with a hand-written or stale envelope reads as out of date exactly
|
|
1087
|
+
as a stale body does. A destination outside the content tree gets the page
|
|
1088
|
+
body alone, with no frontmatter, exactly as before.
|
|
1089
|
+
|
|
1067
1090
|
**OPTIONS**
|
|
1068
1091
|
|
|
1069
1092
|
| Positional | Type | Default | Description |
|
package/docs/configuration.md
CHANGED
|
@@ -727,11 +727,12 @@ How this repository frames the documentation pages it generates.
|
|
|
727
727
|
registry and are the same wherever rendered; everything here is the
|
|
728
728
|
consumer's: heading, orientation, where the page is filed.
|
|
729
729
|
|
|
730
|
-
| Key
|
|
731
|
-
|
|
|
732
|
-
| `docs.itemFields.title`
|
|
733
|
-
| `docs.itemFields.out`
|
|
734
|
-
| `docs.itemFields.preamble`
|
|
730
|
+
| Key | Type | Required | Default |
|
|
731
|
+
| ----------------------------- | -------- | -------- | ---------------------------------------------------------------------- |
|
|
732
|
+
| `docs.itemFields.title` | string | no | none — the page's H1 |
|
|
733
|
+
| `docs.itemFields.out` | string | no | none — without it, the page goes to stdout |
|
|
734
|
+
| `docs.itemFields.preamble` | string[] | no | none — markdown lines between the generated banner and the first table |
|
|
735
|
+
| `docs.itemFields.frontmatter` | object | no | none — extra note frontmatter, deep-merged over the generated envelope |
|
|
735
736
|
|
|
736
737
|
> ``package-build config: `docs.itemFields` must be a mapping.``
|
|
737
738
|
|
|
@@ -744,9 +745,14 @@ consumer's: heading, orientation, where the page is filed.
|
|
|
744
745
|
|
|
745
746
|
> ``package-build config: `docs.itemFields.preamble[<index>]` must be a string.``
|
|
746
747
|
|
|
748
|
+
`frontmatter` is deep-merged over the note envelope written when `out` is
|
|
749
|
+
under the content tree — see [`content-build docs item-fields`](commands.md#content-build-docs-item-fields):
|
|
750
|
+
|
|
751
|
+
> ``package-build config: `docs.itemFields.frontmatter` must be a mapping.``
|
|
752
|
+
|
|
747
753
|
Any other key under `docs.itemFields` is refused:
|
|
748
754
|
|
|
749
|
-
> ``package-build config: `docs.itemFields.<key>` is not a recognized option (expected one of: title, out, preamble).``
|
|
755
|
+
> ``package-build config: `docs.itemFields.<key>` is not a recognized option (expected one of: title, out, preamble, frontmatter).``
|
|
750
756
|
|
|
751
757
|
### `site`
|
|
752
758
|
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
* @module
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
import path from "node:path";
|
|
38
|
+
import matter from "gray-matter";
|
|
39
|
+
|
|
37
40
|
import { authoredFields, runtimeOnlyFields } from "./field-spec.mjs";
|
|
38
41
|
import { loadPackConfig } from "./pack-config.mjs";
|
|
39
42
|
|
|
@@ -309,3 +312,135 @@ export function renderItemFieldReference({
|
|
|
309
312
|
// and then reported stale by `--check` forever after.
|
|
310
313
|
return lines.join("\n").replace(/\n+$/, "");
|
|
311
314
|
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* @param {unknown} value - Anything.
|
|
318
|
+
* @returns {boolean} Whether it is a mapping a field may be read out of.
|
|
319
|
+
*/
|
|
320
|
+
function isPlainObject(value) {
|
|
321
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Recursively merge `overlay` onto `base`. Plain objects merge key-by-key;
|
|
326
|
+
* everything else (arrays, primitives, `null`) replaces. Inputs are not
|
|
327
|
+
* mutated.
|
|
328
|
+
*
|
|
329
|
+
* @param {any} base - The generated envelope.
|
|
330
|
+
* @param {any} overlay - The consumer's declared `frontmatter`.
|
|
331
|
+
* @returns {any} The merged value.
|
|
332
|
+
*/
|
|
333
|
+
function deepMerge(base, overlay) {
|
|
334
|
+
if (overlay === undefined) return base;
|
|
335
|
+
if (!isPlainObject(base) || !isPlainObject(overlay)) return overlay;
|
|
336
|
+
const out = { ...base };
|
|
337
|
+
for (const [key, value] of Object.entries(overlay)) {
|
|
338
|
+
out[key] = key in base ? deepMerge(base[key], value) : value;
|
|
339
|
+
}
|
|
340
|
+
return out;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Whether a destination file sits under a content tree.
|
|
345
|
+
*
|
|
346
|
+
* The one question that decides whether `docs item-fields` writes a note
|
|
347
|
+
* envelope: `assets/content/` walks every file under it for its `type:`, so a
|
|
348
|
+
* generated page filed there needs one to publish at all, while a page filed
|
|
349
|
+
* anywhere else — a repository's own `docs/` — is read by nobody but Hugo's
|
|
350
|
+
* `--check` guard and the reader following a link, neither of which wants
|
|
351
|
+
* frontmatter.
|
|
352
|
+
*
|
|
353
|
+
* @param {string} destination - Absolute path of the file being written.
|
|
354
|
+
* @param {string} contentRoot - Absolute path of the content tree root
|
|
355
|
+
* (`config.paths.content`).
|
|
356
|
+
* @returns {boolean} Whether `destination` resolves inside `contentRoot`.
|
|
357
|
+
*/
|
|
358
|
+
export function isUnderContentTree(destination, contentRoot) {
|
|
359
|
+
const relative = path.relative(contentRoot, destination);
|
|
360
|
+
return (
|
|
361
|
+
relative !== "" &&
|
|
362
|
+
relative !== ".." &&
|
|
363
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
364
|
+
!path.isAbsolute(relative)
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* A note's `shortcode`, derived from the basename of its destination file.
|
|
370
|
+
*
|
|
371
|
+
* Lowercase alphanumerics only — the address charset every other shortcode in
|
|
372
|
+
* the tree is held to — so `item-frontmatter.md` derives `itemfrontmatter`
|
|
373
|
+
* rather than carrying a hyphen no address segment permits.
|
|
374
|
+
*
|
|
375
|
+
* @param {string} destination - Where the note is written.
|
|
376
|
+
* @returns {string} The derived shortcode.
|
|
377
|
+
*/
|
|
378
|
+
export function shortcodeFromBasename(destination) {
|
|
379
|
+
return path
|
|
380
|
+
.basename(destination, path.extname(destination))
|
|
381
|
+
.toLowerCase()
|
|
382
|
+
.replace(/[^a-z0-9]/g, "");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* The note envelope `docs item-fields` writes when its page lives in the
|
|
387
|
+
* content tree.
|
|
388
|
+
*
|
|
389
|
+
* The universal keys every note in the format carries: `type: doc`,
|
|
390
|
+
* `subType: reference` — this page is out-of-world lookup material, the same
|
|
391
|
+
* genre as every other generated reference — a `shortcode`, `name.full` from
|
|
392
|
+
* the page's title, and `pack: none`, since the page publishes to the website
|
|
393
|
+
* and compiles into no compendium document. A consumer's own
|
|
394
|
+
* `docs.itemFields.frontmatter` is deep-merged over it, so it may add keys or
|
|
395
|
+
* override any of the derived ones, `shortcode` included.
|
|
396
|
+
*
|
|
397
|
+
* @param {object} options
|
|
398
|
+
* @param {string} options.title - The page's H1, and `name.full`'s default.
|
|
399
|
+
* @param {string} options.shortcode - The derived shortcode, from
|
|
400
|
+
* {@link shortcodeFromBasename}.
|
|
401
|
+
* @param {Record<string, unknown>} [options.frontmatter] - The consumer's
|
|
402
|
+
* declared `docs.itemFields.frontmatter`.
|
|
403
|
+
* @returns {Record<string, unknown>} The envelope, ready for `matter.stringify`.
|
|
404
|
+
*/
|
|
405
|
+
export function itemFieldsEnvelope({ title, shortcode, frontmatter }) {
|
|
406
|
+
return deepMerge(
|
|
407
|
+
{
|
|
408
|
+
type: "doc",
|
|
409
|
+
subType: "reference",
|
|
410
|
+
shortcode,
|
|
411
|
+
name: { full: title },
|
|
412
|
+
pack: "none",
|
|
413
|
+
},
|
|
414
|
+
frontmatter,
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Wrap the rendered item-fields page in the note envelope, when its
|
|
420
|
+
* destination is under the content tree.
|
|
421
|
+
*
|
|
422
|
+
* `--check` compares the **whole** file this returns, envelope included — a
|
|
423
|
+
* page committed with its old envelope by hand, or with none at all, is
|
|
424
|
+
* exactly the staleness the guard exists to catch.
|
|
425
|
+
*
|
|
426
|
+
* @param {string} body - The page {@link renderItemFieldReference} rendered.
|
|
427
|
+
* @param {object} options
|
|
428
|
+
* @param {string} options.title - The page's H1, threaded through to
|
|
429
|
+
* `name.full`.
|
|
430
|
+
* @param {string} options.destination - Absolute path the page is written to.
|
|
431
|
+
* @param {string} options.contentRoot - Absolute path of the content tree
|
|
432
|
+
* root (`config.paths.content`).
|
|
433
|
+
* @param {Record<string, unknown>} [options.frontmatter] - The consumer's
|
|
434
|
+
* declared `docs.itemFields.frontmatter`.
|
|
435
|
+
* @returns {string} `body`, unchanged when `destination` is outside the
|
|
436
|
+
* content tree; otherwise `body` with the note envelope stringified above it.
|
|
437
|
+
*/
|
|
438
|
+
export function renderItemFieldsPage(body, { title, destination, contentRoot, frontmatter }) {
|
|
439
|
+
if (!isUnderContentTree(destination, contentRoot)) return body;
|
|
440
|
+
const envelope = itemFieldsEnvelope({
|
|
441
|
+
title,
|
|
442
|
+
shortcode: shortcodeFromBasename(destination),
|
|
443
|
+
frontmatter,
|
|
444
|
+
});
|
|
445
|
+
return matter.stringify(body, envelope);
|
|
446
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "22.3.
|
|
3
|
+
"version": "22.3.1",
|
|
4
4
|
"description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — content compilation, manifest, localization, staging, bundle, release and deployment.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -541,6 +541,14 @@ export type DocPageSpec = {
|
|
|
541
541
|
* first table. Markdown, emitted verbatim.
|
|
542
542
|
*/
|
|
543
543
|
preamble?: string[] | undefined;
|
|
544
|
+
/**
|
|
545
|
+
* Further note frontmatter,
|
|
546
|
+
* deep-merged over the generated envelope
|
|
547
|
+
* (`type: doc`, `subType: reference`,
|
|
548
|
+
* `shortcode`, `name.full`, `pack: none`)
|
|
549
|
+
* when `out` is under the content tree.
|
|
550
|
+
*/
|
|
551
|
+
frontmatter?: Record<string, unknown> | undefined;
|
|
544
552
|
};
|
|
545
553
|
/**
|
|
546
554
|
* The documentation pages this repository generates.
|
|
@@ -18,3 +18,81 @@ export function renderItemFieldReference({ title, preamble, generatedBy, config,
|
|
|
18
18
|
generatedBy?: string | undefined;
|
|
19
19
|
config?: object | undefined;
|
|
20
20
|
}): string;
|
|
21
|
+
/**
|
|
22
|
+
* Whether a destination file sits under a content tree.
|
|
23
|
+
*
|
|
24
|
+
* The one question that decides whether `docs item-fields` writes a note
|
|
25
|
+
* envelope: `assets/content/` walks every file under it for its `type:`, so a
|
|
26
|
+
* generated page filed there needs one to publish at all, while a page filed
|
|
27
|
+
* anywhere else — a repository's own `docs/` — is read by nobody but Hugo's
|
|
28
|
+
* `--check` guard and the reader following a link, neither of which wants
|
|
29
|
+
* frontmatter.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} destination - Absolute path of the file being written.
|
|
32
|
+
* @param {string} contentRoot - Absolute path of the content tree root
|
|
33
|
+
* (`config.paths.content`).
|
|
34
|
+
* @returns {boolean} Whether `destination` resolves inside `contentRoot`.
|
|
35
|
+
*/
|
|
36
|
+
export function isUnderContentTree(destination: string, contentRoot: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* A note's `shortcode`, derived from the basename of its destination file.
|
|
39
|
+
*
|
|
40
|
+
* Lowercase alphanumerics only — the address charset every other shortcode in
|
|
41
|
+
* the tree is held to — so `item-frontmatter.md` derives `itemfrontmatter`
|
|
42
|
+
* rather than carrying a hyphen no address segment permits.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} destination - Where the note is written.
|
|
45
|
+
* @returns {string} The derived shortcode.
|
|
46
|
+
*/
|
|
47
|
+
export function shortcodeFromBasename(destination: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* The note envelope `docs item-fields` writes when its page lives in the
|
|
50
|
+
* content tree.
|
|
51
|
+
*
|
|
52
|
+
* The universal keys every note in the format carries: `type: doc`,
|
|
53
|
+
* `subType: reference` — this page is out-of-world lookup material, the same
|
|
54
|
+
* genre as every other generated reference — a `shortcode`, `name.full` from
|
|
55
|
+
* the page's title, and `pack: none`, since the page publishes to the website
|
|
56
|
+
* and compiles into no compendium document. A consumer's own
|
|
57
|
+
* `docs.itemFields.frontmatter` is deep-merged over it, so it may add keys or
|
|
58
|
+
* override any of the derived ones, `shortcode` included.
|
|
59
|
+
*
|
|
60
|
+
* @param {object} options
|
|
61
|
+
* @param {string} options.title - The page's H1, and `name.full`'s default.
|
|
62
|
+
* @param {string} options.shortcode - The derived shortcode, from
|
|
63
|
+
* {@link shortcodeFromBasename}.
|
|
64
|
+
* @param {Record<string, unknown>} [options.frontmatter] - The consumer's
|
|
65
|
+
* declared `docs.itemFields.frontmatter`.
|
|
66
|
+
* @returns {Record<string, unknown>} The envelope, ready for `matter.stringify`.
|
|
67
|
+
*/
|
|
68
|
+
export function itemFieldsEnvelope({ title, shortcode, frontmatter }: {
|
|
69
|
+
title: string;
|
|
70
|
+
shortcode: string;
|
|
71
|
+
frontmatter?: Record<string, unknown> | undefined;
|
|
72
|
+
}): Record<string, unknown>;
|
|
73
|
+
/**
|
|
74
|
+
* Wrap the rendered item-fields page in the note envelope, when its
|
|
75
|
+
* destination is under the content tree.
|
|
76
|
+
*
|
|
77
|
+
* `--check` compares the **whole** file this returns, envelope included — a
|
|
78
|
+
* page committed with its old envelope by hand, or with none at all, is
|
|
79
|
+
* exactly the staleness the guard exists to catch.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} body - The page {@link renderItemFieldReference} rendered.
|
|
82
|
+
* @param {object} options
|
|
83
|
+
* @param {string} options.title - The page's H1, threaded through to
|
|
84
|
+
* `name.full`.
|
|
85
|
+
* @param {string} options.destination - Absolute path the page is written to.
|
|
86
|
+
* @param {string} options.contentRoot - Absolute path of the content tree
|
|
87
|
+
* root (`config.paths.content`).
|
|
88
|
+
* @param {Record<string, unknown>} [options.frontmatter] - The consumer's
|
|
89
|
+
* declared `docs.itemFields.frontmatter`.
|
|
90
|
+
* @returns {string} `body`, unchanged when `destination` is outside the
|
|
91
|
+
* content tree; otherwise `body` with the note envelope stringified above it.
|
|
92
|
+
*/
|
|
93
|
+
export function renderItemFieldsPage(body: string, { title, destination, contentRoot, frontmatter }: {
|
|
94
|
+
title: string;
|
|
95
|
+
destination: string;
|
|
96
|
+
contentRoot: string;
|
|
97
|
+
frontmatter?: Record<string, unknown> | undefined;
|
|
98
|
+
}): string;
|