@heroiclands/package-build 21.1.0 → 22.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 +245 -0
- package/CONTENT.md +107 -3
- package/assets/fonts/libertinus/LibertinusMono-Regular.otf +0 -0
- package/assets/fonts/libertinus/LibertinusSans-Bold.otf +0 -0
- package/assets/fonts/libertinus/LibertinusSans-Italic.otf +0 -0
- package/assets/fonts/libertinus/LibertinusSans-Regular.otf +0 -0
- package/assets/fonts/libertinus/OFL.txt +94 -0
- package/assets/fonts/libertinus/provenance.yaml +11 -0
- package/assets/images/banners/afflictionbnr.webp +0 -0
- package/assets/images/banners/armorclothingbnr.webp +0 -0
- package/assets/images/banners/attributebnr.webp +0 -0
- package/assets/images/banners/containerbnr.webp +0 -0
- package/assets/images/banners/devdocsbnr.webp +0 -0
- package/assets/images/banners/miscgearbnr.webp +0 -0
- package/assets/images/banners/mysticalabilitybnr.webp +0 -0
- package/assets/images/banners/projectilebnr.webp +0 -0
- package/assets/images/banners/rulesbnr.webp +0 -0
- package/assets/images/banners/skillbnr.webp +0 -0
- package/assets/images/banners/traumabnr.webp +0 -0
- package/assets/images/banners/userguidebnr.webp +0 -0
- package/assets/images/banners/weapongearbnr.webp +0 -0
- package/assets/images/provenance.yaml +4 -0
- package/bin/content-build.mjs +19 -5
- package/bin/package-build.mjs +6 -5
- package/ci/emit-asset-index.mjs +32 -0
- package/content-config.mjs +30 -1
- package/docs/api.md +103 -27
- package/docs/commands.md +13 -11
- package/docs/configuration.md +16 -7
- package/docs/content-format.md +523 -111
- package/engine/actor-compiler.mjs +58 -9
- package/engine/art-fields.mjs +292 -0
- package/engine/asset-index.mjs +397 -0
- package/engine/asset-types.mjs +192 -0
- package/engine/base-compiler.mjs +69 -1
- package/engine/bundles.mjs +5 -5
- package/engine/compile-corpus.mjs +4 -0
- package/engine/content-address.mjs +14 -2
- package/engine/content-charset.mjs +5 -1
- package/engine/content-embeds.mjs +314 -0
- package/engine/content-html.mjs +5 -1
- package/engine/content-icons.mjs +5 -1
- package/engine/content-images.mjs +26 -5
- package/engine/content-index.mjs +68 -33
- package/engine/content-links.mjs +164 -24
- package/engine/dependency-bump.mjs +14 -16
- package/engine/frontmatter-lint.mjs +36 -23
- package/engine/helpers.mjs +83 -31
- package/engine/index-records.mjs +63 -4
- package/engine/index.mjs +15 -0
- package/engine/infobox-registry.mjs +50 -3
- package/engine/infobox.mjs +12 -8
- package/engine/item-compiler.mjs +10 -10
- package/engine/journals.mjs +3 -0
- package/engine/macros.mjs +16 -13
- package/engine/map-notes.mjs +29 -22
- package/engine/metadata-index.mjs +44 -36
- package/engine/note-vocabulary.mjs +71 -29
- package/engine/pack-router.mjs +14 -0
- package/engine/packagebuild-index.mjs +124 -0
- package/engine/packages.mjs +83 -0
- package/engine/pathnames.mjs +74 -0
- package/engine/pdf-build.mjs +133 -8
- package/engine/pdf-render.mjs +49 -12
- package/engine/scenes.mjs +12 -9
- package/engine/site-build.mjs +43 -16
- package/engine/site-index.mjs +10 -1
- package/engine/subtype-registry.mjs +21 -0
- package/engine/web-wikilinks.mjs +46 -12
- package/engine/wikilink-syntax.mjs +20 -2
- package/engine/wikilinks.mjs +15 -2
- package/hm3/actors.mjs +11 -38
- package/manifest.mjs +67 -13
- package/package.json +5 -2
- package/packagebuild-metadata.jsonl +13 -0
- package/sohl/actors.mjs +12 -86
- package/sohl/note-schemas.mjs +4 -16
- package/types/content-config.d.mts +8 -0
- package/types/engine/actor-compiler.d.mts +29 -0
- package/types/engine/art-fields.d.mts +192 -0
- package/types/engine/asset-index.d.mts +92 -0
- package/types/engine/asset-types.d.mts +110 -0
- package/types/engine/base-compiler.d.mts +42 -1
- package/types/engine/compile-corpus.d.mts +4 -1
- package/types/engine/content-charset.d.mts +4 -0
- package/types/engine/content-embeds.d.mts +218 -0
- package/types/engine/content-html.d.mts +4 -0
- package/types/engine/content-icons.d.mts +4 -0
- package/types/engine/content-images.d.mts +15 -2
- package/types/engine/content-index.d.mts +27 -15
- package/types/engine/dependency-bump.d.mts +2 -2
- package/types/engine/frontmatter-lint.d.mts +11 -14
- package/types/engine/helpers.d.mts +7 -2
- package/types/engine/index-records.d.mts +44 -3
- package/types/engine/index.d.mts +5 -0
- package/types/engine/infobox-registry.d.mts +36 -1
- package/types/engine/infobox.d.mts +6 -4
- package/types/engine/macros.d.mts +9 -5
- package/types/engine/map-notes.d.mts +10 -6
- package/types/engine/metadata-index.d.mts +2 -17
- package/types/engine/note-vocabulary.d.mts +30 -0
- package/types/engine/packagebuild-index.d.mts +56 -0
- package/types/engine/packages.d.mts +62 -0
- package/types/engine/pathnames.d.mts +41 -81
- package/types/engine/pdf-build.d.mts +58 -1
- package/types/engine/pdf-render.d.mts +3 -1
- package/types/engine/scenes.d.mts +2 -1
- package/types/engine/site-build.d.mts +5 -1
- package/types/engine/site-index.d.mts +4 -1
- package/types/engine/subtype-registry.d.mts +20 -0
- package/types/engine/web-wikilinks.d.mts +14 -4
- package/types/engine/wikilink-syntax.d.mts +13 -1
- package/types/engine/wikilinks.d.mts +7 -1
- package/types/manifest.d.mts +42 -1
- package/types/sohl/actors.d.mts +0 -1
package/docs/content-format.md
CHANGED
|
@@ -107,11 +107,11 @@ the key is **machinery**, steering a build or an interface rather than
|
|
|
107
107
|
describing the subject, or it is an **image**, which rule 2 keeps out of the
|
|
108
108
|
box:
|
|
109
109
|
|
|
110
|
-
| key
|
|
111
|
-
|
|
|
112
|
-
| `templatePriority`
|
|
113
|
-
| `color`
|
|
114
|
-
|
|
|
110
|
+
| key | why it carries no row |
|
|
111
|
+
| ------------------------ | ------------------------------------------------ |
|
|
112
|
+
| `templatePriority` | template machinery, not a fact about the subject |
|
|
113
|
+
| `color` | sidebar machinery, not a fact about the subject |
|
|
114
|
+
| the art slots, `overlay` | an image, which rule 2 keeps out of the box |
|
|
115
115
|
|
|
116
116
|
A field whose value is a **mapping** carries no row either — a governance
|
|
117
117
|
ladder or a wall layout has no summary shape — and neither does one the note
|
|
@@ -196,6 +196,15 @@ A system that does not map the note's type gets **no box**. A box reading
|
|
|
196
196
|
_Not available_ on every affiliation page would suggest a gap in the note when
|
|
197
197
|
the truth is about the system's scope.
|
|
198
198
|
|
|
199
|
+
Whether a document was produced is the compile's own answer rather than a
|
|
200
|
+
reading of the frontmatter. The note's type must map to the system; the note
|
|
201
|
+
must route to a pack of the document class that map names; and where **that
|
|
202
|
+
pack declares a `system:`**, the note must carry that system's block, which is
|
|
203
|
+
the same rule the pack itself compiles under. A pack declaring **no** system
|
|
204
|
+
compiles every note it claims from `data:` and the field defaults, so a note
|
|
205
|
+
with no block still produces a document and its box still carries content —
|
|
206
|
+
which is the ordinary arrangement in a package built for one system.
|
|
207
|
+
|
|
199
208
|
#### Four section layouts
|
|
200
209
|
|
|
201
210
|
A section says how it is arranged, and a renderer switches on that and on a
|
|
@@ -506,7 +515,7 @@ type.
|
|
|
506
515
|
| shared source | → sohl | → hm3 |
|
|
507
516
|
| ----------------------- | ------------------------- | ---------------------------- |
|
|
508
517
|
| `name.full` | `name` | `name` |
|
|
509
|
-
| `
|
|
518
|
+
| `data.icon` | `img` | `img` |
|
|
510
519
|
| `id` | `_id` | `_id` |
|
|
511
520
|
| `packFolder` | `folder` | `folder` |
|
|
512
521
|
| `shortcode` | `system.shortcode` | NA |
|
|
@@ -520,23 +529,30 @@ no SoHL form, so its SoHL column is. Nothing else varies — which is why these
|
|
|
520
529
|
rows are worth stating once: repeated sixteen times they buried the differences
|
|
521
530
|
that matter.
|
|
522
531
|
|
|
523
|
-
**`
|
|
524
|
-
is shared because the key is legal on every note whatever its type, not
|
|
525
|
-
every document carries artwork: `doc`, `place`, `lore` and `scenario`
|
|
526
|
-
into a JournalEntry, which has no image of any kind, and a `folder`
|
|
527
|
-
a Foundry `Folder`, which has none either. A `homepage` compiles
|
|
528
|
-
compendium document at all. On any of those the mapping has no
|
|
529
|
-
|
|
530
|
-
value goes nowhere.
|
|
532
|
+
**`data.icon` maps onto a document that has one, and not every type's does.**
|
|
533
|
+
The row is shared because the key is legal on every note whatever its type, not
|
|
534
|
+
because every document carries artwork: `doc`, `place`, `lore` and `scenario`
|
|
535
|
+
compile into a JournalEntry, which has no image of any kind, and a `folder`
|
|
536
|
+
compiles into a Foundry `Folder`, which has none either. A `homepage` compiles
|
|
537
|
+
into no compendium document at all. On any of those the mapping has no
|
|
538
|
+
destination, so the resolved value is simply dropped — the note validates, the
|
|
539
|
+
tree compiles, and the value goes nowhere.
|
|
540
|
+
|
|
541
|
+
**What a note writes is an address; what a document carries is a path.**
|
|
542
|
+
`data.icon` is a `WikiLink` defaulting to type `icon`, so a being writes
|
|
543
|
+
`icon: anvil` and never a file name. The compiler resolves that address to the
|
|
544
|
+
file the owning package ships and writes the resulting path into `img`. The two
|
|
545
|
+
sides of this row are therefore in two different currencies, which is why the
|
|
546
|
+
row reads `data.icon → img` rather than naming one thing twice.
|
|
531
547
|
|
|
532
548
|
Since a dropped value looks exactly like a value never written, the frontmatter
|
|
533
|
-
lint **reports it**: an
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
549
|
+
lint **reports it**: an art key authored on a type whose passes emit none is a
|
|
550
|
+
warning naming the note and the key. A warning rather than an error, because the
|
|
551
|
+
note still compiles correctly and the key is not certainly unwanted — a note's
|
|
552
|
+
top level is the generated page's front matter as well, so a site template may
|
|
553
|
+
read there what no document carries. `null` is never reported: that is the
|
|
554
|
+
blessed way to say "this note names no art", and on a type with no art it is a
|
|
555
|
+
true and harmless thing to say.
|
|
540
556
|
|
|
541
557
|
Which types those are is **not a list**. It is asked of the passes: a type routes
|
|
542
558
|
to a document, a document to the pass that compiles it, and each pass declares
|
|
@@ -544,29 +560,85 @@ the art it writes (`emitsArt`). A second table of iconless types would be a tabl
|
|
|
544
560
|
free to drift from what is actually emitted, which is the defect rather than the
|
|
545
561
|
check.
|
|
546
562
|
|
|
547
|
-
|
|
563
|
+
#### The four art slots
|
|
564
|
+
|
|
565
|
+
A note declares the art its document needs, and every other image in it is
|
|
566
|
+
inline. All four slots are ordinary `WikiLink` fields declaring a default type,
|
|
567
|
+
exactly as `seat` declares `place` — a bare shortcode takes its type from the
|
|
568
|
+
declaration, and qualification climbs the same short-form ladder every other
|
|
569
|
+
link uses.
|
|
570
|
+
|
|
571
|
+
| field | default type | resolves into | on |
|
|
572
|
+
| ----------- | ------------ | ---------------------------- | ----------------------------------------- |
|
|
573
|
+
| `icon` | `icon` | `document.img` | every Actor/Item type, and embedded items |
|
|
574
|
+
| `tokenIcon` | `icon` | `prototypeToken.texture.src` | Actor types |
|
|
575
|
+
| `bgImage` | `image` | `background.src` | map types |
|
|
576
|
+
| `banner` | `image` | the site hero image | any note; not a Foundry field |
|
|
577
|
+
|
|
578
|
+
All four are authored under `data:`:
|
|
579
|
+
|
|
580
|
+
```yaml
|
|
581
|
+
data:
|
|
582
|
+
icon: anvil
|
|
583
|
+
banner: packagebuild-none-image-skillbnr
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Two of them are legal on _every_ note**, whatever its type. `data:` is a
|
|
587
|
+
closed container and the per-type vocabularies below are the only lists there
|
|
588
|
+
are, so a key legal everywhere is stated once here rather than repeated in
|
|
589
|
+
twenty-five tables where the one that was mistyped would be the one nobody
|
|
590
|
+
noticed:
|
|
591
|
+
|
|
592
|
+
| shared `data` property | Values | Description |
|
|
593
|
+
| ---------------------- | ---------- | -------------------------------------------------------------------- |
|
|
594
|
+
| `icon` | `WikiLink` | The document's profile art — an `icon` address, resolved into `img`. |
|
|
595
|
+
| `banner` | `WikiLink` | The page's hero image — an `image` address. |
|
|
548
596
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
597
|
+
`icon` is legal everywhere because most types compile into a document that
|
|
598
|
+
carries one; where a type's passes emit none, the lint says so and the value is
|
|
599
|
+
left alone, because a page template may still read it. `banner` reaches no
|
|
600
|
+
compiled document at all, and a page is what every note publishes.
|
|
552
601
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
602
|
+
The other two are narrower, and each type's own table names them: `tokenIcon`
|
|
603
|
+
on the Actor types, `bgImage` on a map.
|
|
604
|
+
|
|
605
|
+
**A portrait is not one of them.** A picture of the subject is a picture, so it
|
|
606
|
+
is authored in the prose that describes the subject, as an ordinary embedded
|
|
607
|
+
image — see [the lead image](#the-lead-image). A slot exists for art a
|
|
608
|
+
_document field_ needs; nothing else earns one.
|
|
609
|
+
|
|
610
|
+
**A reference carries no slashes and no extension.** That is what keeps it from
|
|
611
|
+
being read as a file name, and it is checked: a value shaped like a pathname is
|
|
612
|
+
an error naming the note and the key.
|
|
613
|
+
|
|
614
|
+
`tokenIcon` unset defaults to `icon`. A token has to read at grid scale and when
|
|
615
|
+
a map is zoomed out, so it is an `icon` rather than an `image`, and its fallback
|
|
616
|
+
has to be `icon`-typed too.
|
|
617
|
+
|
|
618
|
+
Actor types (`being`, `vehicle`) therefore add one row:
|
|
619
|
+
|
|
620
|
+
| shared source | → sohl | → hm3 |
|
|
621
|
+
| ---------------- | ---------------------------- | ---------------------------- |
|
|
622
|
+
| `data.tokenIcon` | `prototypeToken.texture.src` | `prototypeToken.texture.src` |
|
|
623
|
+
|
|
624
|
+
An actor's two pieces of art are two different questions. `data.icon` is the
|
|
625
|
+
profile art — what a directory listing shows beside the name and what the sheet
|
|
626
|
+
header carries. `data.tokenIcon` is what a token on the canvas wears. Both are
|
|
627
|
+
wikilinks and both resolve the same way; only the destination differs. An Item
|
|
628
|
+
has one piece of art, so this row applies to actor types alone.
|
|
560
629
|
|
|
561
630
|
**A `data:` source is still read at the top level, for now.** `data:` did
|
|
562
|
-
not invent the facts it holds — it gathered them out of the top level
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
631
|
+
not invent the facts it holds — it gathered them out of the top level — so every
|
|
632
|
+
key it collected has a **pre-`data:` spelling** that is read after the declared
|
|
633
|
+
one and reported as retiring. This is the shared level's counterpart to the
|
|
634
|
+
in-block `<system>.<key>` retirement, and the two are separate: a note may have
|
|
635
|
+
moved one and not the other.
|
|
636
|
+
|
|
637
|
+
**No image key is one of those.** A top-level `img:` is not authored at all:
|
|
638
|
+
`data.icon` is a different key holding a different kind of value, and a note
|
|
639
|
+
writing `img:` is naming a file where an address belongs. `portrait:` is not
|
|
640
|
+
relocated either, at any level — a portrait is an embed in the body, and the
|
|
641
|
+
key that used to declare one is not a key.
|
|
570
642
|
|
|
571
643
|
**Two of the eight are Item-only in SoHL.** `actionDefs` and `notes` are declared
|
|
572
644
|
on every SoHL Item subtype and on no SoHL Actor, so on a `being` or a `vehicle`
|
|
@@ -607,9 +679,9 @@ shipped tree, and the one piece every derived form is built from. A pathname
|
|
|
607
679
|
that does not open `<package>/assets/` belongs to the package being compiled,
|
|
608
680
|
and the whole of it is the suffix.
|
|
609
681
|
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
|
|
682
|
+
```markdown
|
|
683
|
+
 <!-- this package's -->
