@heroiclands/package-build 19.0.0 → 20.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +624 -0
- package/CONTENT.md +79 -8
- package/bin/content-build.mjs +7 -1
- package/content-config.mjs +10 -1
- package/docs/content-format.md +394 -72
- package/engine/actor-compiler.mjs +197 -7
- package/engine/address-charset.mjs +23 -5
- package/engine/base-compiler.mjs +63 -2
- package/engine/bundles.mjs +9 -0
- package/engine/content-address.mjs +92 -1
- package/engine/content-format.mjs +102 -0
- package/engine/content-index.mjs +11 -8
- package/engine/content-links.mjs +37 -21
- package/engine/field-reference.mjs +57 -5
- package/engine/field-spec.mjs +214 -7
- package/engine/folder-notes.mjs +24 -1
- package/engine/foreign-catalog.mjs +4 -1
- package/engine/foundry-entries.mjs +14 -0
- package/engine/frontmatter-lint.mjs +186 -27
- package/engine/frontmatter.mjs +11 -11
- package/engine/generate.mjs +67 -10
- package/engine/helpers.mjs +86 -9
- package/engine/index.mjs +3 -0
- package/engine/item-compiler.mjs +37 -0
- package/engine/journals.mjs +21 -4
- package/engine/macros.mjs +8 -0
- package/engine/map-notes.mjs +7 -7
- package/engine/note-ids.mjs +25 -1
- package/engine/note-vocabulary.mjs +76 -9
- package/engine/retired-fields.mjs +57 -16
- package/engine/runtime-only-fields.mjs +204 -0
- package/engine/scenes.mjs +12 -19
- package/engine/schema-check.mjs +23 -1
- package/engine/site-index.mjs +17 -0
- package/engine/subtype-registry.mjs +30 -0
- package/engine/system-block.mjs +81 -3
- package/engine/web-wikilinks.mjs +33 -27
- package/engine/wikilink-syntax.mjs +7 -0
- package/engine/wikilinks.mjs +74 -16
- package/hm3/actors.mjs +63 -13
- package/package.json +2 -2
- package/sohl/actors.mjs +106 -7
- package/sohl/item-fields.mjs +203 -0
- package/sohl/note-schemas.mjs +6 -3
- package/types/engine/actor-compiler.d.mts +83 -3
- package/types/engine/address-charset.d.mts +22 -4
- package/types/engine/base-compiler.d.mts +54 -3
- package/types/engine/content-address.d.mts +64 -0
- package/types/engine/content-format.d.mts +9 -0
- package/types/engine/field-spec.d.mts +271 -3
- package/types/engine/folder-notes.d.mts +20 -0
- package/types/engine/foundry-entries.d.mts +6 -0
- package/types/engine/frontmatter-lint.d.mts +18 -2
- package/types/engine/frontmatter.d.mts +11 -11
- package/types/engine/generate.d.mts +27 -0
- package/types/engine/helpers.d.mts +37 -9
- package/types/engine/index.d.mts +1 -0
- package/types/engine/map-notes.d.mts +2 -2
- package/types/engine/note-ids.d.mts +14 -0
- package/types/engine/retired-fields.d.mts +29 -13
- package/types/engine/runtime-only-fields.d.mts +102 -0
- package/types/engine/schema-check.d.mts +10 -1
- package/types/engine/subtype-registry.d.mts +21 -0
- package/types/engine/system-block.d.mts +28 -2
- package/types/sohl/actors.d.mts +3 -3
package/CONTENT.md
CHANGED
|
@@ -388,6 +388,24 @@ exactly once, here, and read through `loadPackConfig()` everywhere. There is one
|
|
|
388
388
|
resolved set at runtime; the compilers and the link-manifest emitter cannot come
|
|
389
389
|
to disagree about which notes carry documentation.
|
|
390
390
|
|
|
391
|
+
**Every note compiling into a system-bearing document carries documentation, and
|
|
392
|
+
that includes actors** (#337). `docEntryTypes` is `itemTypes` plus the actor
|
|
393
|
+
types the shipped subtype maps declare (`ACTOR_TYPES`, derived from them rather
|
|
394
|
+
than listed again), plus `macro` and the map types. Only `doc` is outside it, for
|
|
395
|
+
the reason that actually applies to it: its single document _is_ the prose.
|
|
396
|
+
|
|
397
|
+
A being therefore has the same two addresses an item has — `<pkg>-<system>-being-<shortcode>`
|
|
398
|
+
for the Actor and `<pkg>-none-docbeing-<shortcode>` for the page — where before
|
|
399
|
+
it had only the first, and was the one system-bearing note a prose link could not
|
|
400
|
+
name.
|
|
401
|
+
|
|
402
|
+
**An actor keeps its prose inline as well, and that asymmetry is deliberate.** An
|
|
403
|
+
item's description is an `@UUID` pointer into its journal, because one item is
|
|
404
|
+
embedded across hundreds of beings and baking long prose into every copy bloats
|
|
405
|
+
the compendium by the length of the text times the number of carriers. An actor
|
|
406
|
+
is singular, so the same indirection costs a reader a click and saves nothing:
|
|
407
|
+
`system.appearance` and `system.dossier` stay as rendered prose.
|
|
408
|
+
|
|
391
409
|
The Item compiler **dispatches through that same resolved table**, via
|
|
392
410
|
`engine/item-registry.mjs` (`itemTypes()` and `itemBuilder(type)`), so the types a
|
|
393
411
|
consumer's notes are accepted for and the builders they compile with are one
|
|
@@ -534,9 +552,46 @@ Both spellings are equal; the difference is only whether the type brings art.
|
|
|
534
552
|
whitelist without a builder behind it.
|
|
535
553
|
|
|
536
554
|
**The path is spelled the way a note spells it.** Registry art goes through the
|
|
537
|
-
same `resolveImg` rule as a note's `img:`, so
|
|
538
|
-
|
|
539
|
-
|
|
555
|
+
same `resolveImg` rule as a note's `img:`, so one spelling means one thing
|
|
556
|
+
wherever it is written.
|
|
557
|
+
|
|
558
|
+
#### An asset path's first segment says which package owns it
|
|
559
|
+
|
|
560
|
+
Every authored asset path — a registry `img:`, a note's `img:`, an actor's
|
|
561
|
+
`portrait:` — answers "which package holds this file?" in its **first segment**,
|
|
562
|
+
and there are exactly three answers:
|
|
563
|
+
|
|
564
|
+
| Authored path starts with | Owner | Emitted |
|
|
565
|
+
| ------------------------- | --------------------- | -------------------- |
|
|
566
|
+
| `systems/` | a separate **system** | unchanged |
|
|
567
|
+
| `modules/` | a separate **module** | unchanged |
|
|
568
|
+
| anything else | **this package** | `<assetRoot>/<path>` |
|
|
569
|
+
|
|
570
|
+
`assetRoot` is derived, never authored: it is
|
|
571
|
+
`<packageKind>/<foundryPackage>/assets`, and it is the one place `systems/sohl`
|
|
572
|
+
(or `modules/sohl-thalorna`) is ever spelled. So `icons/relic.svg` in a module's
|
|
573
|
+
registry compiles to `modules/sohl-relics/assets/icons/relic.svg`, and the same
|
|
574
|
+
string in the system's compiles to `systems/sohl/assets/icons/relic.svg`. An
|
|
575
|
+
already-served `systems/sohl/assets/icons/…` passes through untouched — which is
|
|
576
|
+
what lets a module pair a SoHL default with one of its own types.
|
|
577
|
+
|
|
578
|
+
**"Anything else" is the rule, not a list of directories.** A package owns its
|
|
579
|
+
whole `assets/` tree, so a directory this toolchain has never heard of is still
|
|
580
|
+
that package's: art under `assets/artwork/` is addressed `artwork/deity.webp`
|
|
581
|
+
and rooted exactly as `icons/…` and `images/…` are. An address naming no package
|
|
582
|
+
at all — an absolute URL, a `data:` URI, a `/`-rooted path — passes through, on
|
|
583
|
+
the same rule rather than as an exception.
|
|
584
|
+
|
|
585
|
+
`worlds/` is deliberately not exempt: a package may not ship art out of a world,
|
|
586
|
+
so prefixing such a path produces a plainly broken one rather than a plausible
|
|
587
|
+
one that 404s in Foundry unreported.
|
|
588
|
+
|
|
589
|
+
**`banner:` is a path that does not follow this rule.** It reaches no compiled
|
|
590
|
+
document; it is a top-level key the Hugo theme reads, and the theme prefixes a
|
|
591
|
+
relative value with `images/` and joins it onto `params.cdnBaseURL`. The two
|
|
592
|
+
address different places — `img:` a file Foundry serves, `banner:` a file the
|
|
593
|
+
CDN serves — so they are stated apart rather than reconciled. See the
|
|
594
|
+
[content format specification](docs/content-format.md#banner-addresses-the-cdn-not-the-foundry-install).
|
|
540
595
|
|
|
541
596
|
#### "Names no art" and "wants no art" are different (#218)
|
|
542
597
|
|
|
@@ -570,12 +625,20 @@ rather than two.
|
|
|
570
625
|
> (`sohl/item-fields.mjs`, "the style of address the office carries"), so one
|
|
571
626
|
> authored key fed two unrelated destinations that disagreed about what empty
|
|
572
627
|
> means — and `title: null` stringified into the compiled document as the literal
|
|
573
|
-
> `"null"`.
|
|
574
|
-
>
|
|
628
|
+
> `"null"`. The field declares `topLevelMeans` now, so the top-level key is no
|
|
629
|
+
> longer a source for it (#218).
|
|
630
|
+
>
|
|
631
|
+
> So `title: null` is a note declining to state a heading, and the site emitter's
|
|
632
|
+
> `fm.title ?? name` falls back to `name.full`. `title: ""` publishes a
|
|
633
|
+
> deliberately blank heading and is warned about on its own account — as the
|
|
634
|
+
> page's heading, not as an art path.
|
|
575
635
|
>
|
|
576
|
-
>
|
|
577
|
-
>
|
|
578
|
-
>
|
|
636
|
+
> **That warning reads the note's top level only.** The two spellings still name
|
|
637
|
+
> unrelated quantities, so a `sohl.title` — the office's style of address — must
|
|
638
|
+
> not answer for the page's heading. Twenty-eight `sohl-kethira-basic`
|
|
639
|
+
> affiliations write `sohl.title: ""`, meaning an office with no style of
|
|
640
|
+
> address, and every one of them was reported as publishing a blank heading
|
|
641
|
+
> until the check honoured the declaration (#312).
|
|
579
642
|
|
|
580
643
|
Because `""` used to mean "unset", a note still carrying that spelling has
|
|
581
644
|
quietly changed meaning, and the frontmatter lint says so — for either art
|
|
@@ -712,6 +775,14 @@ state the same quantity, which is nearly everywhere: `subType` is the other
|
|
|
712
775
|
declared item field spelled like a note-level key, and there the two agree by
|
|
713
776
|
design.
|
|
714
777
|
|
|
778
|
+
**The statement is symmetric, and the frontmatter linter reads it from the other
|
|
779
|
+
side too.** If the two positions hold unrelated quantities, then the _in-block_
|
|
780
|
+
position is not the note-level field either — so a check about a note-level field
|
|
781
|
+
(the page's heading, an art path) reads past a block key the note's own type
|
|
782
|
+
claims for something else. Declaring `topLevelMeans` settles both directions at
|
|
783
|
+
once; it was read for the emitted field alone until #312, which is how an
|
|
784
|
+
affiliation's office style came to answer for its page heading.
|
|
785
|
+
|
|
715
786
|
**An exempted field is still authorable**, at the two positions that describe the
|
|
716
787
|
document rather than the note:
|
|
717
788
|
|
package/bin/content-build.mjs
CHANGED
|
@@ -136,7 +136,7 @@ import {
|
|
|
136
136
|
locateAddressFinding,
|
|
137
137
|
addressFindingMessage,
|
|
138
138
|
} from "../engine/address-diff.mjs";
|
|
139
|
-
import { itemPackJsonDirs } from "../engine/generate.mjs";
|
|
139
|
+
import { emittedArtFor, itemPackJsonDirs } from "../engine/generate.mjs";
|
|
140
140
|
|
|
141
141
|
/**
|
|
142
142
|
* The packs `unpack` extracts.
|
|
@@ -799,6 +799,12 @@ function lintCommand() {
|
|
|
799
799
|
// the compile asks the map for whichever pack it is
|
|
800
800
|
// writing, and a companion is a pack it writes.
|
|
801
801
|
packs: config.packDirectories,
|
|
802
|
+
// What art each type actually reaches its document through,
|
|
803
|
+
// asked of the passes rather than listed here (#349). This
|
|
804
|
+
// is the one place that decides what a tree is held to, so
|
|
805
|
+
// it is where the derivation is handed over — the linter
|
|
806
|
+
// states no list of iconless types of its own.
|
|
807
|
+
emittedArt: emittedArtFor,
|
|
802
808
|
references: argv.references,
|
|
803
809
|
});
|
|
804
810
|
|
package/content-config.mjs
CHANGED
|
@@ -69,6 +69,7 @@ import path from "node:path";
|
|
|
69
69
|
// a cycle around a consumer's config file (see `engine/pack-config.mjs`).
|
|
70
70
|
import { ADDRESS_SEGMENT_PATTERN, isAddressSegment } from "./engine/address-charset.mjs";
|
|
71
71
|
import { MAP_TYPES, PACK_BY_TYPE } from "./engine/ids.mjs";
|
|
72
|
+
import { ACTOR_TYPES } from "./engine/subtype-registry.mjs";
|
|
72
73
|
import { NOTE_VOCABULARY } from "./engine/note-vocabulary.mjs";
|
|
73
74
|
|
|
74
75
|
/**
|
|
@@ -1953,7 +1954,15 @@ export function defineConfig(config) {
|
|
|
1953
1954
|
// holds every key any of them declares, so this stays "the registry's keys"
|
|
1954
1955
|
// rather than becoming a second list to keep in step (#1504).
|
|
1955
1956
|
const itemTypes = Object.freeze(new Set(Object.keys(itemBuilders)));
|
|
1956
|
-
|
|
1957
|
+
// Every note that compiles into a *system-bearing* document publishes its
|
|
1958
|
+
// prose as a documentation JournalEntry, and that includes actors (#337).
|
|
1959
|
+
// A being was the one such note with no `none` address — its only address
|
|
1960
|
+
// named the Actor — so nothing a prose link wrote could land on its page.
|
|
1961
|
+
// `doc` stays out for the reason that actually applies to it: its single
|
|
1962
|
+
// document *is* the prose.
|
|
1963
|
+
const docEntryTypes = Object.freeze(
|
|
1964
|
+
new Set([...itemTypes, ...ACTOR_TYPES, "macro", ...MAP_TYPES]),
|
|
1965
|
+
);
|
|
1957
1966
|
|
|
1958
1967
|
return Object.freeze({
|
|
1959
1968
|
rootDir,
|