@heroiclands/package-build 24.0.2 → 24.0.3
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 +18 -0
- package/bin/content-commands.mjs +8 -10
- package/content-config.mjs +1 -52
- package/docs/api.md +14 -8
- package/docs/authoring/links-and-markup.md +1 -1
- package/docs/commands.md +4 -6
- package/docs/configuration.md +13 -69
- package/docs/guides/site.md +3 -1
- package/docs/reference/format-details.md +19 -71
- package/docs/reference/note-types.md +3 -2
- package/engine/content-charset.mjs +1 -0
- package/engine/dictionary-layout.mjs +16 -3
- package/engine/foreign-catalog.mjs +11 -122
- package/engine/language-rows.mjs +3 -3
- package/engine/language-terms.mjs +7 -1
- package/engine/pdf-build.mjs +9 -178
- package/engine/site-reach.mjs +23 -0
- package/engine/site-render.mjs +18 -3
- package/package.json +2 -1
- package/types/content-config.d.mts +1 -19
- package/types/engine/dictionary-layout.d.mts +5 -0
- package/types/engine/foreign-catalog.d.mts +0 -38
- package/types/engine/language-rows.d.mts +1 -1
- package/types/engine/pdf-build.d.mts +5 -27
- package/types/engine/site-reach.d.mts +11 -0
- package/engine/asset-replacement.mjs +0 -93
- package/types/engine/asset-replacement.d.mts +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 24.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
**Sites**
|
|
8
|
+
|
|
9
|
+
- Glossary and dictionary entries link only to pages a reader can reach, and such links never make a page reachable.
|
|
10
|
+
|
|
11
|
+
**Configuration**
|
|
12
|
+
|
|
13
|
+
- A package can no longer declare a dependency whose images replace its own: `assetReplacement` and `assetArchive` are refused as unknown options.
|
|
14
|
+
|
|
15
|
+
**Languages and scripts**
|
|
16
|
+
|
|
17
|
+
- A sound mark can say `apart`, beside `stress` and `length`: the mark sets a vowel to be said apart from its neighbour, as a diaeresis does.
|
|
18
|
+
- A skeleton row can state `third`, the third consonants it holds for, beside `second`, so a rule that depends on the third consonant can be written.
|
|
19
|
+
- Text in the Veldikko script draws no charset warnings.
|
|
20
|
+
|
|
3
21
|
## 24.0.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/bin/content-commands.mjs
CHANGED
|
@@ -2815,18 +2815,16 @@ async function fetchFromLocalArtifact(config, argv) {
|
|
|
2815
2815
|
|
|
2816
2816
|
/**
|
|
2817
2817
|
* `deps fetch` — fill the caches this build resolves other packages through:
|
|
2818
|
-
* the **content index** of every declared dependency, the **item catalogue
|
|
2819
|
-
*
|
|
2820
|
-
* `assetArchive: true`, and the **site navigation** heroiclands.org
|
|
2818
|
+
* the **content index** of every declared dependency, the **item catalogue**
|
|
2819
|
+
* of those additionally declaring `itemCatalog: true`, and the **site navigation** heroiclands.org
|
|
2821
2820
|
* publishes, which the site build writes its menu from.
|
|
2822
2821
|
*
|
|
2823
2822
|
* The dependency sets differ deliberately. Citing another package's
|
|
2824
|
-
* *addresses
|
|
2825
|
-
*
|
|
2823
|
+
* *addresses* and embedding its *items* are separate edges, and a package may
|
|
2824
|
+
* declare either without the other —
|
|
2826
2825
|
* `harn-ensemble` cites no foreign address and embeds 324,016 item
|
|
2827
2826
|
* references. The navigation is fetched for every package, because every
|
|
2828
|
-
* package publishes a site.
|
|
2829
|
-
* and `assetArchive: true` is fetched once.
|
|
2827
|
+
* package publishes a site.
|
|
2830
2828
|
*
|
|
2831
2829
|
* Its own command rather than a step of `package compile` or `site`, so that
|
|
2832
2830
|
* neither reaches the network. A build that downloads silently is not
|
|
@@ -2887,7 +2885,7 @@ function depsCommand() {
|
|
|
2887
2885
|
const indexes = await fetchAllMetadata(config);
|
|
2888
2886
|
if (indexes) log.info(`Fetched ${indexes} dependency content index(es).`);
|
|
2889
2887
|
const count = await fetchAllCatalogs(config);
|
|
2890
|
-
if (count) log.info(`Fetched ${count} dependency catalogue(s)
|
|
2888
|
+
if (count) log.info(`Fetched ${count} dependency catalogue(s).`);
|
|
2891
2889
|
if (!indexes && !count) {
|
|
2892
2890
|
// Distinguished from a package declaring nothing at all: a
|
|
2893
2891
|
// relationship may still be declared, just narrowed to the
|
|
@@ -2899,8 +2897,8 @@ function depsCommand() {
|
|
|
2899
2897
|
);
|
|
2900
2898
|
log.info(
|
|
2901
2899
|
declared ?
|
|
2902
|
-
"No declared dependency needs a fetched content index
|
|
2903
|
-
"catalogue
|
|
2900
|
+
"No declared dependency needs a fetched content index or item " +
|
|
2901
|
+
"catalogue."
|
|
2904
2902
|
: "This package declares no dependencies.",
|
|
2905
2903
|
);
|
|
2906
2904
|
}
|
package/content-config.mjs
CHANGED
|
@@ -350,8 +350,7 @@ export function publishesContentPages(config) {
|
|
|
350
350
|
* @property {string} [stage] Compiled LevelDB packs.
|
|
351
351
|
* @property {string} [unpack] Where `unpack` extracts JSON back to.
|
|
352
352
|
* @property {string} [foreignCache] Where a dependency declaring
|
|
353
|
-
* `itemCatalog: true`
|
|
354
|
-
* `assetArchive: true` is unpacked.
|
|
353
|
+
* `itemCatalog: true` is unpacked.
|
|
355
354
|
* Inbound, and fetched rather than
|
|
356
355
|
* committed.
|
|
357
356
|
* @property {string} [metadataCache] Where a dependency's published content
|
|
@@ -474,10 +473,6 @@ export function publishesContentPages(config) {
|
|
|
474
473
|
* its Item packs, so the actors pass can
|
|
475
474
|
* resolve embedded items this repository
|
|
476
475
|
* does not hold. Needs a `manifest`.
|
|
477
|
-
* @property {boolean} [assetArchive] Whether `deps fetch` unpacks this
|
|
478
|
-
* dependency's release archive for its
|
|
479
|
-
* asset bytes alone, building no item
|
|
480
|
-
* catalogue from it. Needs a `manifest`.
|
|
481
476
|
* @property {boolean} [contentIndex] Whether `deps fetch` fetches this
|
|
482
477
|
* dependency's content index. Default
|
|
483
478
|
* `true`. `false` declares the dependency
|
|
@@ -486,13 +481,6 @@ export function publishesContentPages(config) {
|
|
|
486
481
|
* `itemCatalog: true` on the same entry,
|
|
487
482
|
* since a catalogue is fetched from the same
|
|
488
483
|
* index.
|
|
489
|
-
* @property {boolean} [assetReplacement] Whether this dependency's asset
|
|
490
|
-
* tree answers this package's own asset
|
|
491
|
-
* addresses ahead of its local record.
|
|
492
|
-
* Default `false`. Refuses `contentIndex:
|
|
493
|
-
* false` on the same entry, since a
|
|
494
|
-
* replacement with no fetched index to
|
|
495
|
-
* check against resolves nothing.
|
|
496
484
|
*/
|
|
497
485
|
|
|
498
486
|
/**
|
|
@@ -859,9 +847,7 @@ export const RELATIONSHIP_KEYS = [
|
|
|
859
847
|
"manifest",
|
|
860
848
|
"compatibility",
|
|
861
849
|
"itemCatalog",
|
|
862
|
-
"assetArchive",
|
|
863
850
|
"contentIndex",
|
|
864
|
-
"assetReplacement",
|
|
865
851
|
];
|
|
866
852
|
const AUTHOR_KEYS = ["name", "email", "url", "discord", "role"];
|
|
867
853
|
/**
|
|
@@ -2611,23 +2597,6 @@ function normalizeRelationships(value) {
|
|
|
2611
2597
|
}
|
|
2612
2598
|
spec.itemCatalog = rel.itemCatalog;
|
|
2613
2599
|
}
|
|
2614
|
-
// Opt-in, sibling to `itemCatalog`: unpack this dependency's
|
|
2615
|
-
// release archive for its asset bytes alone, building no item
|
|
2616
|
-
// catalogue from it. Buys the archive for a package with no
|
|
2617
|
-
// items of its own to extract — an asset-replacement source
|
|
2618
|
-
// ships no Item packs and has no use for `itemCatalog: true`.
|
|
2619
|
-
if (rel.assetArchive !== undefined) {
|
|
2620
|
-
if (typeof rel.assetArchive !== "boolean") {
|
|
2621
|
-
fail(`${at}.assetArchive`, "must be true or false");
|
|
2622
|
-
}
|
|
2623
|
-
if (rel.assetArchive && spec.manifest === undefined) {
|
|
2624
|
-
fail(
|
|
2625
|
-
`${at}.assetArchive`,
|
|
2626
|
-
"needs a `manifest` naming the package to fetch",
|
|
2627
|
-
);
|
|
2628
|
-
}
|
|
2629
|
-
spec.assetArchive = rel.assetArchive;
|
|
2630
|
-
}
|
|
2631
2600
|
// Opt-out: declares the dependency for the Foundry manifest
|
|
2632
2601
|
// only, so `deps fetch` fetches no content index for it and a
|
|
2633
2602
|
// wikilink into it is refused rather than silently dead. A
|
|
@@ -2646,26 +2615,6 @@ function normalizeRelationships(value) {
|
|
|
2646
2615
|
}
|
|
2647
2616
|
spec.contentIndex = rel.contentIndex;
|
|
2648
2617
|
}
|
|
2649
|
-
// Opt-in: this dependency's asset tree answers this
|
|
2650
|
-
// package's own asset addresses ahead of its local record —
|
|
2651
|
-
// the "rewrite table" `engine/asset-replacement.mjs` reads.
|
|
2652
|
-
// A replacement with no fetched index to check against
|
|
2653
|
-
// resolves nothing, so it cannot pair with
|
|
2654
|
-
// `contentIndex: false`.
|
|
2655
|
-
if (rel.assetReplacement !== undefined) {
|
|
2656
|
-
if (typeof rel.assetReplacement !== "boolean") {
|
|
2657
|
-
fail(`${at}.assetReplacement`, "must be true or false");
|
|
2658
|
-
}
|
|
2659
|
-
if (rel.assetReplacement && rel.contentIndex === false) {
|
|
2660
|
-
fail(
|
|
2661
|
-
`${at}.assetReplacement`,
|
|
2662
|
-
"cannot be true together with `contentIndex: false` — a " +
|
|
2663
|
-
"replacement with no fetched index to check against resolves " +
|
|
2664
|
-
"nothing",
|
|
2665
|
-
);
|
|
2666
|
-
}
|
|
2667
|
-
spec.assetReplacement = rel.assetReplacement;
|
|
2668
|
-
}
|
|
2669
2618
|
return Object.freeze(spec);
|
|
2670
2619
|
}),
|
|
2671
2620
|
);
|
package/docs/api.md
CHANGED
|
@@ -2624,14 +2624,15 @@ occupies one line and the file ends with a newline.
|
|
|
2624
2624
|
`@heroiclands/package-build/engine/dictionary-layout` renders SQL results as
|
|
2625
2625
|
Markdown for the dictionary or glossary on its owner's note:
|
|
2626
2626
|
|
|
2627
|
-
| Export | Signature | Returns | Use it when
|
|
2628
|
-
| ------------------------- | ------------------------------------ | -------------------------- |
|
|
2629
|
-
| `LAYOUT_REQUIRED_COLUMNS` | `const LAYOUT_REQUIRED_COLUMNS` | Required columns by layout | Checking the columns a dictionary or glossary query must select.
|
|
2630
|
-
| `COMMON_MARK` | `const COMMON_MARK` | `string` | Reading the mark a common glossary entry opens with.
|
|
2631
|
-
| `DICTIONARY_ENTRY_CLASS` | `const DICTIONARY_ENTRY_CLASS` | `string` | Identifying generated headword spans that are native dictionary targets in Foundry.
|
|
2632
|
-
| `
|
|
2633
|
-
| `
|
|
2634
|
-
| `
|
|
2627
|
+
| Export | Signature | Returns | Use it when |
|
|
2628
|
+
| ------------------------- | ------------------------------------ | -------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
2629
|
+
| `LAYOUT_REQUIRED_COLUMNS` | `const LAYOUT_REQUIRED_COLUMNS` | Required columns by layout | Checking the columns a dictionary or glossary query must select. |
|
|
2630
|
+
| `COMMON_MARK` | `const COMMON_MARK` | `string` | Reading the mark a common glossary entry opens with. |
|
|
2631
|
+
| `DICTIONARY_ENTRY_CLASS` | `const DICTIONARY_ENTRY_CLASS` | `string` | Identifying generated headword spans that are native dictionary targets in Foundry. |
|
|
2632
|
+
| `LEXICAL_LINK_CLASS` | `const LEXICAL_LINK_CLASS` | `string` | Identifying the links an entry writes, which a site sets as text where they lead nowhere a reader can reach. |
|
|
2633
|
+
| `dictionaryEntryPlugin` | `dictionaryEntryPlugin(md)` | `void` | Registering native dictionary headword rendering on the Foundry Markdown parser. |
|
|
2634
|
+
| `renderDictionary` | `renderDictionary(result, options?)` | `string` | Rendering a language's words with classes, etymology, senses and citations. |
|
|
2635
|
+
| `renderGlossary` | `renderGlossary(result, options?)` | `string` | Rendering an owner's glossary entries, ranks and offices. |
|
|
2635
2636
|
|
|
2636
2637
|
`result` is `{ columns: string[], rows: object[] }`. Both layouts require
|
|
2637
2638
|
`name`, `senses` and `usage`; a missing column throws an error naming it.
|
|
@@ -2677,6 +2678,11 @@ headword's span and paragraph. `anchorsOf` maps this dictionary target to
|
|
|
2677
2678
|
its containing page's UUID with the word fragment; generic authored spans
|
|
2678
2679
|
keep their containing-page behavior.
|
|
2679
2680
|
|
|
2681
|
+
`LEXICAL_LINK_CLASS` is `"lexical-ref"`. Every link an entry writes to
|
|
2682
|
+
another note, a citation, a headword's link to its dictionary word or a
|
|
2683
|
+
wikilink in a gloss, carries it as an attribute. A site build sets such a link
|
|
2684
|
+
as its text when the target is a page a reader cannot reach.
|
|
2685
|
+
|
|
2680
2686
|
## Automatic dictionary and glossary sections
|
|
2681
2687
|
|
|
2682
2688
|
`@heroiclands/package-build/engine/lexical-sections` derives and inserts the
|
|
@@ -1469,7 +1469,7 @@ A column's heading is its SQL alias, so `AS "Name"` is what a reader sees. A cel
|
|
|
1469
1469
|
| `joining` | One row per entry of a language note's `data.sounds.joining`: `first`, `second`, `written` and `example`. |
|
|
1470
1470
|
| `joins` | One row per entry of a language note's `data.sounds.joins`: `meeting`, `rule`, `letters` and `"where"`. |
|
|
1471
1471
|
| `marks` | One row per entry of a language note's or a spelling guide's `data.sounds.marks`: `mark`, `letters`, `kind` and `"limit"`. |
|
|
1472
|
-
| `skeleton` | One row per entry of a language note's `data.sounds.skeleton`: `second` and `between`.
|
|
1472
|
+
| `skeleton` | One row per entry of a language note's `data.sounds.skeleton`: `second`, `third` and `between`. |
|
|
1473
1473
|
| `frames` | One row per frame of a language note's `data.sounds.frames`: `frame`, `shape`, `class`, `makes` and `examples` as `{ root, form }`. |
|
|
1474
1474
|
| `read_past` | One row per entry of a language note's `data.sounds.readPast`: `written`, `readAs` and `what`. |
|
|
1475
1475
|
| `mutations` | One row per entry of a language note's `data.sounds.mutations`: `mutation`, `sound`, `becomes` and `example`. |
|
package/docs/commands.md
CHANGED
|
@@ -1718,13 +1718,11 @@ package-build deps fetch [--from <zip|dir>] [--id <id>]
|
|
|
1718
1718
|
The only action is `fetch`, which fills three caches under `build/cache/`:
|
|
1719
1719
|
the **content index** of every declared dependency and of every
|
|
1720
1720
|
`recommends` or `conflicts` relationship that declares `itemCatalog: true`,
|
|
1721
|
-
the **item catalogue
|
|
1722
|
-
|
|
1723
|
-
`assetArchive: true`, and the **site navigation** —
|
|
1721
|
+
the **item catalogue** of those that additionally declare `itemCatalog: true`,
|
|
1722
|
+
and the **site navigation** —
|
|
1724
1723
|
`https://www.heroiclands.org/nav.json`, the header menu every package site
|
|
1725
1724
|
renders, fetched for every package because every package publishes a site.
|
|
1726
|
-
|
|
1727
|
-
is fetched once. Its own command rather than a step of `package compile` or
|
|
1725
|
+
Its own command rather than a step of `package compile` or
|
|
1728
1726
|
`site`, so neither reaches the network — a build that downloads silently is
|
|
1729
1727
|
not reproducible and hides a dependency's version change behind a passing
|
|
1730
1728
|
run. Each cache is stamped complete only once its fetch finishes, so a
|
|
@@ -1766,7 +1764,7 @@ including when the repository declares no dependencies at all.
|
|
|
1766
1764
|
```
|
|
1767
1765
|
$ package-build deps fetch
|
|
1768
1766
|
[…] Fetched the site navigation to build/cache/navigation/nav.json.
|
|
1769
|
-
[…] No relationship declares `itemCatalog: true
|
|
1767
|
+
[…] No relationship declares `itemCatalog: true`; nothing to fetch.
|
|
1770
1768
|
[…] This package declares no dependencies.
|
|
1771
1769
|
|
|
1772
1770
|
$ package-build deps fetch --from build/dist/module.zip
|
package/docs/configuration.md
CHANGED
|
@@ -606,7 +606,7 @@ HeroicLands layout, resolved against `rootDir`:
|
|
|
606
606
|
| `paths.packJson` | `build/packs-json` | Build-only per-entry JSON intermediate. |
|
|
607
607
|
| `paths.stage` | `build/stage/packs` | Compiled LevelDB packs. |
|
|
608
608
|
| `paths.unpack` | `build/tmp/packs` | Where `unpack` extracts JSON back to. |
|
|
609
|
-
| `paths.foreignCache` | `build/cache/foreign` | Where a dependency declaring `itemCatalog: true`
|
|
609
|
+
| `paths.foreignCache` | `build/cache/foreign` | Where a dependency declaring `itemCatalog: true` is unpacked. |
|
|
610
610
|
| `paths.metadataCache` | `build/cache/metadata` | Where a published content index is fetched to, for every declared dependency and every relationship declaring `itemCatalog: true`. |
|
|
611
611
|
| `paths.navigationCache` | `build/cache/navigation` | Where the site navigation heroiclands.org publishes is fetched to, for the site's menu. |
|
|
612
612
|
|
|
@@ -1228,7 +1228,7 @@ writes its own `sitemap.xml` whether or not it states this key.
|
|
|
1228
1228
|
```yaml
|
|
1229
1229
|
site:
|
|
1230
1230
|
base: /
|
|
1231
|
-
sitemaps: [sohl, hm3, thalorna, kethira,
|
|
1231
|
+
sitemaps: [sohl, hm3, thalorna, kethira, harnensemble, harnadventures]
|
|
1232
1232
|
```
|
|
1233
1233
|
|
|
1234
1234
|
`site.mergeIndexes` names the package sites, by `contentPackage`, whose search
|
|
@@ -1275,7 +1275,7 @@ site:
|
|
|
1275
1275
|
projects: doc-projects
|
|
1276
1276
|
feed: blog
|
|
1277
1277
|
tags: true
|
|
1278
|
-
sitemaps: [sohl, hm3, thalorna, kethira,
|
|
1278
|
+
sitemaps: [sohl, hm3, thalorna, kethira, harnensemble, harnadventures]
|
|
1279
1279
|
mergeIndexes: [sohl, thalorna, kethira, harnensemble]
|
|
1280
1280
|
```
|
|
1281
1281
|
|
|
@@ -1645,17 +1645,15 @@ system relationship it declares — see [`stats.systemVersion`](#statssystemvers
|
|
|
1645
1645
|
|
|
1646
1646
|
Each entry, in any of the four lists:
|
|
1647
1647
|
|
|
1648
|
-
| Key (under `relationships.<kind>[]`)
|
|
1649
|
-
|
|
|
1650
|
-
| `relationships.systems[].id`
|
|
1651
|
-
| `relationships.systems[].contentPackage`
|
|
1652
|
-
| `relationships.systems[].type`
|
|
1653
|
-
| `relationships.systems[].manifest`
|
|
1654
|
-
| `relationships.systems[].compatibility`
|
|
1655
|
-
| `relationships.systems[].itemCatalog`
|
|
1656
|
-
| `relationships.systems[].
|
|
1657
|
-
| `relationships.systems[].contentIndex` | boolean | no | `true` |
|
|
1658
|
-
| `relationships.systems[].assetReplacement` | boolean | no | `false` |
|
|
1648
|
+
| Key (under `relationships.<kind>[]`) | Type | Required | Default |
|
|
1649
|
+
| ---------------------------------------- | ------------------------------- | -------- | ------- |
|
|
1650
|
+
| `relationships.systems[].id` | string | yes | — |
|
|
1651
|
+
| `relationships.systems[].contentPackage` | string | no | the id |
|
|
1652
|
+
| `relationships.systems[].type` | string | no | none |
|
|
1653
|
+
| `relationships.systems[].manifest` | string | no | none |
|
|
1654
|
+
| `relationships.systems[].compatibility` | object, `{minimum?, verified?}` | no | none |
|
|
1655
|
+
| `relationships.systems[].itemCatalog` | boolean | no | `false` |
|
|
1656
|
+
| `relationships.systems[].contentIndex` | boolean | no | `true` |
|
|
1659
1657
|
|
|
1660
1658
|
(the same keys apply under `requires[]`, `recommends[]` and
|
|
1661
1659
|
`conflicts[]`.)
|
|
@@ -1664,7 +1662,7 @@ Each entry, in any of the four lists:
|
|
|
1664
1662
|
|
|
1665
1663
|
> ``package-build config: `relationships.<kind>[<index>].id` must be a non-empty string.``
|
|
1666
1664
|
|
|
1667
|
-
> ``package-build config: `relationships.<kind>[<index>].<key>` is not a recognized option (expected one of: id, contentPackage, type, manifest, compatibility, itemCatalog,
|
|
1665
|
+
> ``package-build config: `relationships.<kind>[<index>].<key>` is not a recognized option (expected one of: id, contentPackage, type, manifest, compatibility, itemCatalog, contentIndex).``
|
|
1668
1666
|
|
|
1669
1667
|
`contentPackage` names what the other package's _content_ is called, where
|
|
1670
1668
|
that differs from its Foundry id. A note addresses a file by the content
|
|
@@ -1685,31 +1683,6 @@ embedded-item addresses the compile does. It requires a `manifest`:
|
|
|
1685
1683
|
|
|
1686
1684
|
> ``package-build config: `relationships.<kind>[<index>].itemCatalog` needs a `manifest` naming the package to fetch.``
|
|
1687
1685
|
|
|
1688
|
-
`assetArchive` opts into unpacking the named package's release archive for
|
|
1689
|
-
its asset bytes alone — the sibling of `itemCatalog`, for a dependency whose
|
|
1690
|
-
bytes are wanted and whose items are not. It builds no item catalogue from
|
|
1691
|
-
the archive, which is what distinguishes it from `itemCatalog: true`. It
|
|
1692
|
-
requires a `manifest`:
|
|
1693
|
-
|
|
1694
|
-
> ``package-build config: `relationships.<kind>[<index>].assetArchive` must be true or false.``
|
|
1695
|
-
|
|
1696
|
-
> ``package-build config: `relationships.<kind>[<index>].assetArchive` needs a `manifest` naming the package to fetch.``
|
|
1697
|
-
|
|
1698
|
-
A relationship with no items of its own to extract, such as an asset
|
|
1699
|
-
replacement module, declares only `assetArchive: true`:
|
|
1700
|
-
|
|
1701
|
-
```yaml
|
|
1702
|
-
relationships:
|
|
1703
|
-
requires:
|
|
1704
|
-
- id: thalornaaltart
|
|
1705
|
-
manifest: https://…/releases/latest/download/module.json
|
|
1706
|
-
compatibility: { verified: "1.0.0" }
|
|
1707
|
-
assetArchive: true
|
|
1708
|
-
```
|
|
1709
|
-
|
|
1710
|
-
A relationship declaring both `itemCatalog: true` and `assetArchive: true` is
|
|
1711
|
-
fetched once: `deps fetch` does not download the archive twice for one entry.
|
|
1712
|
-
|
|
1713
1686
|
`contentIndex` and `itemCatalog` are the two edges a relationship may declare,
|
|
1714
1687
|
and a package may have either without the other. `itemCatalog` says a
|
|
1715
1688
|
dependency supplies _items_; `contentIndex`, `true` by default, says
|
|
@@ -1729,35 +1702,6 @@ demand.
|
|
|
1729
1702
|
|
|
1730
1703
|
> ``package-build config: `relationships.<kind>[<index>].contentIndex` cannot be false together with `itemCatalog: true` — a catalogue is fetched from the same index.``
|
|
1731
1704
|
|
|
1732
|
-
`assetReplacement` opts a relationship into serving this package's own asset
|
|
1733
|
-
addresses from the named dependency's tree instead of its local one —
|
|
1734
|
-
`engine/asset-replacement.mjs`'s `resolveAssetReplacement` is what reads the
|
|
1735
|
-
declaration. Off by default: declaring a dependency is not the same as
|
|
1736
|
-
wanting its pictures in place of the ones this package ships itself. It
|
|
1737
|
-
requires a fetched index to check the replacement against, so it cannot pair
|
|
1738
|
-
with `contentIndex: false`:
|
|
1739
|
-
|
|
1740
|
-
```yaml
|
|
1741
|
-
relationships:
|
|
1742
|
-
requires:
|
|
1743
|
-
- id: thalornaaltart
|
|
1744
|
-
manifest: https://…/releases/latest/download/module.json
|
|
1745
|
-
assetReplacement: true
|
|
1746
|
-
contentIndex: true
|
|
1747
|
-
```
|
|
1748
|
-
|
|
1749
|
-
With that declared, an address `thalorna` would otherwise answer itself —
|
|
1750
|
-
`thalorna-none-image-thorn` — resolves against
|
|
1751
|
-
`thalornaaltart-none-image-thorn` first, falling back to `thalorna`'s own
|
|
1752
|
-
record when `thalornaaltart` carries no file at that address. A package
|
|
1753
|
-
declaring more than one `assetReplacement: true` relationship is tried in
|
|
1754
|
-
the order the relationships are declared, and the first one carrying the
|
|
1755
|
-
address wins.
|
|
1756
|
-
|
|
1757
|
-
> ``package-build config: `relationships.<kind>[<index>].assetReplacement` must be true or false.``
|
|
1758
|
-
|
|
1759
|
-
> ``package-build config: `relationships.<kind>[<index>].assetReplacement` cannot be true together with `contentIndex: false` — a replacement with no fetched index to check against resolves nothing.``
|
|
1760
|
-
|
|
1761
1705
|
### `systems`
|
|
1762
1706
|
|
|
1763
1707
|
**Type:** object (`{id: spec}`) · **Optional** · default `{}`. Refused in a
|
package/docs/guides/site.md
CHANGED
|
@@ -247,7 +247,9 @@ generated after a note's text (Within, Governed by, Governed places,
|
|
|
247
247
|
Chronology, Events, Accounts, What followed, In song and story). Each is drawn
|
|
248
248
|
without a link to a page outside the reachable set, and a section left with
|
|
249
249
|
nothing under it is not drawn. An infobox value that names an unreachable page
|
|
250
|
-
is set as plain text.
|
|
250
|
+
is set as plain text. So is a link in a dictionary or glossary entry, whether
|
|
251
|
+
it names a word's entry, cites a note or sits in a gloss; it does not make its
|
|
252
|
+
target reachable. A link written in prose or produced by a query is kept
|
|
251
253
|
wherever it points, and it is what makes its target reachable.
|
|
252
254
|
|
|
253
255
|
A page that is not reachable is the way to preview a page in place. Write the
|
|
@@ -1026,12 +1026,12 @@ ships as the Foundry module `harn-ensemble`) writing `images/map.webp`:
|
|
|
1026
1026
|
And for the same note writing `sohl/assets/icons/noun/shieldnn.svg`, a file the
|
|
1027
1027
|
system ships and this repository does not hold:
|
|
1028
1028
|
|
|
1029
|
-
| Surface | Address
|
|
1030
|
-
| ----------- |
|
|
1031
|
-
| **Foundry** | `systems/sohl/icons/shieldnn.svg`
|
|
1032
|
-
| **Local** | `assets/icons/noun/shieldnn.svg`, in the `sohl` repository
|
|
1033
|
-
| **Web** | `https://cdn.heroiclands.org/sohl/icons/shieldnn.svg`
|
|
1034
|
-
| **Book** | not carried
|
|
1029
|
+
| Surface | Address |
|
|
1030
|
+
| ----------- | ---------------------------------------------------------- |
|
|
1031
|
+
| **Foundry** | `systems/sohl/icons/shieldnn.svg` |
|
|
1032
|
+
| **Local** | `assets/icons/noun/shieldnn.svg`, in the `sohl` repository |
|
|
1033
|
+
| **Web** | `https://cdn.heroiclands.org/sohl/icons/shieldnn.svg` |
|
|
1034
|
+
| **Book** | not carried |
|
|
1035
1035
|
|
|
1036
1036
|
**The content package name and Foundry id are separate values.**
|
|
1037
1037
|
`harnensemble` is what the content is called, what a note writes, and what the
|
|
@@ -1049,7 +1049,7 @@ does not know still resolves on the website and in the book — those need only
|
|
|
1049
1049
|
the name and the suffix — and has no Foundry address, which is refused rather
|
|
1050
1050
|
than guessed.
|
|
1051
1051
|
|
|
1052
|
-
|
|
1052
|
+
A package whose image files belong to another package's notes can declare
|
|
1053
1053
|
`packageBuild.assets[].bindsTo` on the relevant asset copy. Each file's basename
|
|
1054
1054
|
then acts as a shortcode for the declared package and type. The related
|
|
1055
1055
|
`relationships.requires[].contentIndex` supplies the address index; with that
|
|
@@ -1057,29 +1057,6 @@ index enabled, an asset with no matching note is a located build error. See
|
|
|
1057
1057
|
[asset bindings](../configuration.md#packagebuildstagedir-and-packagebuildassets)
|
|
1058
1058
|
for the configuration and cache requirements.
|
|
1059
1059
|
|
|
1060
|
-
**A package declared as a replacement is carried into the book, from its
|
|
1061
|
-
fetched archive, when it answers the address; every other foreign package
|
|
1062
|
-
stays not carried.** A relationship declaring `assetReplacement: true` names a
|
|
1063
|
-
dependency whose asset tree answers this package's own addresses first — see
|
|
1064
|
-
[`relationships`](../configuration.md#relationships) — and the book is the one
|
|
1065
|
-
surface that otherwise refuses a foreign file outright, so it is the one
|
|
1066
|
-
surface this changes. A `thalorna` note embedding
|
|
1067
|
-
`![[thalornaaltart-none-icon-anvil|An anvil]]` names `thalornaaltart`'s own
|
|
1068
|
-
address, exactly as a note citing `sohl`'s shared bestiary art would; when
|
|
1069
|
-
`thalornaaltart` is declared with `assetReplacement: true` and its fetched
|
|
1070
|
-
archive carries `icon-anvil` under its own package, the book stages that file
|
|
1071
|
-
from the archive instead of printing the caption with no picture. A note
|
|
1072
|
-
citing a different package's own address this way — `sohl`'s bestiary art,
|
|
1073
|
-
say — stays refused exactly as the row above states, because `sohl` was never
|
|
1074
|
-
declared as a replacement: a package answers in place of another only when it
|
|
1075
|
-
opted in, never because its archive happens to carry a file at the same type
|
|
1076
|
-
and shortcode.
|
|
1077
|
-
|
|
1078
|
-
A relationship declaring `assetReplacement: true` whose archive was never
|
|
1079
|
-
fetched is a configuration mistake, not an ordinary unresolved address: the
|
|
1080
|
-
book reports a located error naming the relationship and instructing
|
|
1081
|
-
`package-build deps fetch`, rather than printing a caption with no picture.
|
|
1082
|
-
|
|
1083
1060
|
**The host is configuration.** `site.assets` in `package-build.config.yaml` is
|
|
1084
1061
|
the root the web form is joined onto, and a package-owned image on a page with
|
|
1085
1062
|
none set is an error naming that key.
|
|
@@ -1670,16 +1647,16 @@ An **`Address` field** takes the address with no brackets:
|
|
|
1670
1647
|
```yaml
|
|
1671
1648
|
data:
|
|
1672
1649
|
parents:
|
|
1673
|
-
-
|
|
1650
|
+
- zemorhodhis
|
|
1674
1651
|
seat: tashal
|
|
1675
1652
|
```
|
|
1676
1653
|
|
|
1677
|
-
not `[[
|
|
1654
|
+
not `[[zemorhodhis]]`. The field is declared as an `Address`, so the schema knows
|
|
1678
1655
|
what the value is and reads it as one; brackets are a wikilink's punctuation,
|
|
1679
1656
|
which the reader would have to strip before it could do anything.
|
|
1680
1657
|
|
|
1681
1658
|
A frontmatter value is parsed by the address grammar above, so a single-segment
|
|
1682
|
-
value such as `
|
|
1659
|
+
value such as `zemorhodhis` names the target by its shortcode alone, with every
|
|
1683
1660
|
other segment supplied by the position. Frontmatter is structure rather than
|
|
1684
1661
|
prose: a field value is a reference something else will compile against, and it
|
|
1685
1662
|
should say exactly what it points at.
|
|
@@ -2822,37 +2799,6 @@ and keeps the excluded picture's address in its flag or `data-asset`. A
|
|
|
2822
2799
|
package that leaves out a picture a note references and ships no stand-in of
|
|
2823
2800
|
that type fails the build with an error at the referencing note.
|
|
2824
2801
|
|
|
2825
|
-
##### A declared replacement resolves first
|
|
2826
|
-
|
|
2827
|
-
A package may declare, on a `relationships.<kind>[]` entry, that a
|
|
2828
|
-
dependency's asset tree answers this package's own asset addresses ahead of
|
|
2829
|
-
its local record — `assetReplacement: true` in `package-build.config.yaml`.
|
|
2830
|
-
Once declared, an asset address resolves in this order:
|
|
2831
|
-
|
|
2832
|
-
1. **Every declared replacement, in declaration order.** The package segment
|
|
2833
|
-
of each relationship declaring `assetReplacement: true` is tried in the
|
|
2834
|
-
order those relationships are written, and the first one carrying the
|
|
2835
|
-
address wins.
|
|
2836
|
-
2. **Falling through to the package's own record** when no declared
|
|
2837
|
-
replacement carries the address — the resolution this package already
|
|
2838
|
-
performs with no `assetReplacement` declared at all.
|
|
2839
|
-
|
|
2840
|
-
**This reaches asset types only.** A being, an item or a lore note is never
|
|
2841
|
-
replaced this way, whatever a relationship declares: the rule tests the
|
|
2842
|
-
address's type, not the relationship. A replacement answers only `icon`,
|
|
2843
|
-
`image` and `audio` addresses whose package segment is this package's own; an
|
|
2844
|
-
address naming any other type, or naming a different package, is untouched.
|
|
2845
|
-
|
|
2846
|
-
**A replacement's own output address is never itself looked up against
|
|
2847
|
-
another replacement.** Resolving `thalornaaltart-none-image-thorn` never asks
|
|
2848
|
-
whether something replaces `thalornaaltart` — resolution is a single pass over
|
|
2849
|
-
the declared list, not a chain, which forecloses a cycle by construction.
|
|
2850
|
-
|
|
2851
|
-
This is distinct from a `foreign` lookup, which serves a declared dependency's
|
|
2852
|
-
own content for an address this package's local index does not carry. A
|
|
2853
|
-
replacement is consulted **before** the local address; a foreign lookup only
|
|
2854
|
-
**after** it misses locally.
|
|
2855
|
-
|
|
2856
2802
|
#### A font is not an asset
|
|
2857
2803
|
|
|
2858
2804
|
`assets/fonts` is not a root, and a font has no address.
|
|
@@ -3592,7 +3538,7 @@ for the keys.
|
|
|
3592
3538
|
| `joining` | `data.sounds.joining` | `first` and `second` (lists), `written`, `example` |
|
|
3593
3539
|
| `joins` | `data.sounds.joins` | `meeting`, `rule`, `letters` (a list), `where` |
|
|
3594
3540
|
| `marks` | `data.sounds.marks` | `mark`, `letters` (a list), `kind`, `limit`; a spelling guide's rows too, keyed by the guide |
|
|
3595
|
-
| `skeleton` | `data.sounds.skeleton` | `second` (a list, `[any]` for every other), `between`
|
|
3541
|
+
| `skeleton` | `data.sounds.skeleton` | `second` (a list, `[any]` for every other), `third` (the same), `between` |
|
|
3596
3542
|
| `frames` | `data.sounds.frames` | `frame`, `shape`, `class` (a list), `makes`, `examples` (a list of `{ root, form }`) |
|
|
3597
3543
|
| `read_past` | `data.sounds.readPast` | `written`, `readAs`, `what` |
|
|
3598
3544
|
| `sound_changes` | `data.soundChanges` | One row per step: `position` (the set's), `name`, `from_language`, `to_language`, `takes`, `step_position` (the step's in its set), `step`, `change`, `where` |
|
|
@@ -6272,10 +6218,11 @@ SoHL sets `system.quantity` to `1` for each compendium item.
|
|
|
6272
6218
|
| `sounds.marks` | `{ mark, letters, kind, limit }[]` | The marks the language writes on its letters |
|
|
6273
6219
|
| `sounds.marks[].mark` | `string`, required | The mark's name, as `acute` |
|
|
6274
6220
|
| `sounds.marks[].letters` | `string[]`, required | The letters that carry it |
|
|
6275
|
-
| `sounds.marks[].kind` | `stress` or `
|
|
6221
|
+
| `sounds.marks[].kind` | `stress`, `length` or `apart`, required | What it says of its letter |
|
|
6276
6222
|
| `sounds.marks[].limit` | `one` or `any`, required | How many a word may carry |
|
|
6277
|
-
| `sounds.skeleton` | `{ second, between? }[]`
|
|
6223
|
+
| `sounds.skeleton` | `{ second, third?, between? }[]` | The vowel set between a root's second and third consonants |
|
|
6278
6224
|
| `sounds.skeleton[].second` | `string[]` or `any`, required | The second consonants the row holds for; `any` for every other |
|
|
6225
|
+
| `sounds.skeleton[].third` | `string[]` or `any` | The third consonants the row holds for; every third consonant where absent |
|
|
6279
6226
|
| `sounds.skeleton[].between` | `string` | The vowel set between; nothing where absent or empty |
|
|
6280
6227
|
| `sounds.frames` | `{ frame, shape, class, makes, examples? }[]` | The patterns a root is set in |
|
|
6281
6228
|
| `sounds.frames[].frame` | `string`, required | The frame's name, which a word's `frame` names |
|
|
@@ -6917,10 +6864,11 @@ closed list where its values are words:
|
|
|
6917
6864
|
- `joins`: what happens where a consonant or a vowel meets another (`C+C`,
|
|
6918
6865
|
`V+C`, `V+V`): `merge`, `insert` the `letters` between, `drop` the first, or
|
|
6919
6866
|
`double` the consonant, everywhere or `where` stated.
|
|
6920
|
-
- `marks`: the marks written on letters, each saying `stress` or `
|
|
6867
|
+
- `marks`: the marks written on letters, each saying `stress`, `length`, or `apart` (the mark sets a vowel to be said apart from its neighbour, as a diaeresis does), and
|
|
6921
6868
|
whether a word carries `one` at most or `any`.
|
|
6922
6869
|
- `skeleton`: the vowel set between a root's second and third consonants, by
|
|
6923
|
-
the second consonant
|
|
6870
|
+
the second consonant and, where a row states `third`, the third; nothing
|
|
6871
|
+
where none is stated.
|
|
6924
6872
|
- `frames`: the patterns a root is set in, each with its shape, the word
|
|
6925
6873
|
classes it makes, what it makes, and the form each root takes in it.
|
|
6926
6874
|
- `mutations`: the sounds a word changes where a named mutation holds — a stop
|
|
@@ -7108,7 +7056,7 @@ data:
|
|
|
7108
7056
|
tongue: [skill-tantsoulng, skill-jurthatlng],
|
|
7109
7057
|
}
|
|
7110
7058
|
marks:
|
|
7111
|
-
- { mark: diaeresis, letters: [ë], kind:
|
|
7059
|
+
- { mark: diaeresis, letters: [ë], kind: apart, limit: any }
|
|
7112
7060
|
```
|
|
7113
7061
|
|
|
7114
7062
|
A guide declares no tags, so a letter row's `tongue` names language notes by
|
|
@@ -8311,7 +8259,7 @@ Content prepared to be played — a situation with its cast, places, and possibl
|
|
|
8311
8259
|
| `sounds.marks` | `{ mark, letters, kind, limit }[]` | The marks written on the letters, each row's keys as a language note's `sounds.marks` |
|
|
8312
8260
|
| `sounds.marks[].mark` | `string`, required | The mark's name, as `acute` |
|
|
8313
8261
|
| `sounds.marks[].letters` | `string[]`, required | The letters that carry it |
|
|
8314
|
-
| `sounds.marks[].kind` | `stress` or `
|
|
8262
|
+
| `sounds.marks[].kind` | `stress`, `length` or `apart`, required | What it says of its letter |
|
|
8315
8263
|
| `sounds.marks[].limit` | `one` or `any`, required | How many a word may carry |
|
|
8316
8264
|
|
|
8317
8265
|
A setting guide introduces one culture's view of the setting, so it names that
|
|
@@ -631,10 +631,11 @@ These fields are accepted by every note type. A field's value can still be irrel
|
|
|
631
631
|
| `data.sounds.marks` | list of `{ mark, letters, kind, limit }` | no | The marks the language writes on its letters. |
|
|
632
632
|
| `data.sounds.marks[].mark` | a string, such as `acute` | yes | The mark's name. |
|
|
633
633
|
| `data.sounds.marks[].letters` | a list of letters | yes | The letters that carry it. |
|
|
634
|
-
| `data.sounds.marks[].kind` | one of stress, length
|
|
634
|
+
| `data.sounds.marks[].kind` | one of stress, length, apart | yes | What the mark says of its letter. |
|
|
635
635
|
| `data.sounds.marks[].limit` | one of one, any | yes | How many a word may carry: `one` at most, or `any`. |
|
|
636
636
|
| `data.sounds.skeleton` | list of `{ second, between? }` | no | The vowel set between a root's second and third consonants. |
|
|
637
637
|
| `data.sounds.skeleton[].second` | a list of sounds, or `any` | yes | The second consonants of a root the row holds for; `any` for every other. |
|
|
638
|
+
| `data.sounds.skeleton[].third` | a list of sounds, or `any` | no | The third consonants of a root the row holds for; every third consonant where absent. |
|
|
638
639
|
| `data.sounds.skeleton[].between` | a vowel, such as `a` | no | The vowel set between the second and third consonants; nothing where absent. |
|
|
639
640
|
| `data.sounds.frames` | list of `{ frame, shape, class, makes, examples? }` | no | The patterns a root is set in. |
|
|
640
641
|
| `data.sounds.frames[].frame` | a string, such as `bare` | yes | The frame's name, which a word's `frame` names. |
|
|
@@ -1026,7 +1027,7 @@ Lore records in-world knowledge. A `culture` describes a people; a `custom` desc
|
|
|
1026
1027
|
| `data.sounds.marks` | list of `{ mark, letters, kind, limit }` | no | The marks the language writes on its letters. |
|
|
1027
1028
|
| `data.sounds.marks[].mark` | a string, such as `acute` | yes | The mark's name. |
|
|
1028
1029
|
| `data.sounds.marks[].letters` | a list of letters | yes | The letters that carry it. |
|
|
1029
|
-
| `data.sounds.marks[].kind` | one of stress, length
|
|
1030
|
+
| `data.sounds.marks[].kind` | one of stress, length, apart | yes | What the mark says of its letter. |
|
|
1030
1031
|
| `data.sounds.marks[].limit` | one of one, any | yes | How many a word may carry: `one` at most, or `any`. |
|
|
1031
1032
|
| `data.map.name` | string | yes | What `map=` names the map by: lowercase letters, digits and `-`, unique in the package. |
|
|
1032
1033
|
| `data.map.logographic` | `true` | no | The script writes meanings: a mapped run's words are written by the language's lexicon alone, and the rows write only the text between them. |
|
|
@@ -172,6 +172,7 @@ const SCRIPT_BLOCKS = Object.freeze([
|
|
|
172
172
|
[0xf0000, 0xf2fff], // plane 15: Pirzath, Thuravark, Semaron, the reserved alphabets, Teng Chou
|
|
173
173
|
[0x1e960, 0x1ec6f], // Zethu overflow, Qalezu, Zethu
|
|
174
174
|
[0x1ecc0, 0x1ecff], // Qalezu catch-before forms
|
|
175
|
+
[0x1ed50, 0x1ed7f], // Veldikko
|
|
175
176
|
[0x13430, 0x1345f], // the Egyptian format controls Zethu uses
|
|
176
177
|
]);
|
|
177
178
|
|