|
|
684
|
+
 <!-- the sohl package's -->
|
|
613
685
|
```
|
|
614
686
|
|
|
615
687
|
The four forms, for a `thalorna` note (the `thalorna` package ships as the
|
|
@@ -676,39 +748,28 @@ whole `assets/` tree and the directory names inside it are its own business:
|
|
|
676
748
|
`sohl-kethira-basic` keeps art under `assets/artwork/`, and `artwork/deity.webp`
|
|
677
749
|
is that package's by the same rule that claims `icons/…` and `images/…`.
|
|
678
750
|
|
|
679
|
-
**
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
751
|
+
**Where a pathname is still authored, it follows this rule.** That is the
|
|
752
|
+
address of an image in a note's body, and a map note's `overlay`. The art
|
|
753
|
+
fields do not: `icon`, `tokenIcon`, `bgImage` and `banner` name
|
|
754
|
+
addresses, and the path comes from the record the resolved address points at —
|
|
755
|
+
which already carries the owning package, so there is nothing for a first
|
|
756
|
+
segment to state.
|
|
684
757
|
|
|
685
|
-
|
|
686
|
-
stating plainly, because the two fields look alike and a value written for one
|
|
687
|
-
resolves somewhere else entirely under the other.
|
|
758
|
+
#### `banner:` reaches no compiled document
|
|
688
759
|
|
|
689
|
-
`banner
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
and **anything else is prefixed with `images/`** and joined onto
|
|
694
|
-
`params.cdnBaseURL`. A `banner:` written to the package rule therefore resolves
|
|
695
|
-
to a doubled path:
|
|
760
|
+
`data.banner` is the page's hero image, and it is the one art slot with no
|
|
761
|
+
Foundry destination: searching a built `packs-json` tree for it turns up
|
|
762
|
+
nothing. It reaches the generated page and the book's section plates, and
|
|
763
|
+
nothing else.
|
|
696
764
|
|
|
697
|
-
|
|
698
|
-
banner:
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
That can be made to work by mirroring the path on the CDN, and one consumer
|
|
703
|
-
does exactly that — but it is not what the author meant.
|
|
765
|
+
It is a `WikiLink` all the same, defaulting to type `image`, so a section note
|
|
766
|
+
writes `banner: skillbnr` and a note borrowing another package's plate writes
|
|
767
|
+
`banner: packagebuild-none-image-skillbnr`. The resolved record carries the
|
|
768
|
+
owning package, and each surface joins the suffix onto its own root — the site
|
|
769
|
+
onto `site.assets`, the book onto the directory it stages banners into.
|
|
704
770
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
from it. `banner:` names a hero image on the site's own asset host, reaches no
|
|
708
|
-
compiled document and no book, and is resolved by the theme rather than by this
|
|
709
|
-
toolchain — `banner: none` is not even a target. Write a `banner:` relative to
|
|
710
|
-
the CDN's `images/` root — `banners/lore.webp`, not `images/banners/lore.webp`
|
|
711
|
-
and not a package-qualified pathname.
|
|
771
|
+
**`banner: null` is how a note says it wants no plate.** It is a true statement
|
|
772
|
+
on any type, and the frontmatter lint never reports it.
|
|
712
773
|
|
|
713
774
|
#### The pack a note compiles into
|
|
714
775
|
|
|
@@ -1060,7 +1121,7 @@ free-form value decides the headings there.
|
|
|
1060
1121
|
|
|
1061
1122
|
### WikiLinks
|
|
1062
1123
|
|
|
1063
|
-
|
|
1124
|
+
Many fields in the tables below take a `WikiLink`, and a link is written
|
|
1064
1125
|
`[[target]]` or `[[target|label]]`. The target is an **address**.
|
|
1065
1126
|
|
|
1066
1127
|
#### The canonical address
|
|
@@ -1311,6 +1372,249 @@ Brackets belong in prose, where a link sits inside a sentence and needs marking
|
|
|
1311
1372
|
off from the words around it. A frontmatter value has nothing to be marked off
|
|
1312
1373
|
from.
|
|
1313
1374
|
|
|
1375
|
+
### Assets are types
|
|
1376
|
+
|
|
1377
|
+
`icon`, `image` and `audio` are types in the type vocabulary, and an address
|
|
1378
|
+
reaches one exactly as it reaches a being or a skill. Their trees are
|
|
1379
|
+
the one thing about them that differs: they sit beside `content/` rather than
|
|
1380
|
+
inside it, because the thing a note is addressing is a file rather than a note.
|
|
1381
|
+
|
|
1382
|
+
**Three roots, one per type.** The directory is named for what it holds and the
|
|
1383
|
+
type is named for what an address reaches, so the two differ by a letter and the
|
|
1384
|
+
mapping is declared rather than derived from the name:
|
|
1385
|
+
|
|
1386
|
+
| root | type |
|
|
1387
|
+
| --------------- | ------- |
|
|
1388
|
+
| `assets/icons` | `icon` |
|
|
1389
|
+
| `assets/images` | `image` |
|
|
1390
|
+
| `assets/audio` | `audio` |
|
|
1391
|
+
|
|
1392
|
+
**A file's extension decides whether it is an asset at all**, and its root
|
|
1393
|
+
decides which type. Every image-extensioned file anywhere under `assets/icons`
|
|
1394
|
+
is an icon, and every audio-extensioned file under `assets/audio` is an audio
|
|
1395
|
+
asset, however deep it sits.
|
|
1396
|
+
|
|
1397
|
+
That filter is load-bearing rather than tidy-minded: `provenance.yaml` files
|
|
1398
|
+
live **inside** these roots, at any level, and a walk that took every file would
|
|
1399
|
+
read attribution records as assets. A directory under `assets/` that is not one
|
|
1400
|
+
of the four holds no addressable asset — `assets/ui` is a package's own
|
|
1401
|
+
furniture, and nothing addresses it.
|
|
1402
|
+
|
|
1403
|
+
**An asset type carries no system.** Its addresses keep the fourth segment, and
|
|
1404
|
+
it is always `none` — `sohl-none-icon-anvil`, never `sohl-icon-anvil` — so key
|
|
1405
|
+
parsing stays uniform across every type. The path shape is a property of the
|
|
1406
|
+
type rather than a test on a value.
|
|
1407
|
+
|
|
1408
|
+
#### The filename is the shortcode
|
|
1409
|
+
|
|
1410
|
+
```text
|
|
1411
|
+
assets/icons/game-icons/lorc/anvil.svg → <package>-none-icon-anvil
|
|
1412
|
+
assets/images/beings/creatures/drake.webp → <package>-none-image-drake
|
|
1413
|
+
```
|
|
1414
|
+
|
|
1415
|
+
**The extension is not part of the address**, and neither are the directories
|
|
1416
|
+
above the file. A root's shortcodes are one flat namespace however deeply the
|
|
1417
|
+
tree nests, so two files under one root sharing a basename are two claims on one
|
|
1418
|
+
address and a build error naming both. Across roots they are no such thing:
|
|
1419
|
+
`icon-anvil` and `image-anvil` are different addresses.
|
|
1420
|
+
|
|
1421
|
+
Leaving the extension out is what makes a format change free. Changing an icon
|
|
1422
|
+
from SVG to WebP is dropping a different file in place, and no note changes;
|
|
1423
|
+
`abysdrksvg` and `abysdrkwebp` would be two addresses for one drake.
|
|
1424
|
+
|
|
1425
|
+
**Beneath the root the structure is arbitrary, exactly as it is under
|
|
1426
|
+
`assets/content`.** A note's address does not depend on where its `.md` sits,
|
|
1427
|
+
and an asset's address does not depend on where its file sits within its root.
|
|
1428
|
+
Both trees are arranged for the people who maintain them —
|
|
1429
|
+
`icons/game-icons/<contributor>/`, `images/beings/creatures/` — and either can be
|
|
1430
|
+
rearranged wholesale without a single reference changing.
|
|
1431
|
+
|
|
1432
|
+
**That freedom is the point.** Whoever maintains a tree organises it however
|
|
1433
|
+
makes sense to them — by contributor, by subject, by the source a set came from,
|
|
1434
|
+
by whatever the next thousand files want — and the build has no opinion. A
|
|
1435
|
+
layout that carried meaning would spend that freedom to buy nothing: moving a
|
|
1436
|
+
file would become a breaking change, and the arrangement would answer to the
|
|
1437
|
+
walk rather than to the person reading it.
|
|
1438
|
+
|
|
1439
|
+
**The root itself is the exception, and only because an asset root is
|
|
1440
|
+
homogeneous.** `assets/content` is mixed: it holds beings, places, skills and
|
|
1441
|
+
the rest side by side, and each note declares its own `type:`, so no directory
|
|
1442
|
+
needs to. An asset root holds one type and nothing else — everything under
|
|
1443
|
+
`assets/icons` is an icon — which is what lets the root supply the type. It has
|
|
1444
|
+
to: a `.webp` carries no frontmatter and has nowhere to say what it is.
|
|
1445
|
+
|
|
1446
|
+
So the two trees follow one rule about layout and differ on exactly one point:
|
|
1447
|
+
a note's type comes from the note, an asset's type comes from its root. That is
|
|
1448
|
+
also why the three roots are a closed list rather than a convention — a fourth
|
|
1449
|
+
directory under `assets/` declares nothing, so nothing in it is addressable.
|
|
1450
|
+
`assets/ui` and `assets/fonts` fall out of that rule rather than needing an
|
|
1451
|
+
exemption.
|
|
1452
|
+
|
|
1453
|
+
**A shortcode is lowercase alphanumerics.** A filename that is not — a version
|
|
1454
|
+
string, a hyphen, a date stamp — cannot be addressed, and the build says so
|
|
1455
|
+
rather than inventing a shortcode for it.
|
|
1456
|
+
|
|
1457
|
+
#### The asset record
|
|
1458
|
+
|
|
1459
|
+
An asset reaches the content index as a record of its own — one line per
|
|
1460
|
+
addressable file, in the same JSON Lines index the notes publish into. It
|
|
1461
|
+
carries no frontmatter, no anchors and no `foundry` block: a file declares
|
|
1462
|
+
nothing about itself, compiles into no document, and publishes no page, so the
|
|
1463
|
+
`address` holds the canonical key and no page slug.
|
|
1464
|
+
|
|
1465
|
+
| `asset` field | Source | What it says |
|
|
1466
|
+
| ------------- | ---------- | ------------------------------------------------------------------ |
|
|
1467
|
+
| `path` | the walk | Where the file sits inside the emitting package's asset directory. |
|
|
1468
|
+
| `attribution` | provenance | Who made the file, or what tool generated it. |
|
|
1469
|
+
| `source` | provenance | Where it came from — a URL, or a sentence. |
|
|
1470
|
+
| `license` | provenance | The licence it is used under — an SPDX identifier, or terms. |
|
|
1471
|
+
| `notes` | provenance | Anything else a person reading the attribution needs. |
|
|
1472
|
+
|
|
1473
|
+
Every field is present on every record, blank where nothing states one. A fixed
|
|
1474
|
+
shape is what lets a consumer read `asset.license` without first asking whether
|
|
1475
|
+
the package happened to record one.
|
|
1476
|
+
|
|
1477
|
+
**`path` is what makes resolution one step.** The record is emitted by the
|
|
1478
|
+
package holding the bytes, so the path is that package's path and each consumer
|
|
1479
|
+
joins its own root onto it:
|
|
1480
|
+
|
|
1481
|
+
| Consumer | `thalorna-none-image-thorn` resolves to |
|
|
1482
|
+
| -------- | ------------------------------------------------------------------ |
|
|
1483
|
+
| Web | `<cdn base>/thalorna/images/beings/characters/thorn.webp` |
|
|
1484
|
+
| Book | `<asset base>/thalorna/images/beings/characters/thorn.webp` |
|
|
1485
|
+
| Foundry | `modules/sohl-thalorna/assets/images/beings/characters/thorn.webp` |
|
|
1486
|
+
|
|
1487
|
+
Foundry names a **Foundry package id** rather than a content package, because
|
|
1488
|
+
the two are distinct — they are equal in the system only by coincidence, and in
|
|
1489
|
+
`sohl-thalorna` they differ.
|
|
1490
|
+
|
|
1491
|
+
##### Where provenance comes from
|
|
1492
|
+
|
|
1493
|
+
A `provenance.yaml` states `attribution`, `source`, `license` and `notes`, and
|
|
1494
|
+
nothing else: an unknown key is a finding rather than a silent drop, because
|
|
1495
|
+
`licence` beside `license` is otherwise an attribution record that looks
|
|
1496
|
+
complete and carries nothing.
|
|
1497
|
+
|
|
1498
|
+
One address resolves its record in this order:
|
|
1499
|
+
|
|
1500
|
+
1. A sibling `<filename.ext>.yaml`, which **replaces** an inherited record
|
|
1501
|
+
wholesale rather than merging over it. A sidecar exists precisely because the
|
|
1502
|
+
inherited answer is wrong for this one file, so carrying half of it forward
|
|
1503
|
+
would make the record's meaning depend on a directory two levels up.
|
|
1504
|
+
2. Otherwise the nearest `provenance.yaml`, searching the file's own directory
|
|
1505
|
+
and then its ancestors, **stopping at the type root**. A record above the root
|
|
1506
|
+
would speak for trees it says nothing about.
|
|
1507
|
+
3. Otherwise nothing, and the provenance fields are blank. A package that
|
|
1508
|
+
records no attribution is a fact to state, not a walk to fail.
|
|
1509
|
+
|
|
1510
|
+
#### A font is not an asset
|
|
1511
|
+
|
|
1512
|
+
`assets/fonts` is not a root, and a font has no address.
|
|
1513
|
+
|
|
1514
|
+
**An asset type exists so a note can name a file and a package can substitute
|
|
1515
|
+
it.** Nothing about a font answers to either half. No note names a typeface —
|
|
1516
|
+
the art slots are `icon`, `tokenIcon`, `bgImage` and `banner` — and substituting
|
|
1517
|
+
one package's font for another's is not something anyone wants.
|
|
1518
|
+
|
|
1519
|
+
**Neither consumer of a font can use an address.** A stylesheet names a file
|
|
1520
|
+
with `url()`, resolved relative to the stylesheet and never through the content
|
|
1521
|
+
index. The book names a _family_ — `#set text(font: "Libertinus Serif")` — and
|
|
1522
|
+
the typesetter matches that against a directory it is pointed at. One wants a
|
|
1523
|
+
relative path, the other a family name; an address serves neither.
|
|
1524
|
+
|
|
1525
|
+
**And the model fits badly.** An address holds one file whose format is free to
|
|
1526
|
+
change, which suits a picture. A font family is a matrix of family, weight and
|
|
1527
|
+
style, and a filename already says which cell a file is — a shortcode would have
|
|
1528
|
+
to re-encode that, worse.
|
|
1529
|
+
|
|
1530
|
+
So fonts stay ordinary files a package ships and points a tool at, and their
|
|
1531
|
+
licences are recorded where a person reads them rather than in an index.
|
|
1532
|
+
|
|
1533
|
+
#### `icon` and `image` are two types, not one
|
|
1534
|
+
|
|
1535
|
+
An icon has to stay coherent drawn into a 32×32 slot, which is why icons are
|
|
1536
|
+
SVG. An image is unbounded, expected to be large, and unreadable at that size.
|
|
1537
|
+
That is a fitness property of the asset itself, and one merged type would leave
|
|
1538
|
+
every consumer inferring the handling from the extension; two types let a guard
|
|
1539
|
+
assert it instead.
|
|
1540
|
+
|
|
1541
|
+
So the two have **separate shortcode namespaces**. `icon-anvil` and
|
|
1542
|
+
`image-anvil` are different addresses for different purposes, and a rewrite rule
|
|
1543
|
+
reaches one without touching the other.
|
|
1544
|
+
|
|
1545
|
+
**An asset address is its own name.** `image-thorn` is an image called `thorn`;
|
|
1546
|
+
any resemblance to `being-thorn` is coincidence, and nothing derives one from
|
|
1547
|
+
the other.
|
|
1548
|
+
|
|
1549
|
+
#### `packagebuild` is a reserved package name
|
|
1550
|
+
|
|
1551
|
+
package-build is an npm package rather than a system or a module, and it ships
|
|
1552
|
+
a set of images — section banners chiefly — that many packages draw on.
|
|
1553
|
+
Addressing them as `packagebuild-none-image-<shortcode>` lets a note reach one
|
|
1554
|
+
without declaring a dependency on some parent system or module it otherwise has
|
|
1555
|
+
no relationship with.
|
|
1556
|
+
|
|
1557
|
+
**Its files reach the website and the book and no Foundry document.** Foundry
|
|
1558
|
+
installs no package of that name and no relationship can be declared with one,
|
|
1559
|
+
so `banner:` — the one art slot with no Foundry destination — is where a
|
|
1560
|
+
`packagebuild` address belongs. A body image naming one, written either way, is
|
|
1561
|
+
refused with the line and column it sits on.
|
|
1562
|
+
|
|
1563
|
+
`packagebuild` is therefore **reserved** in the package registry: nothing may
|
|
1564
|
+
create a real package that collides with it, and its resolution is special-cased,
|
|
1565
|
+
because no installed directory sits behind the name.
|
|
1566
|
+
|
|
1567
|
+
#### An embedded image is a wikilink
|
|
1568
|
+
|
|
1569
|
+
```text
|
|
1570
|
+
![[address|label]]
|
|
1571
|
+
```
|
|
1572
|
+
|
|
1573
|
+
There is no image grammar. An embed is the wikilink above, with `!` meaning
|
|
1574
|
+
_render it here_ rather than _link to it_, and the syntax supplying the default
|
|
1575
|
+
type the way a field declaration does — `image`. The short-form ladder, the
|
|
1576
|
+
package and system defaults, the lowercase rule, the ambiguity reporting and the
|
|
1577
|
+
findings vocabulary all apply unchanged.
|
|
1578
|
+
|
|
1579
|
+
| written | means |
|
|
1580
|
+
| ------------------------------ | ---------------------------------------- |
|
|
1581
|
+
| `![[anvil\|]]` | decorative — the common case |
|
|
1582
|
+
| `![[anvil\|An anvil]]` | alt text where it carries meaning |
|
|
1583
|
+
| `![[anvil]]` | unlabelled, and a finding like any other |
|
|
1584
|
+
| `![[sohl-image-anvil\|Anvil]]` | qualified, reaching another package |
|
|
1585
|
+
|
|
1586
|
+
The parser distinguishes a missing label from an empty one, so _deliberately
|
|
1587
|
+
decorative_ and _not written_ differ without an exemption.
|
|
1588
|
+
|
|
1589
|
+
**The label is the alt text, and it stays with the referrer.** One image serves
|
|
1590
|
+
many documents, and only the referrer knows what it means where it sits.
|
|
1591
|
+
|
|
1592
|
+
**An embed reaches asset types only.** The syntax invites the broader reading —
|
|
1593
|
+
transclusion of an arbitrary note — so the restriction is a guard rather than a
|
|
1594
|
+
convention.
|
|
1595
|
+
|
|
1596
|
+
**An embed takes the same directive an image does**, in the same place —
|
|
1597
|
+
immediately after the closing `]]`, with no space:
|
|
1598
|
+
|
|
1599
|
+
```markdown
|
|
1600
|
+
![[branwldrgr|Brànwâal Dôrgaar]]{float: top-left}
|
|
1601
|
+
![[thalornamap|Map of Thalorna]]{.full-width}
|
|
1602
|
+
![[thalornamap|Map of Thalorna]]{.full-width, float: top-left}
|
|
1603
|
+
![[thalornamap|Map of Thalorna]]{float: top-left, .full-width}
|
|
1604
|
+
```
|
|
1605
|
+
|
|
1606
|
+
**The same parser reads both**, so an embed takes a width class, a `float:`, or
|
|
1607
|
+
both together in either order, comma-separated — everything
|
|
1608
|
+
[an image's directive](#width-is-a-class-and-the-ordinary-width-carries-no-marker)
|
|
1609
|
+
takes and nothing beyond it. The width and position vocabularies are the ones
|
|
1610
|
+
above, and they are closed here for the same reason: a directive that is quietly
|
|
1611
|
+
ignored looks exactly like one that worked, and a directive holding a problem is
|
|
1612
|
+
not honoured in part either.
|
|
1613
|
+
|
|
1614
|
+
**A being's portrait is one of these**, opening its `{#appearance}` section by
|
|
1615
|
+
convention rather than declared in a field — see
|
|
1616
|
+
[the lead image](#the-lead-image).
|
|
1617
|
+
|
|
1314
1618
|
### What a note produces
|
|
1315
1619
|
|
|
1316
1620
|
Note types fall into two groups, and only the first has a mapping table.
|
|
@@ -1402,7 +1706,7 @@ authored statement, three renderers, which is the single-sourcing every other
|
|
|
1402
1706
|
part of this format follows.
|
|
1403
1707
|
|
|
1404
1708
|
```markdown
|
|
1405
|
-
![Brànwâal Dôrgaar]
|
|
1709
|
+
![[branwldrgr|Brànwâal Dôrgaar]]{float: top-left}
|
|
1406
1710
|
|
|
1407
1711
|
{.full-width}
|
|
1408
1712
|
```
|
|
@@ -1450,8 +1754,17 @@ not. The website and a Foundry journal get true CSS wrap from the same
|
|
|
1450
1754
|
directive. Expect the same statement, not the same page.
|
|
1451
1755
|
|
|
1452
1756
|
An image with no `float:` is an ordinary block in the flow, where it was
|
|
1453
|
-
written. A `.full-width` image is
|
|
1454
|
-
|
|
1757
|
+
written. A `.full-width` image is set at the **top of a new page**: the book is
|
|
1758
|
+
set in two columns, only a float spans them both, and a float is placed where
|
|
1759
|
+
the page has room rather than where it was written — so the page breaks before
|
|
1760
|
+
the picture, and the prose that follows it runs below it on the same page. The
|
|
1761
|
+
picture can therefore never print above the prose that introduces it or after
|
|
1762
|
+
the prose that follows it, at the cost of the page before it ending short. A
|
|
1763
|
+
picture taller than the page takes a page of its own.
|
|
1764
|
+
|
|
1765
|
+
A `.full-width` image that **also states a `float:`** is asking for a float and
|
|
1766
|
+
gets one, with no break before it. A float is placed where it fits, which may be
|
|
1767
|
+
the next page.
|
|
1455
1768
|
|
|
1456
1769
|
##### Both vocabularies are closed
|
|
1457
1770
|
|
|
@@ -1472,12 +1785,18 @@ a scheme of `http:` or `https:`, or none at all.
|
|
|
1472
1785
|
|
|
1473
1786
|
##### Where an address resolves
|
|
1474
1787
|
|
|
1475
|
-
An image's address follows the rule
|
|
1788
|
+
An image's address follows [the pathname rule](#a-pathname-names-the-package-that-owns-the-file)
|
|
1476
1789
|
— its first segment says which package owns the file — and each surface
|
|
1477
1790
|
resolves it to what that surface serves:
|
|
1478
1791
|
|
|
1479
1792
|
- **Foundry** is handed the path inside the install, so `images/map.webp`
|
|
1480
|
-
reaches a journal page as `modules/<package>/assets/images/map.webp`.
|
|
1793
|
+
reaches a journal page as `modules/<package>/assets/images/map.webp`. An
|
|
1794
|
+
address with no such path — a package this build declares no relationship
|
|
1795
|
+
with, or `packagebuild`, which Foundry installs nothing of — is **refused,
|
|
1796
|
+
located by file, line and column**, and the build fails. Foundry is the one
|
|
1797
|
+
surface a correctly written pathname can be dead on while the other two
|
|
1798
|
+
resolve it, and a `src` that resolves against nothing looks exactly like an
|
|
1799
|
+
address that worked.
|
|
1481
1800
|
- **The book** is handed a copy of the file, staged out of this package's own
|
|
1482
1801
|
asset tree into the build directory before the compiler runs. An address
|
|
1483
1802
|
naming a file this package does not ship — another package's, or a URL —
|
|
@@ -1651,7 +1970,6 @@ The following H1 headers are treated specially:
|
|
|
1651
1970
|
For JournalEntries, the following rules apply:
|
|
1652
1971
|
|
|
1653
1972
|
- `# ... {#spoilers}`: The contents of this header go into a page which is viewable only by the GM (`CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE`).
|
|
1654
|
-
- The `portrait` frontmatter property will be added as a new JournalPage of type image with the name "Portrait" and anchor "portrait".
|
|
1655
1973
|
|
|
1656
1974
|
**Archetype** is often used to describe a character in broad terms. These are often useful when determining whether a character matches a particular adventure. The list of character archetypes are:
|
|
1657
1975
|
|
|
@@ -1684,7 +2002,7 @@ Generates a living (or undead, or spirit) being.
|
|
|
1684
2002
|
|
|
1685
2003
|
| `data` property | Values | Description |
|
|
1686
2004
|
| --------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
1687
|
-
| `
|
|
2005
|
+
| `tokenIcon` | `WikiLink` | What a token on the canvas wears — an `icon` address; defaults to `icon` |
|
|
1688
2006
|
| `templatePriority` | `number` | Template priority, _null_ = not a template |
|
|
1689
2007
|
| `archetypes` | `Archetype[]` | What sort of character this is. **Always an array** — `[]` where none apply; `null` is an error. |
|
|
1690
2008
|
| `occupation` | `string` | Name of the character's occupation |
|
|
@@ -1705,6 +2023,45 @@ Generates a living (or undead, or spirit) being.
|
|
|
1705
2023
|
| `appearance.complexion` | `string` | Complexion |
|
|
1706
2024
|
| `appearance.extra_features` | `string[]` | Extra features |
|
|
1707
2025
|
|
|
2026
|
+
#### The lead image
|
|
2027
|
+
|
|
2028
|
+
**A being's portrait is the first thing inside its `{#appearance}` section,
|
|
2029
|
+
always.**
|
|
2030
|
+
|
|
2031
|
+
```markdown
|
|
2032
|
+
# Appearance {#appearance}
|
|
2033
|
+
|
|
2034
|
+
![[<address>|<the being's full name>]]{float: top-left}
|
|
2035
|
+
```
|
|
2036
|
+
|
|
2037
|
+
**Nothing about that embed is special.** It is an ordinary embedded image with
|
|
2038
|
+
an ordinary directive, and no pass treats it differently for sitting where it
|
|
2039
|
+
sits. What is strict is the convention: the portrait opens the appearance
|
|
2040
|
+
section, so a reader opening any being note finds the picture in the same place,
|
|
2041
|
+
and an author writing one never has to decide where it goes.
|
|
2042
|
+
|
|
2043
|
+
**The section is the part that is not a convention.** `{#appearance}` is what
|
|
2044
|
+
becomes an actor's `system.appearance`, so a picture written above that heading
|
|
2045
|
+
is outside the section and reaches no document. The heading carries the anchor
|
|
2046
|
+
at **H1** — a deeper heading is not matched, and its whole section is extracted
|
|
2047
|
+
as empty rather than reported.
|
|
2048
|
+
|
|
2049
|
+
The label is the being's full name. That is what a reader needs when the picture
|
|
2050
|
+
does not load, and what a screen reader announces in its place.
|
|
2051
|
+
|
|
2052
|
+
**There is no `portrait` field**, at any level. A portrait is a picture of the
|
|
2053
|
+
subject, and a picture of the subject belongs in the prose that describes it —
|
|
2054
|
+
where an author can see it, move it, caption it or remove it, as with any other
|
|
2055
|
+
image. A field puts it somewhere only a template can reach, and every template
|
|
2056
|
+
then has to agree about where that is.
|
|
2057
|
+
|
|
2058
|
+
Later images are ordinary images too — a second picture of the being, a coat of
|
|
2059
|
+
arms, a map of its holding — and they sit wherever the prose wants them,
|
|
2060
|
+
including in `{#dossier}`.
|
|
2061
|
+
|
|
2062
|
+
**A being with no portrait writes no lead image.** There is no empty form and no
|
|
2063
|
+
placeholder.
|
|
2064
|
+
|
|
1708
2065
|
#### A being's embedded items
|
|
1709
2066
|
|
|
1710
2067
|
`<system>.items` is a list, and each entry compiles into one embedded Item. An
|
|
@@ -1727,6 +2084,7 @@ sohl:
|
|
|
1727
2084
|
| `model` | yes | The address of the item this entry is a copy of |
|
|
1728
2085
|
| `system` | no | Values that override the model's |
|
|
1729
2086
|
| `name` | no | A name of this entry's own, where it differs from the model's |
|
|
2087
|
+
| `data` | no | Art this entry names — see _An entry's art_ below |
|
|
1730
2088
|
|
|
1731
2089
|
**`type:` is not written beside a `model`.** The address already names the type,
|
|
1732
2090
|
so a second statement of it is a place to be wrong, and it is refused.
|
|
@@ -1761,6 +2119,38 @@ things — and it could not say which package a template came from, so an addres
|
|
|
1761
2119
|
resolved into a dependency only because no local pack claimed it and would have
|
|
1762
2120
|
retargeted silently the day one did.
|
|
1763
2121
|
|
|
2122
|
+
#### An entry's art
|
|
2123
|
+
|
|
2124
|
+
An entry is an item in every respect but where it is written, so it carries art
|
|
2125
|
+
by the two rules [an item note](#the-four-art-slots) does. It names an `icon`
|
|
2126
|
+
address under its own `data:`, and that resolves into the embedded document's
|
|
2127
|
+
`img`:
|
|
2128
|
+
|
|
2129
|
+
```yaml
|
|
2130
|
+
sohl:
|
|
2131
|
+
items:
|
|
2132
|
+
- name: Quiver (leather)
|
|
2133
|
+
type: miscgear
|
|
2134
|
+
data:
|
|
2135
|
+
icon: quiver
|
|
2136
|
+
system:
|
|
2137
|
+
shortcode: quiver
|
|
2138
|
+
```
|
|
2139
|
+
|
|
2140
|
+
`icon` is the only slot an entry has. The other three belong to a note: two
|
|
2141
|
+
describe an Actor or a map, and `banner` is a page's hero image, which an
|
|
2142
|
+
embedded document has no page for.
|
|
2143
|
+
|
|
2144
|
+
**Naming none is the common case, and it takes a default.** An entry copying a
|
|
2145
|
+
`model:` carries the catalogue item's art, and an entry copying nothing takes
|
|
2146
|
+
the default its type pairs in `itemBuilders` — the same default an item note of
|
|
2147
|
+
that type compiles with. An entry naming an address of its own overrides either.
|
|
2148
|
+
Writing `icon: ""` ships the document blank on purpose, and no default replaces
|
|
2149
|
+
it.
|
|
2150
|
+
|
|
2151
|
+
**`data:` reaches no compiled document.** It is where a note names art, and a
|
|
2152
|
+
compiled Item has `img` instead; the container is read and goes no further.
|
|
2153
|
+
|
|
1764
2154
|
#### Identifying a being's embedded items
|
|
1765
2155
|
|
|
1766
2156
|
Each entry in `sohl.items` compiles into one embedded Item, and its `_id` is
|
|
@@ -1827,15 +2217,15 @@ It will also generate a single JournalEntry located at the top level of the "jou
|
|
|
1827
2217
|
|
|
1828
2218
|
Represents a conveyance able to hold goods and people moving from one place to another.
|
|
1829
2219
|
|
|
1830
|
-
| `data` property | Values
|
|
1831
|
-
| ------------------ |
|
|
1832
|
-
| `
|
|
1833
|
-
| `templatePriority` | `number`
|
|
2220
|
+
| `data` property | Values | Description |
|
|
2221
|
+
| ------------------ | ---------- | ------------------------------------------------------------------------ |
|
|
2222
|
+
| `tokenIcon` | `WikiLink` | What a token on the canvas wears — an `icon` address; defaults to `icon` |
|
|
2223
|
+
| `templatePriority` | `number` | Template priority, _null_ = not a template |
|
|
1834
2224
|
|
|
1835
2225
|
If `sohl` is present, this becomes a `vehicle` actor.
|
|
1836
2226
|
|
|
1837
2227
|
It maps nothing beyond the shared rows above, actor row included: a vehicle
|
|
1838
|
-
carries a
|
|
2228
|
+
carries a template priority and no field of its own.
|
|
1839
2229
|
|
|
1840
2230
|
### type: affiliation
|
|
1841
2231
|
|
|
@@ -2525,23 +2915,23 @@ are subTypes of one type rather than three types.
|
|
|
2525
2915
|
|
|
2526
2916
|
The `data:` fields, of which three are required:
|
|
2527
2917
|
|
|
2528
|
-
| `data` property | Values | Description
|
|
2529
|
-
| ----------------- | ---------------- |
|
|
2530
|
-
| `
|
|
2531
|
-
| `dimensions` | `[int, int]` | **Required.** `[width, height]` in whole pixels, the art's own size
|
|
2532
|
-
| `pxPerGrid` | `integer` | **Required.** Whole pixels per grid square; must match the art
|
|
2533
|
-
| `navName` | `string` | Short name for Foundry's scene navigation bar
|
|
2534
|
-
| `levelName` | `string` | The name of the embedded level. Defaults to `Ground`
|
|
2535
|
-
| `backgroundColor` | `ColorHexValue` | Shown where the art does not reach. Defaults to `#999999`
|
|
2536
|
-
| `overlay` | `string` | Path to **foreground** art
|
|
2537
|
-
| `walls` | `WallSegment[]` | List of wall segments
|
|
2538
|
-
| `doors` | `Door[]` | List of doors
|
|
2539
|
-
| `lights` | `Light[]` | List of lights
|
|
2540
|
-
| `tiles` | `Tile[]` | List of tiles
|
|
2541
|
-
| `sounds` | `Sound[]` | List of sounds
|
|
2542
|
-
| `regions` | `SceneRegion[]` | List of scene regions
|
|
2543
|
-
| `place` | `WikiLink` | The place this map depicts. Optional, because an encounter map depicts no named place — but that is the exception, and a map without one is a map of nowhere
|
|
2544
|
-
| `notes` | `NoteLocation[]` | grid coordinates of note markers mapped to anchors in this document
|
|
2918
|
+
| `data` property | Values | Description |
|
|
2919
|
+
| ----------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
2920
|
+
| `bgImage` | `WikiLink` | **Required.** The map art — an `image` address. Becomes the level's `background.src`, what tokens stand on |
|
|
2921
|
+
| `dimensions` | `[int, int]` | **Required.** `[width, height]` in whole pixels, the art's own size |
|
|
2922
|
+
| `pxPerGrid` | `integer` | **Required.** Whole pixels per grid square; must match the art |
|
|
2923
|
+
| `navName` | `string` | Short name for Foundry's scene navigation bar |
|
|
2924
|
+
| `levelName` | `string` | The name of the embedded level. Defaults to `Ground` |
|
|
2925
|
+
| `backgroundColor` | `ColorHexValue` | Shown where the art does not reach. Defaults to `#999999` |
|
|
2926
|
+
| `overlay` | `string` | Path to **foreground** art |
|
|
2927
|
+
| `walls` | `WallSegment[]` | List of wall segments |
|
|
2928
|
+
| `doors` | `Door[]` | List of doors |
|
|
2929
|
+
| `lights` | `Light[]` | List of lights |
|
|
2930
|
+
| `tiles` | `Tile[]` | List of tiles, each naming its art in `image` |
|
|
2931
|
+
| `sounds` | `Sound[]` | List of sounds, each naming its clip in `audio` |
|
|
2932
|
+
| `regions` | `SceneRegion[]` | List of scene regions |
|
|
2933
|
+
| `place` | `WikiLink` | The place this map depicts. Optional, because an encounter map depicts no named place — but that is the exception, and a map without one is a map of nowhere |
|
|
2934
|
+
| `notes` | `NoteLocation[]` | grid coordinates of note markers mapped to anchors in this document |
|
|
2545
2935
|
|
|
2546
2936
|
Everything else a Scene holds is **derived**, not authored: padding, grid type,
|
|
2547
2937
|
grid distance and units, token vision and fog mode all come from the subType, and
|
|
@@ -2554,16 +2944,38 @@ one Level or it has no map at all, and nothing supplies one after the fact: the
|
|
|
2554
2944
|
client-side `_preCreate` that would create it does not run during offline pack
|
|
2555
2945
|
compilation, and the server-side migration shim is version-gated on
|
|
2556
2946
|
`_stats.coreVersion`, so a pack stamped 14.x or later skips it entirely. The
|
|
2557
|
-
single Level is synthesised from `
|
|
2947
|
+
single Level is synthesised from `bgImage`, `overlay`, `levelName` and
|
|
2558
2948
|
`backgroundColor`.
|
|
2559
2949
|
|
|
2560
|
-
> **`
|
|
2561
|
-
> not system-specific — a Scene is a core Foundry document, and a second
|
|
2562
|
-
> would want the identical art — so the field sits
|
|
2563
|
-
>
|
|
2950
|
+
> **`bgImage` is a `WikiLink` under `data:`, as every other type's artwork is.**
|
|
2951
|
+
> Art is not system-specific — a Scene is a core Foundry document, and a second
|
|
2952
|
+
> system would want the identical art — so the field sits under `data:` rather
|
|
2953
|
+
> than inside a system block.
|
|
2564
2954
|
>
|
|
2565
|
-
>
|
|
2566
|
-
>
|
|
2955
|
+
> **A map has no `img`.** `bgImage` is the only key naming a map's background,
|
|
2956
|
+
> and a note writing `img:` or `data.img:` is refused. The two are not
|
|
2957
|
+
> alternative spellings: `img` is a Foundry destination and no Scene has one.
|
|
2958
|
+
|
|
2959
|
+
**Every art key inside a map is an address, and each is named for the type it
|
|
2960
|
+
reaches.** A map's geometry is authored in Foundry's own units, and its art is
|
|
2961
|
+
not authored in Foundry's own paths.
|
|
2962
|
+
|
|
2963
|
+
| authored | default type | emitted as |
|
|
2964
|
+
| -------------------- | ------------ | ---------------------------- |
|
|
2965
|
+
| `data.bgImage` | `image` | the level's `background.src` |
|
|
2966
|
+
| `tiles.<key>.image` | `image` | the tile's `texture.src` |
|
|
2967
|
+
| `sounds.<key>.audio` | `audio` | the `AmbientSound`'s `path` |
|
|
2968
|
+
|
|
2969
|
+
Naming each key for the type it references is what makes the default worth
|
|
2970
|
+
having: `audio:` reaches an `audio` address without a note ever writing the
|
|
2971
|
+
type segment. Where a tile places a glyph rather than artwork it qualifies —
|
|
2972
|
+
`image: sohl-none-icon-chest` — which is the ordinary short-form ladder rather
|
|
2973
|
+
than an exception to it.
|
|
2974
|
+
|
|
2975
|
+
**The authored key and the emitted field differ where Foundry's name differs.**
|
|
2976
|
+
An `AmbientSound` stores its clip in `path`, and that is what the compiled
|
|
2977
|
+
document carries; the note writes `audio` because the note is naming an
|
|
2978
|
+
address, not filling in a Foundry field.
|
|
2567
2979
|
|
|
2568
2980
|
**Two unit conventions, deliberately.** Geometry — walls, doors, lights, tiles,
|
|
2569
2981
|
sounds, region shapes — is authored in **pixels**, Foundry's native storage,
|
|
@@ -2762,8 +3174,8 @@ rules describe it, and compiling one through this path would ship a macro whose
|
|
|
2762
3174
|
body was a code block posted verbatim into chat. Chat macros as content would
|
|
2763
3175
|
need an authoring convention of their own.
|
|
2764
3176
|
|
|
2765
|
-
The note's `
|
|
2766
|
-
|
|
3177
|
+
The note's `data.icon` resolves the way every other note's does; a note that
|
|
3178
|
+
authors none takes Foundry's own `icons/svg/dice-target.svg`.
|
|
2767
3179
|
|
|
2768
3180
|
### type: bundle
|
|
2769
3181
|
|