@heroiclands/package-build 22.14.2 → 22.14.4
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 +26 -0
- package/bin/content-build.mjs +6 -6
- package/bin/package-build.mjs +10 -0
- package/config.mjs +18 -1
- package/content-config.mjs +2 -2
- package/docs/api.md +66 -37
- package/docs/configuration.md +16 -7
- package/docs/content-format.md +172 -200
- package/docs/getting-started.md +46 -14
- package/docs/project-setup.md +5 -6
- package/engine/address.mjs +3 -5
- package/engine/asset-bindings.mjs +66 -0
- package/engine/calendar-notes.mjs +74 -0
- package/engine/changelog-lint.mjs +2 -2
- package/engine/content-images.mjs +20 -10
- package/engine/content-index.mjs +63 -36
- package/engine/content-lint.mjs +1 -2
- package/engine/content-package.mjs +2 -2
- package/engine/content-tables.mjs +4 -8
- package/engine/folder-notes.mjs +1 -2
- package/engine/foundry-entries.mjs +21 -6
- package/engine/frontmatter-lint.mjs +3 -4
- package/engine/frontmatter.mjs +5 -8
- package/engine/helpers.mjs +3 -4
- package/engine/index.mjs +3 -0
- package/engine/infobox.mjs +66 -2
- package/engine/item-registry.mjs +2 -2
- package/engine/note-vocabulary.mjs +83 -5
- package/engine/pack-config.mjs +2 -2
- package/engine/pack-router.mjs +2 -2
- package/engine/pdf-render.mjs +31 -8
- package/engine/pdf-toc.mjs +3 -3
- package/engine/retired-fields.mjs +1 -1
- package/engine/scene-levels.mjs +4 -4
- package/engine/schema-check.mjs +1 -1
- package/engine/site-build.mjs +134 -121
- package/engine/site-preview.mjs +293 -0
- package/engine/site-root.mjs +20 -2
- package/engine/social-tie-terms.mjs +11 -0
- package/engine/social-ties.mjs +84 -0
- package/engine/sql-tables.mjs +4 -9
- package/hm3/actors.mjs +1 -1
- package/package.json +3 -3
- package/sohl/item-fields.mjs +2 -2
- package/types/config.d.mts +8 -0
- package/types/content-config.d.mts +1 -1
- package/types/engine/address.d.mts +3 -5
- package/types/engine/asset-bindings.d.mts +6 -0
- package/types/engine/calendar-notes.d.mts +12 -0
- package/types/engine/content-images.d.mts +7 -4
- package/types/engine/content-index.d.mts +11 -0
- package/types/engine/content-package.d.mts +2 -2
- package/types/engine/folder-notes.d.mts +1 -2
- package/types/engine/frontmatter-lint.d.mts +1 -2
- package/types/engine/frontmatter.d.mts +2 -4
- package/types/engine/helpers.d.mts +3 -4
- package/types/engine/index.d.mts +1 -0
- package/types/engine/item-registry.d.mts +2 -2
- package/types/engine/note-vocabulary.d.mts +5 -6
- package/types/engine/pack-config.d.mts +1 -1
- package/types/engine/pack-router.d.mts +1 -1
- package/types/engine/pdf-render.d.mts +10 -1
- package/types/engine/pdf-toc.d.mts +1 -1
- package/types/engine/site-build.d.mts +36 -3
- package/types/engine/site-preview.d.mts +34 -0
- package/types/engine/social-tie-terms.d.mts +5 -0
- package/types/engine/social-ties.d.mts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 22.14.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
**Illustrations** — Named image sizes set the display width on pages and in books. Images without a size use their natural dimensions within the available space.
|
|
8
|
+
|
|
9
|
+
## 22.14.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
Editors can preview a content page from unsaved text, including its tables, links, images, and GM passages.
|
|
14
|
+
|
|
15
|
+
Setting orientation pages can be authored as setting guides, with the same links, tables, and GM passages as other guides.
|
|
16
|
+
|
|
17
|
+
**Content authoring**
|
|
18
|
+
|
|
19
|
+
- Beings can describe defining social ties, and place notes can identify their practical purpose.
|
|
20
|
+
- Calendar notes can set their own display formats, and being birth and death dates receive date validation.
|
|
21
|
+
- Structured place and affiliation relationships appear as linked rows in the infobox.
|
|
22
|
+
|
|
23
|
+
**Published output**
|
|
24
|
+
|
|
25
|
+
- Content indexes identify each system's Actor document separately when a note produces more than one.
|
|
26
|
+
- Alternative art builds report image names that have no matching note in the related package.
|
|
27
|
+
- Site search archives include every indexed page.
|
|
28
|
+
|
|
3
29
|
## 22.14.2
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/bin/content-build.mjs
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*
|
|
25
25
|
* The side effects that need *configuration* live inside the command handler,
|
|
26
26
|
* not at module scope, so `--version` and `--help` answer in a directory that
|
|
27
|
-
* has neither a `package-build.config.yaml` nor a package manifest
|
|
27
|
+
* has neither a `package-build.config.yaml` nor a package manifest.
|
|
28
28
|
* Running an actual command still resolves both, and still fails loudly when
|
|
29
29
|
* either is missing.
|
|
30
30
|
*
|
|
@@ -158,11 +158,11 @@ import { loadMapWorld } from "../engine/map-places.mjs";
|
|
|
158
158
|
* knows them. It does not come out of the shipped manifest — a second
|
|
159
159
|
* declaration of the same list, in a second format, with nothing checking that
|
|
160
160
|
* the two agreed. The manifest is generated from this list now
|
|
161
|
-
|
|
161
|
+
*, so reading it back would be a round trip through an
|
|
162
162
|
* artifact that need not exist.
|
|
163
163
|
*
|
|
164
164
|
* Read on demand rather than at load, so `--version` and `--help` still answer
|
|
165
|
-
* with no configuration present
|
|
165
|
+
* with no configuration present.
|
|
166
166
|
*
|
|
167
167
|
* @returns {Array<{name: string}>}
|
|
168
168
|
*/
|
|
@@ -1979,8 +1979,8 @@ function reachabilityCommand() {
|
|
|
1979
1979
|
*/
|
|
1980
1980
|
async function fetchFromLocalArtifact(config, argv) {
|
|
1981
1981
|
// Two caches, two dependency sets: an index is fetched for every declared
|
|
1982
|
-
// dependency, a catalogue only for those declaring `itemCatalog: true
|
|
1983
|
-
//
|
|
1982
|
+
// dependency, a catalogue only for those declaring `itemCatalog: true`.
|
|
1983
|
+
// `--from` fills whichever of them this dependency belongs to, so
|
|
1984
1984
|
// that testing against an unreleased build behaves like a release would.
|
|
1985
1985
|
const rels = metadataRelationships(config);
|
|
1986
1986
|
const named = rels.map((r) => r.id).join(", ") || "none";
|
|
@@ -2307,7 +2307,7 @@ function packageCommand() {
|
|
|
2307
2307
|
// The one directory the pipeline creates rather than expects:
|
|
2308
2308
|
// `unpack` writes the extracted JSON there and `compile` reads
|
|
2309
2309
|
// it back. Created here rather than at module scope so that
|
|
2310
|
-
// asking the CLI its version needs no configuration
|
|
2310
|
+
// asking the CLI its version needs no configuration.
|
|
2311
2311
|
fs.mkdirSync(config.paths.unpack, {
|
|
2312
2312
|
recursive: true,
|
|
2313
2313
|
});
|
package/bin/package-build.mjs
CHANGED
|
@@ -80,6 +80,8 @@ import yargs from "yargs";
|
|
|
80
80
|
import { hideBin } from "yargs/helpers";
|
|
81
81
|
|
|
82
82
|
import { loadPackageBuildConfig } from "../config.mjs";
|
|
83
|
+
import { checkForeignAssetBindings } from "../engine/asset-bindings.mjs";
|
|
84
|
+
import { formatDiagnostic } from "../engine/diagnostics.mjs";
|
|
83
85
|
import { writeSiteRoot } from "../engine/site-root.mjs";
|
|
84
86
|
import { DEPLOY_ROOT } from "../engine/site-config.mjs";
|
|
85
87
|
import { compilesFoundryDocuments } from "../content-config.mjs";
|
|
@@ -271,6 +273,14 @@ function assetsCommand() {
|
|
|
271
273
|
console.log("package-build: no `packageBuild.assets` declared; nothing to stage.");
|
|
272
274
|
return;
|
|
273
275
|
}
|
|
276
|
+
const bindings = checkForeignAssetBindings(loadPackConfig(), {
|
|
277
|
+
assets: config.assets,
|
|
278
|
+
});
|
|
279
|
+
if (bindings.length) {
|
|
280
|
+
const error = new Error(bindings.map(formatDiagnostic).join("\n"));
|
|
281
|
+
error.located = true;
|
|
282
|
+
die(error);
|
|
283
|
+
}
|
|
274
284
|
|
|
275
285
|
let transform;
|
|
276
286
|
if (config.assetTransform) {
|
package/config.mjs
CHANGED
|
@@ -100,7 +100,7 @@ export const DERIVED_MANIFEST_KEYS = Object.freeze({
|
|
|
100
100
|
relationships: "the top level of package-build.config.yaml",
|
|
101
101
|
packs: "the `packs` list at the top level of package-build.config.yaml",
|
|
102
102
|
});
|
|
103
|
-
const ASSET_KEYS = ["from", "to"];
|
|
103
|
+
const ASSET_KEYS = ["from", "to", "bindsTo"];
|
|
104
104
|
const CLEAN_KEYS = ["extra"];
|
|
105
105
|
const LANG_KEYS = [
|
|
106
106
|
"sources",
|
|
@@ -210,6 +210,8 @@ function requireNonEmptyString(value, where) {
|
|
|
210
210
|
* @typedef {object} AssetSpec
|
|
211
211
|
* @property {string} from Source path, relative to the repository root.
|
|
212
212
|
* @property {string} to Destination, relative to the staged package root.
|
|
213
|
+
* @property {{package: string, system: string, type: string}|undefined} [bindsTo]
|
|
214
|
+
* The foreign Address each file's basename claims, without its shortcode.
|
|
213
215
|
*/
|
|
214
216
|
|
|
215
217
|
/**
|
|
@@ -222,9 +224,24 @@ function normalizeAsset(value, index) {
|
|
|
222
224
|
if (!isMapping(value)) fail(where, "must be a mapping");
|
|
223
225
|
const asset = /** @type {Record<string, unknown>} */ (value);
|
|
224
226
|
rejectUnknownKeys(asset, ASSET_KEYS, `${where}.`);
|
|
227
|
+
let bindsTo;
|
|
228
|
+
if (asset.bindsTo !== undefined) {
|
|
229
|
+
if (!isMapping(asset.bindsTo)) fail(`${where}.bindsTo`, "must be a mapping");
|
|
230
|
+
const binding = /** @type {Record<string, unknown>} */ (asset.bindsTo);
|
|
231
|
+
rejectUnknownKeys(binding, ["package", "system", "type"], `${where}.bindsTo.`);
|
|
232
|
+
bindsTo = Object.freeze({
|
|
233
|
+
package: requireNonEmptyString(binding.package, `${where}.bindsTo.package`),
|
|
234
|
+
system:
|
|
235
|
+
binding.system === undefined ?
|
|
236
|
+
"note"
|
|
237
|
+
: requireNonEmptyString(binding.system, `${where}.bindsTo.system`),
|
|
238
|
+
type: requireNonEmptyString(binding.type, `${where}.bindsTo.type`),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
225
241
|
return Object.freeze({
|
|
226
242
|
from: requireNonEmptyString(asset.from, `${where}.from`),
|
|
227
243
|
to: requireNonEmptyString(asset.to, `${where}.to`),
|
|
244
|
+
...(bindsTo ? { bindsTo } : {}),
|
|
228
245
|
});
|
|
229
246
|
}
|
|
230
247
|
|
package/content-config.mjs
CHANGED
|
@@ -688,7 +688,7 @@ export function publishesContentPages(config) {
|
|
|
688
688
|
* @property {Readonly<Record<string, string>>} itemArt Derived: the default art
|
|
689
689
|
* of each entry that paired one. Sparse — a
|
|
690
690
|
* type absent here has no default, and a note
|
|
691
|
-
* of it must carry `img
|
|
691
|
+
* of it must carry `img:`.
|
|
692
692
|
* @property {Readonly<Record<string, readonly object[]>>} itemFields Derived:
|
|
693
693
|
* the frontmatter fields each entry
|
|
694
694
|
* declared. Sparse, like `itemArt` — a type
|
|
@@ -2202,7 +2202,7 @@ function normalizePackageBuild(value) {
|
|
|
2202
2202
|
* travel by different routes: `itemTypes` was derived from these keys, while
|
|
2203
2203
|
* art was looked up in `sohl/default-item-art.mjs` — a table a consumer cannot
|
|
2204
2204
|
* add to. A consumer's own item type was therefore configurable while its
|
|
2205
|
-
* default art was not, so its notes all had to carry an explicit `img
|
|
2205
|
+
* default art was not, so its notes all had to carry an explicit `img:`.
|
|
2206
2206
|
* Art now travels with the builder it belongs to, which is the one place a type
|
|
2207
2207
|
* is already declared.
|
|
2208
2208
|
*
|
package/docs/api.md
CHANGED
|
@@ -5,15 +5,11 @@ subpath entries, declared in `package.json`'s `exports` map. Every function
|
|
|
5
5
|
and value documented here is a supported contract, not an internal seam —
|
|
6
6
|
`./sohl` and `./hm3` included.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
handful of packaging functions — deploying, staging, running a container,
|
|
14
|
-
packing a release — necessarily touch the filesystem or a subprocess; each
|
|
15
|
-
is named for it in the tables below, and the pure half of its module is kept
|
|
16
|
-
separate from it.
|
|
8
|
+
Rule functions take source text or already-loaded data and return findings or
|
|
9
|
+
values. That lets one rule set serve a lint script, a build step and a unit
|
|
10
|
+
test without tying diagnostics to a particular reporter. Context builders,
|
|
11
|
+
content walks, site rendering, and packaging functions read or write files as
|
|
12
|
+
their signatures and descriptions state.
|
|
17
13
|
|
|
18
14
|
This reference is organized by subpath entry, matching how a consumer
|
|
19
15
|
imports: `import * as engine from "@heroiclands/package-build/engine"` reads
|
|
@@ -640,19 +636,22 @@ A date on a note is one authored string — `[~][-]YYYY[/MM[/DD]] [<calendar sho
|
|
|
640
636
|
|
|
641
637
|
A calendar is a `lore` note with `subType: calendar`, declaring the months it keeps, the weekdays it names, the seasons it marks and the eras it counts years in. How long the year is, how the day divides and how the moon moves are facts about the **world**, written on its `place` note and its moon's, and no calendar may restate them — which is why the months summing to the world's year is the only arithmetic a calendar note is held to. One definition is emitted per calendar, in array shape: Foundry core prunes the keys outside its schema, and Calendaria converts the arrays to its own keyed collections.
|
|
642
638
|
|
|
643
|
-
| Export
|
|
644
|
-
|
|
|
645
|
-
| `CALENDAR_SUBTYPE`
|
|
646
|
-
| `INVARIANT_SUBTYPES`
|
|
647
|
-
| `CALENDAR_FIELDS`
|
|
648
|
-
| `
|
|
649
|
-
| `
|
|
650
|
-
| `
|
|
651
|
-
| `
|
|
652
|
-
| `
|
|
653
|
-
| `
|
|
654
|
-
| `
|
|
655
|
-
| `
|
|
639
|
+
| Export | Signature | Returns | Use it when |
|
|
640
|
+
| --------------------------- | ----------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------- |
|
|
641
|
+
| `CALENDAR_SUBTYPE` | `const CALENDAR_SUBTYPE` | — | naming the `lore` subType whose notes are calendars |
|
|
642
|
+
| `INVARIANT_SUBTYPES` | `const INVARIANT_SUBTYPES` | — | naming the `place` subTypes a world fact may be written on |
|
|
643
|
+
| `CALENDAR_FIELDS` | `const CALENDAR_FIELDS` | — | reading the closed list of what a calendar note may declare |
|
|
644
|
+
| `CALENDAR_DATE_FORMAT_KEYS` | `const CALENDAR_DATE_FORMAT_KEYS` | — | reading the supported Calendaria display slots |
|
|
645
|
+
| `CALENDAR_FORMAT_TOKENS` | `const CALENDAR_FORMAT_TOKENS` | — | checking bare date tokens in a format string |
|
|
646
|
+
| `INVARIANT_FIELDS` | `const INVARIANT_FIELDS` | — | reading the closed list of what a body may declare about itself |
|
|
647
|
+
| `checkCalendarNote` | `checkCalendarNote(note, opts)` | `object[]` — findings | holding a `lore` note to the family and to the year the world keeps |
|
|
648
|
+
| `checkCalendarDateFormats` | `checkCalendarDateFormats(note)` | `object[]` — findings | checking display slots and escaped literal words |
|
|
649
|
+
| `checkWorldFacts` | `checkWorldFacts(note, opts)` | `object[]` — findings | holding a `place` note's world facts to one body, one year and one moon |
|
|
650
|
+
| `worldInvariants` | `worldInvariants(index)` | `{year, present, moon, body, moonName, …}` | reading the year, the present and the moon a package's own notes state |
|
|
651
|
+
| `quarterDays` | `quarterDays(daysPerYear)` | `number[]` — four days of the year | asking which days the year turns on |
|
|
652
|
+
| `compileCalendar` | `compileCalendar({note, invariants, contentPackage})` | `object` — the definition | building the one object both a core consumer and Calendaria read |
|
|
653
|
+
| `compileCalendars` | `compileCalendars(index, opts)` | `{calendars, invariants}` | building every calendar a package declares, or none where it states no year |
|
|
654
|
+
| `calendariaEnvelope` | `calendariaEnvelope(definition, opts)` | `object` — the import envelope | wrapping a definition for a hand import through Calendaria's settings |
|
|
656
655
|
|
|
657
656
|
### `engine.beingAge`
|
|
658
657
|
|
|
@@ -769,17 +768,18 @@ Emitting this package's cross-package link manifest. `engine/content-address.mjs
|
|
|
769
768
|
|
|
770
769
|
Emitting this package's content index. Every content build already walks the whole note tree and parses every note's frontmatter — the pack compilers, the site build, and the content-table expander each do it — and every one of them throws the result away when it finishes. So nothing outside a build can ask a question about the content: "which beings carry no `kbcat`?", "what does this table actually select?", "did that type rename leave anything behind?" have no answer short of writing a throwaway script that re-walks the tree. Eight dead Bestiary tables shipped for weeks behind exactly that gap.
|
|
771
770
|
|
|
772
|
-
| Export | Signature
|
|
773
|
-
| ----------------------- |
|
|
774
|
-
| `noteAddress` | `function noteAddress(frontmatter, contentPackage)`
|
|
775
|
-
| `sortKeysDeep` | `function sortKeysDeep(value)`
|
|
776
|
-
| `asciiName` | `function asciiName(name)`
|
|
777
|
-
| `asciiAliases` | `function asciiAliases(aliases)`
|
|
778
|
-
| `serializeContentIndex` | `function serializeContentIndex(records)`
|
|
779
|
-
| `indexRecordsFor` | `indexRecordsFor({ contentBase, config, skipDirectories, problems })`
|
|
780
|
-
| `
|
|
781
|
-
| `
|
|
782
|
-
| `
|
|
771
|
+
| Export | Signature | Returns | Use it when |
|
|
772
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
773
|
+
| `noteAddress` | `function noteAddress(frontmatter, contentPackage)` | {{slug: string, canonical: string}\|null} `slug` is what goes inside `[[…]]` within this package; `canonical` is the fully qualified key the manifest files the note under, carrying the package and the system as well. | The address a wikilink writes to reach a note, or `null` when it has none. |
|
|
774
|
+
| `sortKeysDeep` | `function sortKeysDeep(value)` | {unknown} The value with every plain object's keys in sorted order. | Recursively sort an object's keys, so serialization is order-independent. |
|
|
775
|
+
| `asciiName` | `function asciiName(name)` | {string\|null} The ASCII form, or `null` when there is no name, or nothing printable survives. | A note's display name reduced to printable 7-bit ASCII. |
|
|
776
|
+
| `asciiAliases` | `function asciiAliases(aliases)` | {Array<string>} Possibly empty, never null: a note with no aliases has an empty set of them, which is a fact rather than a missing value, and a consumer iterating it should not have to check first. | A note's `name.aliases` reduced to printable 7-bit ASCII, in order. |
|
|
777
|
+
| `serializeContentIndex` | `function serializeContentIndex(records)` | {string} One compact JSON object per line, newline-terminated. | Serialize records as JSON Lines. |
|
|
778
|
+
| `indexRecordsFor` | `indexRecordsFor({ contentBase, config, skipDirectories, problems })` | {object[]} One record per note, plus one per documentation entry. | The index records for a content tree, without writing anything. |
|
|
779
|
+
| `indexRecordsForNote` | `indexRecordsForNote({ frontmatter, body, bodyLine, relPath, absPath, contentPackage, manifest, addressContext })` | `object[]` | Derive the note's own record and its documentation record from parsed text. |
|
|
780
|
+
| `emitContentIndex` | `emitContentIndex({ contentBase, outDir, config })` | {{file: string, notes: number, assets: number, records: number, bytes: number, full: number, draft: number, stub: number}} Where it was written, how many notes and how many assets it holds, how many records that is in all, its size, and the ladder those notes sit on. | Emit this package's content index. |
|
|
781
|
+
| `buildIndexRecord` | `buildIndexRecord({ frontmatter, relPath, absPath, contentPackage, body, bodyLine, manifest })` | `Record<string, any>` — the record, with derived fields sorted deep | building one note's content-index record; refuses a note that authors a key the index derives itself (`package` among them) before building anything |
|
|
782
|
+
| `collectContentIndex` | `collectContentIndex(contentBase, { contentPackage, skipDirectories, assetsBase, manifest, problems })` | `Array<Record<string, any>>` | reading a whole content tree into index records, in a total order independent of directory-read order; an item note yields two records (its own and its documentation journal's), and each asset root yields one per file |
|
|
783
783
|
|
|
784
784
|
`engine.contentIndex` also re-exports eight names from neighbouring leaf modules, at this same import path:
|
|
785
785
|
|
|
@@ -860,10 +860,38 @@ Publishing a content tree as a website. Compiling a content tree into compendium
|
|
|
860
860
|
| `tableUniverse` | `function tableUniverse(pages)` | {Map<string, object[]>} Package → the notes it may tabulate. | The universe a generated table searches, grouped by package. |
|
|
861
861
|
| `pageFrontmatter` | `function pageFrontmatter(page,` | {object} The frontmatter to write. | The frontmatter a page publishes with. |
|
|
862
862
|
| `pageDestination` | `function pageDestination(page, { bundle })` | — | Where a page is written, relative to the output root: flat, or as a leaf bundle when it carries a file beside itself. |
|
|
863
|
+
| `renderSitePage` | `renderSitePage(page, options)` | `{body, data, resolved, tableErrors, secretErrors, wikiErrors, imageErrors}` | Transform one page with the same passes the site writer uses. |
|
|
863
864
|
| `renderPages` | `function renderPages(pages, options)` | {{written: number, byKind: Record<string, number>, tableErrors: object[], wikiErrors: object[]}} | Renders and writes every page. |
|
|
864
865
|
| `resolveSitePass` | `function resolveSitePass(name, options)` | {{beforeLinks?: Function}} The bundle. | Resolves `site.pass` to its bundle. |
|
|
866
|
+
| `sitePageDecorator` | `sitePageDecorator(config, index)` | Function | Add the site's infobox and being metadata to a rendered page. |
|
|
865
867
|
| `buildSite` | `buildSite({ config, sqlTables, locate })` | {{gates: object, stats: object\|null, tableErrors: object[], wikiErrors: object[], mapFindings: object[], manifests: object\|null}} | Builds a Hugo content tree from a content tree, and reports what it found. |
|
|
866
868
|
|
|
869
|
+
### `engine.sitePreview`
|
|
870
|
+
|
|
871
|
+
`prepareSitePreview({ config })` reads the saved content tree and declared dependency indexes, prepares its SQL corpus, and returns a private preview context. Pass the active note's absolute path and complete buffer text to `render(file, text)`. A successful result has `{ ok: true, markdown, frontmatter, findings: [] }`; a failed result has `{ ok: false, findings }` and no replacement content. Findings identify the source file and carry a line and column when the offending text can be located.
|
|
872
|
+
|
|
873
|
+
| Export | Signature | Returns | Use it when |
|
|
874
|
+
| -------------------- | -------------------------------- | ------------------------------------------ | -------------------------------------------------- |
|
|
875
|
+
| `prepareSitePreview` | `prepareSitePreview({ config })` | `{render(file, text), refresh(), close()}` | An editor needs a private, reusable page renderer. |
|
|
876
|
+
|
|
877
|
+
The context keeps other notes and foreign packages at their saved state. Call `refresh()` after a save to read them again, and `close()` when the editor releases the project. Rendering and refreshing never write the authored notes or the site's `build/hugo/content` mount. The editor owns any private HTML artifact and keeps its last complete artifact when a render fails.
|
|
878
|
+
|
|
879
|
+
```js
|
|
880
|
+
import { sitePreview } from "@heroiclands/package-build/engine";
|
|
881
|
+
|
|
882
|
+
const preview = await sitePreview.prepareSitePreview({ config });
|
|
883
|
+
try {
|
|
884
|
+
const result = await preview.render(absoluteFile, currentBufferText);
|
|
885
|
+
if (result.ok) {
|
|
886
|
+
// Convert result.markdown and result.frontmatter to the editor's HTML preview.
|
|
887
|
+
} else {
|
|
888
|
+
showDiagnostics(result.findings);
|
|
889
|
+
}
|
|
890
|
+
} finally {
|
|
891
|
+
await preview.close();
|
|
892
|
+
}
|
|
893
|
+
```
|
|
894
|
+
|
|
867
895
|
### `engine.contentLint`
|
|
868
896
|
|
|
869
897
|
Linting a content tree's **addresses** — the rules every package's notes are authored against, wherever those notes live. These rules do not live in a consumer's `utils/`, which has two consequences and no upside. `thalorna` and `kethira` notes were checked by nothing at all, so the packages most likely to carry authoring mistakes were the ones nothing inspected. And one rule with two implementations can disagree without anything detecting it, which the canonical-separator handling already did once on each side.
|
|
@@ -937,12 +965,12 @@ Raw HTML in a note's prose, reported. **A note is markdown.** What markdown cann
|
|
|
937
965
|
|
|
938
966
|
### `engine.contentImages`
|
|
939
967
|
|
|
940
|
-
An image saying how wide it is and where it sits. A
|
|
968
|
+
An image saying how wide it is and where it sits. A directive in the curly-attribute convention Pandoc and Kramdown use supplies a width class, a named `size:`, and a `float:` position. The named size sets a maximum display width for each surface.
|
|
941
969
|
|
|
942
970
|
| Export | Signature | Returns | Use it when |
|
|
943
971
|
| --------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
944
972
|
| `IMAGE_CLASSES` | `const IMAGE_CLASSES` | — | The width classes an image may carry, and what each means to a renderer. |
|
|
945
|
-
| `IMAGE_SIZES` | `const IMAGE_SIZES` | — | The named sizes an image directive accepts
|
|
973
|
+
| `IMAGE_SIZES` | `const IMAGE_SIZES` | — | The named sizes an image directive accepts. |
|
|
946
974
|
| `IMAGE_FLOATS` | `const IMAGE_FLOATS` | — | The `float:` positions an image may take, and where each puts it. |
|
|
947
975
|
| `IMAGE_FIGURE_CLASS` | `const IMAGE_FIGURE_CLASS` | — | The class every figure carries, whatever its width or position. |
|
|
948
976
|
| `IMAGE_PATTERN` | `const IMAGE_PATTERN` | — | A markdown image, with the directive it may carry. |
|
|
@@ -996,7 +1024,7 @@ Wikilink resolution for the knowledgebase build. The same authored links the pac
|
|
|
996
1024
|
|
|
997
1025
|
### `engine.contentTables`
|
|
998
1026
|
|
|
999
|
-
Generated content tables
|
|
1027
|
+
Generated content tables from fenced `dataview` `TABLE` queries. A catalog table (every cloth armour, every animal's abilities) is data that already lives in the frontmatter of the notes it describes. Authoring such a table by hand duplicates that data and guarantees drift, so a content body instead declares what it wants tabulated, in a fenced `dataview` block:
|
|
1000
1028
|
|
|
1001
1029
|
| Export | Signature | Returns | Use it when |
|
|
1002
1030
|
| --------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -1116,7 +1144,7 @@ What a `[[…]]` **is**, before anything decides where it points. One authored l
|
|
|
1116
1144
|
|
|
1117
1145
|
### `engine.pdfToc`
|
|
1118
1146
|
|
|
1119
|
-
The document tree a PDF is built from, and the plan it resolves to
|
|
1147
|
+
The document tree a PDF is built from, and the plan it resolves to. The packs and the website both render the _whole_ content tree: every note becomes a document and a page, and the three surfaces agreeing about what the content is, is the point. **A book is not that.** It is a selection — a declared structure whose leaves pick notes out of the corpus by a `WHERE` clause, interleaved with prose that may not live in the content tree at all.
|
|
1120
1148
|
|
|
1121
1149
|
| Export | Signature | Returns | Use it when |
|
|
1122
1150
|
| ------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
@@ -1139,6 +1167,7 @@ A note's markdown, and a document plan, rendered as Typst source. **This module
|
|
|
1139
1167
|
| `renderBook` | `renderBook({ plan, bodies, title, subtitle, front, fonts, version, preamble, banners })` | {string} A complete `.typ` document. | The whole book, as one Typst document. |
|
|
1140
1168
|
| `resolveDanglingLabels` | `function resolveDanglingLabels(source, findings` | {string} The same document, with no reference left dangling. | Point every internal link at a label the document actually declares. |
|
|
1141
1169
|
| `iconNamesIn` | `function iconNamesIn(markdown)` | {string[]} The names, in order of appearance, with repeats. | Every icon name a body uses, so a build can resolve them once. |
|
|
1170
|
+
| `BOOK_IMAGE_WIDTHS` | `const BOOK_IMAGE_WIDTHS` | — | The book measure requested by each named image size. |
|
|
1142
1171
|
| `bookTypstPreamble` | `function bookTypstPreamble()` | {string} Typst markup. | The Typst definitions the book's page furniture is drawn with. |
|
|
1143
1172
|
|
|
1144
1173
|
### `engine.pdfFonts`
|
package/docs/configuration.md
CHANGED
|
@@ -529,8 +529,8 @@ Any other key is refused:
|
|
|
529
529
|
|
|
530
530
|
**Type:** string[] · **Optional** · default `[]`.
|
|
531
531
|
|
|
532
|
-
Directory names the content walk ignores wherever they appear —
|
|
533
|
-
`Templates
|
|
532
|
+
Directory names the content walk ignores wherever they appear — an author's
|
|
533
|
+
`Templates` directory, for instance.
|
|
534
534
|
|
|
535
535
|
```yaml
|
|
536
536
|
skipDirectories: [Templates]
|
|
@@ -1465,10 +1465,11 @@ table says `lang`, not `build/stage/lang`.
|
|
|
1465
1465
|
`assets` is the table of staging copies: source path in the repository,
|
|
1466
1466
|
destination under the staged package root.
|
|
1467
1467
|
|
|
1468
|
-
| Key
|
|
1469
|
-
|
|
|
1470
|
-
| `packageBuild.assets[].from`
|
|
1471
|
-
| `packageBuild.assets[].to`
|
|
1468
|
+
| Key | Type | Required |
|
|
1469
|
+
| ------------------------------- | -------------------------- | -------- |
|
|
1470
|
+
| `packageBuild.assets[].from` | string | yes |
|
|
1471
|
+
| `packageBuild.assets[].to` | string | yes |
|
|
1472
|
+
| `packageBuild.assets[].bindsTo` | `{package, type, system?}` | no |
|
|
1472
1473
|
|
|
1473
1474
|
> ``package-build config: `packageBuild.stageDir` must be a non-empty string.``
|
|
1474
1475
|
|
|
@@ -1478,7 +1479,15 @@ destination under the staged package root.
|
|
|
1478
1479
|
|
|
1479
1480
|
> ``package-build config: `packageBuild.assets[<index>].from` must be a non-empty string.``
|
|
1480
1481
|
|
|
1481
|
-
> ``package-build config: `packageBuild.assets[<index>].<key>` is not a recognised key (expected one of: from, to).``
|
|
1482
|
+
> ``package-build config: `packageBuild.assets[<index>].<key>` is not a recognised key (expected one of: from, to, bindsTo).``
|
|
1483
|
+
|
|
1484
|
+
`bindsTo` says that every file under this copy's `from` directory uses its
|
|
1485
|
+
filename, without the extension, as a foreign Address shortcode. `package`
|
|
1486
|
+
and `type` are required; `system` defaults to `note`. The relationship with
|
|
1487
|
+
that package must provide a content index for the build to check the binding.
|
|
1488
|
+
The check reads the cached index, reports an unresolved file as an error, and
|
|
1489
|
+
does not fetch during compilation. Run `content-build deps fetch` to fill a
|
|
1490
|
+
cold cache.
|
|
1482
1491
|
|
|
1483
1492
|
### `packageBuild.assetTransform` and `packageBuild.manifestFlags`
|
|
1484
1493
|
|