@heroiclands/package-build 22.21.0 → 22.23.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 +223 -0
- package/assets/styles/content-base.css +162 -0
- package/bin/content-commands.mjs +77 -17
- package/bin/package-build.mjs +15 -2
- package/ci/content-format-reference.mjs +68 -1
- package/config.mjs +26 -0
- package/content-config.mjs +153 -6
- package/docs/api.md +120 -89
- package/docs/authoring/assets.md +14 -0
- package/docs/authoring/dates-and-calendars.md +41 -3
- package/docs/authoring/frontmatter.md +2 -2
- package/docs/authoring/links-and-markup.md +325 -35
- package/docs/commands.md +12 -10
- package/docs/configuration.md +117 -14
- package/docs/content-format.md +4 -2
- package/docs/guides/book.md +5 -4
- package/docs/guides/reference-pages.md +15 -0
- package/docs/reference/format-details.md +545 -104
- package/docs/reference/note-types.md +30 -13
- package/engine/actor-compiler.mjs +23 -0
- package/engine/anchored-sections.mjs +35 -4
- package/engine/anchors.mjs +26 -30
- package/engine/art-fields.mjs +118 -0
- package/engine/art-slots.mjs +7 -1
- package/engine/asset-index.mjs +160 -10
- package/engine/asset-replacement.mjs +93 -0
- package/engine/asset-types.mjs +240 -0
- package/engine/base-compiler.mjs +139 -22
- package/engine/base-styles.mjs +149 -0
- package/engine/bundles.mjs +13 -2
- package/engine/compendiums.mjs +8 -1
- package/engine/content-blocks.mjs +410 -0
- package/engine/content-embeds.mjs +19 -0
- package/engine/content-figures.mjs +468 -0
- package/engine/content-footnotes.mjs +197 -0
- package/engine/content-format-check.mjs +15 -12
- package/engine/content-format.yaml +1 -1
- package/engine/content-images.mjs +126 -25
- package/engine/content-index.mjs +38 -12
- package/engine/content-links.mjs +14 -6
- package/engine/content-tables.mjs +45 -4
- package/engine/content-tasklists.mjs +189 -0
- package/engine/docs-checks.mjs +4 -4
- package/engine/extension-attributes.mjs +48 -2
- package/engine/field-reference.mjs +31 -10
- package/engine/field-spec.mjs +10 -8
- package/engine/foreign-catalog.mjs +143 -18
- package/engine/frontmatter-lint.mjs +120 -65
- package/engine/frontmatter.mjs +3 -3
- package/engine/heading-attributes.mjs +321 -0
- package/engine/helpers.mjs +109 -41
- package/engine/homepage.mjs +8 -8
- package/engine/index.mjs +3 -0
- package/engine/infobox-registry.mjs +4 -1
- package/engine/infobox-render.mjs +15 -3
- package/engine/infobox.mjs +129 -15
- package/engine/itinerary-scenes.mjs +4 -10
- package/engine/journals.mjs +294 -50
- package/engine/lore-events.mjs +197 -0
- package/engine/macros.mjs +1 -1
- package/engine/markdown-expressions.mjs +434 -59
- package/engine/note-dates.mjs +354 -12
- package/engine/note-frontmatter.mjs +7 -16
- package/engine/note-vocabulary.mjs +183 -42
- package/engine/page-lists.mjs +358 -0
- package/engine/pathnames.mjs +36 -0
- package/engine/pdf-build.mjs +431 -74
- package/engine/pdf-images.mjs +64 -0
- package/engine/pdf-render.mjs +563 -66
- package/engine/rank-ladder.mjs +198 -0
- package/engine/reckoning-markers.mjs +1 -1
- package/engine/retired-fields.mjs +8 -13
- package/engine/scenes.mjs +26 -7
- package/engine/site-build.mjs +166 -23
- package/engine/site-config.mjs +10 -1
- package/engine/site-index.mjs +90 -3
- package/engine/site-preview.mjs +20 -7
- package/engine/social-ties.mjs +52 -14
- package/engine/sql-tables.mjs +66 -9
- package/engine/standings.mjs +89 -6
- package/engine/system-block.mjs +56 -30
- package/engine/web-wikilinks.mjs +48 -1
- package/hm3/actors.mjs +8 -5
- package/manifest.mjs +43 -24
- package/package.json +1 -1
- package/packagebuild-metadata.jsonl +13 -13
- package/sohl/actors.mjs +22 -99
- package/sohl/item-fields.mjs +5 -5
- package/sohl/items.mjs +1 -1
- package/sohl/note-schemas.mjs +11 -21
- package/types/config.d.mts +9 -0
- package/types/content-config.d.mts +48 -1
- package/types/engine/actor-compiler.d.mts +11 -0
- package/types/engine/anchored-sections.d.mts +24 -0
- package/types/engine/anchors.d.mts +9 -4
- package/types/engine/art-fields.d.mts +64 -0
- package/types/engine/asset-index.d.mts +43 -0
- package/types/engine/asset-replacement.d.mts +22 -0
- package/types/engine/asset-types.d.mts +18 -0
- package/types/engine/base-compiler.d.mts +19 -17
- package/types/engine/base-styles.d.mts +93 -0
- package/types/engine/content-blocks.d.mts +87 -0
- package/types/engine/content-embeds.d.mts +16 -0
- package/types/engine/content-figures.d.mts +101 -0
- package/types/engine/content-footnotes.d.mts +80 -0
- package/types/engine/content-format-check.d.mts +8 -6
- package/types/engine/content-images.d.mts +78 -12
- package/types/engine/content-index.d.mts +8 -2
- package/types/engine/content-tables.d.mts +12 -4
- package/types/engine/content-tasklists.d.mts +72 -0
- package/types/engine/extension-attributes.d.mts +22 -1
- package/types/engine/field-reference.d.mts +21 -0
- package/types/engine/field-spec.d.mts +20 -16
- package/types/engine/foreign-catalog.d.mts +39 -0
- package/types/engine/frontmatter.d.mts +1 -1
- package/types/engine/heading-attributes.d.mts +179 -0
- package/types/engine/helpers.d.mts +29 -10
- package/types/engine/homepage.d.mts +7 -7
- package/types/engine/index.d.mts +1 -0
- package/types/engine/infobox-registry.d.mts +4 -1
- package/types/engine/infobox-render.d.mts +6 -1
- package/types/engine/infobox.d.mts +6 -0
- package/types/engine/journals.d.mts +41 -12
- package/types/engine/lore-events.d.mts +14 -0
- package/types/engine/markdown-expressions.d.mts +46 -2
- package/types/engine/note-dates.d.mts +64 -1
- package/types/engine/note-frontmatter.d.mts +1 -4
- package/types/engine/note-vocabulary.d.mts +82 -6
- package/types/engine/page-lists.d.mts +126 -0
- package/types/engine/pathnames.d.mts +26 -0
- package/types/engine/pdf-build.d.mts +28 -6
- package/types/engine/pdf-images.d.mts +52 -0
- package/types/engine/pdf-render.d.mts +84 -2
- package/types/engine/rank-ladder.d.mts +32 -0
- package/types/engine/retired-fields.d.mts +4 -6
- package/types/engine/site-build.d.mts +27 -4
- package/types/engine/site-config.d.mts +9 -0
- package/types/engine/site-index.d.mts +67 -1
- package/types/engine/site-preview.d.mts +1 -1
- package/types/engine/sql-tables.d.mts +31 -7
- package/types/engine/standings.d.mts +21 -3
- package/types/engine/system-block.d.mts +37 -14
- package/types/engine/web-wikilinks.d.mts +3 -1
- package/types/hm3/actors.d.mts +21 -3
- package/types/manifest.d.mts +19 -23
- package/types/sohl/actors.d.mts +6 -7
- package/engine/content-admonitions.mjs +0 -114
- package/engine/content-captions.mjs +0 -181
- package/engine/content-secrets.mjs +0 -112
- package/types/engine/content-admonitions.d.mts +0 -24
- package/types/engine/content-captions.d.mts +0 -45
- package/types/engine/content-secrets.d.mts +0 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,228 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 22.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
**Figures**
|
|
8
|
+
|
|
9
|
+
- A picture and the words about it are written as one block: the caption is optional, several pictures can share one, and a border is available.
|
|
10
|
+
- Prose refers to a figure by name, in its own note or in another, and reads back its number, its number and caption, or the caption alone.
|
|
11
|
+
- A figure drawn from a map counts as a Map, numbered the same way on every surface.
|
|
12
|
+
- A figure holding one picture opens as an illustrated page in Foundry, with that viewer's own pop-out and zoom.
|
|
13
|
+
|
|
14
|
+
**Pictures**
|
|
15
|
+
|
|
16
|
+
- A picture carrying no caption draws no line beneath it, on a page, in a journal or in print.
|
|
17
|
+
- A picture states what it is for, and is drawn at the size that choice gives it — never larger than it was made.
|
|
18
|
+
- A page's hero image is 1792×768, and one of any other size is refused, naming the size to cut it to.
|
|
19
|
+
|
|
20
|
+
**Art provenance**
|
|
21
|
+
|
|
22
|
+
- A record saying a file is not machine-generated is published saying so.
|
|
23
|
+
- A package may refuse generated art in its own tree.
|
|
24
|
+
- A package may declare that a dependency's art answers its own addresses, and the book draws the replacement.
|
|
25
|
+
|
|
26
|
+
**Notes**
|
|
27
|
+
|
|
28
|
+
- A lore note states the occasions it records, each with a date and an optional recurrence, and publishes the next one due.
|
|
29
|
+
- A note may write a shared field at the position it is being retired from, and the build accepts it with a warning rather than refusing the note.
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
**Item-frontmatter reference**: regenerating the page no longer renders a broken sentence for `affiliation`'s `title`, which now says plainly that a top-level key is refused outright.
|
|
34
|
+
|
|
35
|
+
## 22.22.0
|
|
36
|
+
|
|
37
|
+
### Minor Changes
|
|
38
|
+
|
|
39
|
+
**Diagnostics**
|
|
40
|
+
|
|
41
|
+
- A dead `#anchor` now fails the website build, matching the compendium build
|
|
42
|
+
and the link checker — a link that used to publish a dead section quietly now
|
|
43
|
+
reports it.
|
|
44
|
+
- A note with more than one problem in its body now reports every one of them
|
|
45
|
+
in a single build, instead of only the first.
|
|
46
|
+
|
|
47
|
+
**The book**
|
|
48
|
+
|
|
49
|
+
- A page link in a book now goes where it says, and one into a package the book
|
|
50
|
+
depends on reaches that package's pages; the address they are built from is
|
|
51
|
+
`package.json`'s `homepage`, which a book now needs.
|
|
52
|
+
- A note written for the next author — a `markdownlint` pragma, an aside about a
|
|
53
|
+
quoted notice — no longer appears on the page.
|
|
54
|
+
- A box written inside a GM-only section prints as a box.
|
|
55
|
+
- A box's title prints as written, emphasis included, and one carrying a bracket,
|
|
56
|
+
a `#` or a `$` no longer stops the book being made.
|
|
57
|
+
- Two captions sharing one id each print their own block once, under their own
|
|
58
|
+
number.
|
|
59
|
+
- A link that resolves nowhere now fails the book build, as it already fails the
|
|
60
|
+
compendium and website builds, and the book is still written so the page
|
|
61
|
+
carrying the link can be found.
|
|
62
|
+
- Markup the book cannot set is reported at the file and line it is written on
|
|
63
|
+
rather than printed on the page, in a title page and a prose file as well as in
|
|
64
|
+
a note.
|
|
65
|
+
- A table query that selects no rows now says so, and names the line, where it
|
|
66
|
+
read `[object Object]`.
|
|
67
|
+
- A link the book cannot resolve names the line and column it is written on.
|
|
68
|
+
|
|
69
|
+
**Affiliations**
|
|
70
|
+
|
|
71
|
+
- A rank with no title or no description is now reported instead of shipping, so
|
|
72
|
+
a member's standing can no longer resolve to a blank on a sheet or a page.
|
|
73
|
+
- A rank level that is not a whole number, and a key a rank does not take, are
|
|
74
|
+
reported too, each naming the line the rank is written on.
|
|
75
|
+
- Every problem on one rank is reported at once, so a ladder is fixed in a single
|
|
76
|
+
pass.
|
|
77
|
+
- A rank needs only its level, title and description; the lore note is for a
|
|
78
|
+
standing that needs more said about it than a description can hold.
|
|
79
|
+
- An affiliation's rank ladder now appears on its page, alongside its offices,
|
|
80
|
+
ordered by level.
|
|
81
|
+
- A note's `lore`, `parents`, `domains` and `economy` lists now reach the page
|
|
82
|
+
wherever they are authored, instead of vanishing silently.
|
|
83
|
+
- A being's entry in a body states the rung it stands on — an ordinary member is
|
|
84
|
+
1, someone cast out is 0 — and an entry that states none is reported.
|
|
85
|
+
- An office is not a rung, so an entry naming a post and no standing is reported
|
|
86
|
+
with the rest of them.
|
|
87
|
+
- A body that gives two rungs one level is reported on the second, so what a
|
|
88
|
+
standing is called does not depend on which rung is written first.
|
|
89
|
+
|
|
90
|
+
**Authoring**
|
|
91
|
+
|
|
92
|
+
- A note's frontmatter accepts only the documented keys; an unrecognised one is an error at its own line, naming every accepted key and the one it was probably meant to be.
|
|
93
|
+
- A page takes its heading from the note's name, so a homepage stating a title any other way publishes the name its package manifest carries.
|
|
94
|
+
- Active Effects and document flags are read from the game-system block that carries them, so a note stating either outside one ships a document without them.
|
|
95
|
+
- Info boxes, warning boxes and captions can be written again: any note using
|
|
96
|
+
one failed its build with an error about a secret block it did not contain.
|
|
97
|
+
- A note may now mix boxes, captions and GM-only sections freely, and a box
|
|
98
|
+
inside a GM-only section stays inside it.
|
|
99
|
+
- A `:::` line that closes nothing says so plainly instead of naming the wrong
|
|
100
|
+
construct.
|
|
101
|
+
- An image may be sized `full-width`, and a float takes a named corner — both
|
|
102
|
+
always worked and neither was written down.
|
|
103
|
+
|
|
104
|
+
**Beings**
|
|
105
|
+
|
|
106
|
+
- A being's complexion can now hold several values, because a face is weathered
|
|
107
|
+
and ruddy at once rather than only one of them.
|
|
108
|
+
- Several of them read as one phrase on a sheet or a page — "weathered, ruddy and
|
|
109
|
+
scarred complexion" — rather than saying the word once per value.
|
|
110
|
+
- A being may be recorded as `nonbinary`, or as having no gender at all, where
|
|
111
|
+
before only `male`, `female` and `other` were named.
|
|
112
|
+
- A frame is `scant`, `light`, `medium`, `heavy` or `massive`. The reference named
|
|
113
|
+
a `heavy` frame `large`, which nothing wrote.
|
|
114
|
+
- A being's body and movement are authored under `sohl.system`, and its
|
|
115
|
+
attributes and skills as `sohl.items` entries; a note writing either
|
|
116
|
+
elsewhere in the block is reported.
|
|
117
|
+
|
|
118
|
+
**Actors**
|
|
119
|
+
|
|
120
|
+
- An `{#appearance}` or `{#dossier}` anchor written on a heading below the top
|
|
121
|
+
level now fails the build naming the file and the line, instead of compiling
|
|
122
|
+
a blank appearance or biography with nothing to say why.
|
|
123
|
+
|
|
124
|
+
**Dates**
|
|
125
|
+
|
|
126
|
+
- A birth or death date written without quotes is reported where a day's
|
|
127
|
+
trailing zero could have been lost, naming both days the value could mean. A
|
|
128
|
+
calendar's epoch and a moon's new day read the same way.
|
|
129
|
+
|
|
130
|
+
**Definition lists**
|
|
131
|
+
|
|
132
|
+
- Every package now ships a definition-list style, so a term and its definition
|
|
133
|
+
line up in two columns with the terms sharing one right edge.
|
|
134
|
+
- A narrow journal window stacks each term above its own definition instead of
|
|
135
|
+
cramping both into columns, and widening the window restores them.
|
|
136
|
+
- A term is bold wherever it appears, so writing one needs no `**` around it.
|
|
137
|
+
- Infobox rows in the book sit against the same right edge, with space between
|
|
138
|
+
rows rather than run together.
|
|
139
|
+
|
|
140
|
+
**Packages**
|
|
141
|
+
|
|
142
|
+
- `packageBuild.baseStyles: false` declines the shared style for a package that
|
|
143
|
+
wants the surface entirely to itself.
|
|
144
|
+
|
|
145
|
+
**Named blocks**
|
|
146
|
+
|
|
147
|
+
- A `:::secret`, `:::info` or `:::warn` block now takes a title of its own, so a
|
|
148
|
+
GM passage can say "For the GM" or "If they ask about the harbour" instead of
|
|
149
|
+
one fixed word.
|
|
150
|
+
- A block also takes an id, classes and other attributes, so a note can link to
|
|
151
|
+
one and a package can style a particular kind its own way.
|
|
152
|
+
- Without a title a block heads itself **Secret**, **Info** or **Warn**. A
|
|
153
|
+
warning that used to head "Warning" now heads "Warn", and a secret that used to
|
|
154
|
+
head "GM note" now heads "Secret"; writing `title="GM note"` keeps the old
|
|
155
|
+
wording.
|
|
156
|
+
- A secret on a web page now opens with its own title rather than the word
|
|
157
|
+
"Spoiler", and carries its kind so a site can style it.
|
|
158
|
+
- A block's colours come from a stylesheet rather than from the block itself,
|
|
159
|
+
so a light panel no longer keeps a light background against dark page text.
|
|
160
|
+
- A misspelled block name is now reported instead of being left in the page as
|
|
161
|
+
the literal `:::name` an author typed.
|
|
162
|
+
- One malformed block no longer stops every other block in the same note from
|
|
163
|
+
rendering.
|
|
164
|
+
- A box written inside a GM-only section stays inside it, and a box inside
|
|
165
|
+
another box says so rather than rendering as a muddle.
|
|
166
|
+
|
|
167
|
+
**Configuration**
|
|
168
|
+
|
|
169
|
+
- A `compatibility.verified` build below the package's own `compatibility.minimum`
|
|
170
|
+
is now reported instead of shipping a manifest that claims a build was verified
|
|
171
|
+
against a floor it cannot install on.
|
|
172
|
+
- The same check applies to a declared system's and a related package's own
|
|
173
|
+
`compatibility`, naming the file and line of the offending `verified`.
|
|
174
|
+
|
|
175
|
+
### Patch Changes
|
|
176
|
+
|
|
177
|
+
**Lists**
|
|
178
|
+
|
|
179
|
+
- A list item opened with `- [ ]` or `- [x]` reads as its own words everywhere
|
|
180
|
+
— on the website, in the compendium, and in the book — never as a checkbox.
|
|
181
|
+
- Writing one that way is reported at its own line, naming the ordinary list
|
|
182
|
+
it belongs in.
|
|
183
|
+
|
|
184
|
+
**Footnotes**
|
|
185
|
+
|
|
186
|
+
- A footnote referenced inside a box or a caption now prints and numbers with
|
|
187
|
+
the rest of the note instead of showing as literal text.
|
|
188
|
+
- A definition written below the top level of a note is reported, as is a
|
|
189
|
+
reference nothing defines.
|
|
190
|
+
- A definition no reference uses is reported rather than dropped from the page.
|
|
191
|
+
|
|
192
|
+
**Named blocks and captions**
|
|
193
|
+
|
|
194
|
+
- A heading that would open a page of its own is reported when it is written
|
|
195
|
+
inside a box or a caption.
|
|
196
|
+
|
|
197
|
+
**Headings**
|
|
198
|
+
|
|
199
|
+
- A heading carrying classes or attributes beside its anchor now anchors on the
|
|
200
|
+
anchor alone, so a link written to it resolves on every surface.
|
|
201
|
+
- A Foundry journal and a web page carry a heading's classes and attributes onto
|
|
202
|
+
the heading, and no surface prints the braces.
|
|
203
|
+
- A heading whose braces hold something other than an attribute block is
|
|
204
|
+
reported at its own line instead of being typeset.
|
|
205
|
+
- `.secret` on the heading that opens a section makes its Foundry page the
|
|
206
|
+
GM's alone.
|
|
207
|
+
- A withheld section reads as a spoiler on the web and a labelled block in the
|
|
208
|
+
book, which conceal it rather than withhold it.
|
|
209
|
+
- A heading refuses `id=`, `class=` and any key beginning `on`, as a named block
|
|
210
|
+
does, so no note writes an event handler onto a page.
|
|
211
|
+
|
|
212
|
+
**Page lists**
|
|
213
|
+
|
|
214
|
+
- A note can now write a page list: name a tag, and the pages carrying it come out as a list of links.
|
|
215
|
+
- The list reaches a reader in Foundry, on the website and in the book alike, from the one directive.
|
|
216
|
+
- A page joins the list by carrying its tag and leaves by losing it, so a landing page stays true as notes are written.
|
|
217
|
+
- A list can print each page's description beside its link, and can be restricted to one note type.
|
|
218
|
+
- A tag that no page carries is reported with the tag it looked for, rather than printing nothing.
|
|
219
|
+
|
|
220
|
+
**Beings**
|
|
221
|
+
|
|
222
|
+
- A being's `socialTies` map now builds without the two findings it always
|
|
223
|
+
produced, so a patron, friend, dependent, acquaintance, rival or nemesis
|
|
224
|
+
can be written.
|
|
225
|
+
|
|
3
226
|
## 22.21.0
|
|
4
227
|
|
|
5
228
|
### Minor Changes
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Song of Heroic Lands (SoHL) system for Foundry VTT.
|
|
3
|
+
* Copyright (c) 2024-2026 Tom Rodriguez ("Toasty") — <toasty@heroiclands.org>
|
|
4
|
+
*
|
|
5
|
+
* This work is licensed under the GNU General Public License v3.0 (GPLv3).
|
|
6
|
+
* You may copy, modify, and distribute it under the terms of that license.
|
|
7
|
+
*
|
|
8
|
+
* For full terms, see the LICENSE.md file in the project root or visit:
|
|
9
|
+
* https://www.gnu.org/licenses/gpl-3.0.html
|
|
10
|
+
*
|
|
11
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* The base stylesheet every package ships, staged into the package root and
|
|
16
|
+
* named first in the manifest's `styles`.
|
|
17
|
+
*
|
|
18
|
+
* It carries only what every package needs for its compiled content to be
|
|
19
|
+
* legible, which today is the definition list: an infobox emits one, and so
|
|
20
|
+
* does the ordinary markdown `Term` / `: definition` syntax. A package keeps
|
|
21
|
+
* its own stylesheet for its own needs and overrides anything here from it.
|
|
22
|
+
*
|
|
23
|
+
* `packageBuild.baseStyles: false` declines it.
|
|
24
|
+
*
|
|
25
|
+
* **The scope is the content, not the interface.** Foundry styles `dl dt` and
|
|
26
|
+
* `dl dd` itself, application-wide, and a package stylesheet loads into a later
|
|
27
|
+
* cascade layer than those rules sit in — so an unscoped `dl` here would
|
|
28
|
+
* restyle every definition list in Foundry's own chrome and in every other
|
|
29
|
+
* package's sheets. The four roots are where compiled content renders: a
|
|
30
|
+
* journal page, a journal entry, an enriched field, and the editor.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* Definition lists, in two states of one style.
|
|
35
|
+
*
|
|
36
|
+
* **Wide.** Two columns, the term right-aligned against a fixed gutter so every
|
|
37
|
+
* term in the list shares one right edge, the definition in the remaining
|
|
38
|
+
* space. The fixed track is what produces the shared edge; a `max-content`
|
|
39
|
+
* track cannot, because each row then sizes itself.
|
|
40
|
+
*
|
|
41
|
+
* **Narrow.** Stacked, the term above its own definition, with space between
|
|
42
|
+
* pairs and none between a term and the definition it belongs to.
|
|
43
|
+
*
|
|
44
|
+
* **The measurement is the list, not the screen.** A Foundry journal is a
|
|
45
|
+
* resizable window, usually far narrower than the viewport, so a viewport media
|
|
46
|
+
* query would hold a journal stacked while the screen said otherwise — or cramp
|
|
47
|
+
* it into two columns at 300px. `container-type: inline-size` on the `dl` and a
|
|
48
|
+
* `@container` query on its children measure the list itself, and give the same
|
|
49
|
+
* two states on a page, in a window and in a sidebar.
|
|
50
|
+
*
|
|
51
|
+
* The narrow state is reached by spanning both tracks rather than by changing
|
|
52
|
+
* the template, because an element cannot query the container it establishes:
|
|
53
|
+
* the `dl` holds the grid and the container, so only `dt` and `dd` can respond.
|
|
54
|
+
* Row spacing is the definition's bottom margin rather than the grid's
|
|
55
|
+
* `row-gap` for the same reason — `row-gap` sits on the `dl`, and the two
|
|
56
|
+
* states need different values.
|
|
57
|
+
*
|
|
58
|
+
* The three tunable values are custom properties, so a package adjusts the term
|
|
59
|
+
* column, the gutter or the stacking point without copying the rule.
|
|
60
|
+
*/
|
|
61
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) dl {
|
|
62
|
+
display: grid;
|
|
63
|
+
/* `minmax(0, …)` keeps the track at its full width wherever there is room
|
|
64
|
+
* and lets it shrink rather than overflow where there is not. */
|
|
65
|
+
grid-template-columns: minmax(0, var(--pb-deflist-term-width, 11rem)) 1fr;
|
|
66
|
+
column-gap: var(--pb-deflist-gutter, 2rem);
|
|
67
|
+
container-type: inline-size;
|
|
68
|
+
container-name: pb-deflist;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) dl > dt {
|
|
72
|
+
grid-column: 1;
|
|
73
|
+
/* The one rule that holds on every surface, so an author writes the term
|
|
74
|
+
* and nothing else rather than bolding it by hand. */
|
|
75
|
+
font-weight: 600;
|
|
76
|
+
text-align: right;
|
|
77
|
+
line-height: 1.6;
|
|
78
|
+
margin: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) dl > dd {
|
|
82
|
+
grid-column: 2;
|
|
83
|
+
margin: 0 0 var(--pb-deflist-row-gap, 1.5rem);
|
|
84
|
+
line-height: 1.6;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) dl > dd:last-child {
|
|
88
|
+
margin-bottom: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* Stacked, below the width two columns need: the term column, the gutter, and
|
|
93
|
+
* enough left for a definition to read as prose rather than as a word per line.
|
|
94
|
+
*
|
|
95
|
+
* Named, so the query resolves against a list this sheet set up rather than
|
|
96
|
+
* against whichever ancestor container happens to be nearest.
|
|
97
|
+
*/
|
|
98
|
+
@container pb-deflist (max-width: 32rem) {
|
|
99
|
+
dt {
|
|
100
|
+
grid-column: 1 / -1;
|
|
101
|
+
text-align: left;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
dd {
|
|
105
|
+
grid-column: 1 / -1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* Named body blocks. `:::info` and `:::warn` emit a `<section>` carrying the
|
|
111
|
+
* block's name as its class, so the appearance belongs here rather than in an
|
|
112
|
+
* inline `style` a consumer cannot override.
|
|
113
|
+
*
|
|
114
|
+
* `secret` is deliberately absent: Foundry styles `section.secret` itself and
|
|
115
|
+
* owns the reveal control on it, and a rule here would fight both.
|
|
116
|
+
*
|
|
117
|
+
* Every colour is a custom property, so a package overrides one from its own
|
|
118
|
+
* sheet without restating the layout.
|
|
119
|
+
*/
|
|
120
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
121
|
+
:is(section.info, section.warn) {
|
|
122
|
+
border-left: 3px solid var(--pb-block-edge);
|
|
123
|
+
background: var(--pb-block-fill);
|
|
124
|
+
color: var(--pb-block-text, inherit);
|
|
125
|
+
padding: 0.5em 0.8em;
|
|
126
|
+
margin: 0.75em 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
130
|
+
:is(section.info, section.warn)
|
|
131
|
+
> strong:first-child {
|
|
132
|
+
color: var(--pb-block-edge);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) section.info {
|
|
136
|
+
--pb-block-edge: #2f6f9f;
|
|
137
|
+
--pb-block-fill: #eef6fb;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) section.warn {
|
|
141
|
+
--pb-block-edge: #9a6700;
|
|
142
|
+
--pb-block-fill: #fff5db;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/*
|
|
146
|
+
* A light panel keeps a dark foreground whatever the surrounding theme does to
|
|
147
|
+
* the inherited colour, because the fill does not follow it.
|
|
148
|
+
*/
|
|
149
|
+
@media (prefers-color-scheme: dark) {
|
|
150
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)
|
|
151
|
+
:is(section.info, section.warn) {
|
|
152
|
+
--pb-block-text: #1b1b1b;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) section.info {
|
|
156
|
+
--pb-block-edge: #1d4f75;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
:is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror) section.warn {
|
|
160
|
+
--pb-block-edge: #7a5100;
|
|
161
|
+
}
|
|
162
|
+
}
|
package/bin/content-commands.mjs
CHANGED
|
@@ -64,12 +64,14 @@ import {
|
|
|
64
64
|
import { fetchNavigation, generateHugoConfig, writeHugoConfig } from "../engine/site-config.mjs";
|
|
65
65
|
import { renderItemFieldReference, renderItemFieldsPage } from "../engine/field-reference.mjs";
|
|
66
66
|
import { checkDocLinks, checkDocIndex } from "../engine/docs-checks.mjs";
|
|
67
|
+
import { checkArtSlotSizes } from "../engine/art-fields.mjs";
|
|
67
68
|
import { lintContentTree } from "../engine/content-lint.mjs";
|
|
68
69
|
import { lintNoteStates } from "../engine/stub-lint.mjs";
|
|
69
70
|
import { lintContentCharset } from "../engine/content-charset.mjs";
|
|
70
71
|
import { lintContentHtml } from "../engine/content-html.mjs";
|
|
71
72
|
import { lintContentIcons } from "../engine/content-icons.mjs";
|
|
72
73
|
import { lintContentImages } from "../engine/content-images.mjs";
|
|
74
|
+
import { lintContentTaskLists } from "../engine/content-tasklists.mjs";
|
|
73
75
|
import {
|
|
74
76
|
declaredSystems,
|
|
75
77
|
lintFrontmatter,
|
|
@@ -108,6 +110,7 @@ import {
|
|
|
108
110
|
authoredFrontmatter,
|
|
109
111
|
emitContentIndex,
|
|
110
112
|
indexRecordsFor,
|
|
113
|
+
isAssetRecord,
|
|
111
114
|
isNoteRecord,
|
|
112
115
|
noteFile,
|
|
113
116
|
} from "../engine/content-index.mjs";
|
|
@@ -138,6 +141,7 @@ import { buildMaps, FROM_ALL, MAP_DIR } from "../engine/map-build.mjs";
|
|
|
138
141
|
import { CHART_HORIZON_DAYS } from "../engine/map-layout.mjs";
|
|
139
142
|
import { GRAPHVIZ_ENGINES } from "../engine/map-graphviz.mjs";
|
|
140
143
|
import { loadMapWorld } from "../engine/map-places.mjs";
|
|
144
|
+
import { encodeAddresses } from "../engine/address-values.mjs";
|
|
141
145
|
|
|
142
146
|
/**
|
|
143
147
|
* The packs `unpack` extracts.
|
|
@@ -1156,6 +1160,13 @@ function lintCommand() {
|
|
|
1156
1160
|
config,
|
|
1157
1161
|
});
|
|
1158
1162
|
|
|
1163
|
+
// A list item opened with `[ ]` or `[x]` — nothing here is
|
|
1164
|
+
// miscompiled, since every surface sets the marker as the
|
|
1165
|
+
// item's own text and all three agree, so this is advisory.
|
|
1166
|
+
const taskLists = lintContentTaskLists(root, {
|
|
1167
|
+
skipDirectories: config.skipDirectories,
|
|
1168
|
+
});
|
|
1169
|
+
|
|
1159
1170
|
// Whether every empty body is a stub on purpose, and how
|
|
1160
1171
|
// finished the tree is. The counts and the oldest drafts are
|
|
1161
1172
|
// prose rather than findings: a note nobody has finished is not
|
|
@@ -1167,6 +1178,32 @@ function lintCommand() {
|
|
|
1167
1178
|
});
|
|
1168
1179
|
for (const line of states.summary) log.info(line);
|
|
1169
1180
|
|
|
1181
|
+
// Generated art, when this package declares it carries none.
|
|
1182
|
+
// `records` already holds every asset of this build, so the
|
|
1183
|
+
// check is a filter over the corpus already in hand rather
|
|
1184
|
+
// than a second enumeration of the asset trees.
|
|
1185
|
+
const generatedArt =
|
|
1186
|
+
config.forbidGeneratedArt ?
|
|
1187
|
+
records
|
|
1188
|
+
.filter(isAssetRecord)
|
|
1189
|
+
.filter((record) => record.asset.ai === true)
|
|
1190
|
+
.map((record) => ({
|
|
1191
|
+
file: path.join(config.paths.assets, record.asset.path),
|
|
1192
|
+
severity: "error",
|
|
1193
|
+
message:
|
|
1194
|
+
`\`${encodeAddresses(record.address.canonical)}\` is ` +
|
|
1195
|
+
"machine-generated art (`ai: true`), and " +
|
|
1196
|
+
"`forbidGeneratedArt` refuses it in this package",
|
|
1197
|
+
}))
|
|
1198
|
+
: [];
|
|
1199
|
+
|
|
1200
|
+
// A hero image against the size its slot is cut to, read
|
|
1201
|
+
// from the records already in hand.
|
|
1202
|
+
const artSizes = checkArtSlotSizes(records, {
|
|
1203
|
+
config,
|
|
1204
|
+
assetsBase: config.paths.assets,
|
|
1205
|
+
});
|
|
1206
|
+
|
|
1170
1207
|
const findings = [
|
|
1171
1208
|
...addresses.findings,
|
|
1172
1209
|
...frontmatter.findings,
|
|
@@ -1175,7 +1212,10 @@ function lintCommand() {
|
|
|
1175
1212
|
...icons.findings,
|
|
1176
1213
|
...html.findings,
|
|
1177
1214
|
...images.findings,
|
|
1215
|
+
...taskLists.findings,
|
|
1178
1216
|
...states.findings,
|
|
1217
|
+
...generatedArt,
|
|
1218
|
+
...artSizes,
|
|
1179
1219
|
];
|
|
1180
1220
|
// Only an **error** fails the run. Every finding was an error
|
|
1181
1221
|
// by then, so this changes nothing on its own —
|
|
@@ -1461,14 +1501,20 @@ function linksCommand() {
|
|
|
1461
1501
|
}),
|
|
1462
1502
|
);
|
|
1463
1503
|
|
|
1504
|
+
// Worded by the shared table, like every finding below it: a
|
|
1505
|
+
// sentence written here is free to describe the same defect
|
|
1506
|
+
// differently from the build that also refuses it, which is the
|
|
1507
|
+
// drift the table exists to prevent.
|
|
1464
1508
|
for (const d of deadAnchors) {
|
|
1465
1509
|
emitDiagnostic({
|
|
1466
1510
|
file: d.note.file,
|
|
1467
1511
|
...positionOfLiteral(d.note.raw, d.text, d.occurrence),
|
|
1468
1512
|
severity: "error",
|
|
1469
|
-
message:
|
|
1470
|
-
|
|
1471
|
-
|
|
1513
|
+
message: linkFindingMessage({
|
|
1514
|
+
reason: "unknown-anchor",
|
|
1515
|
+
target: d.target,
|
|
1516
|
+
anchor: d.anchor,
|
|
1517
|
+
}),
|
|
1472
1518
|
});
|
|
1473
1519
|
}
|
|
1474
1520
|
// Every link is an address and every address must
|
|
@@ -1799,6 +1845,15 @@ function siteCommand() {
|
|
|
1799
1845
|
for (const e of result.captionErrors) {
|
|
1800
1846
|
emitDiagnostic({ ...e, severity: "error" });
|
|
1801
1847
|
}
|
|
1848
|
+
for (const e of result.headingErrors) {
|
|
1849
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1850
|
+
}
|
|
1851
|
+
for (const e of result.footnoteErrors) {
|
|
1852
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1853
|
+
}
|
|
1854
|
+
for (const e of result.embedErrors) {
|
|
1855
|
+
emitDiagnostic({ ...e, severity: "error" });
|
|
1856
|
+
}
|
|
1802
1857
|
// Reported the way the pack build reports the very same
|
|
1803
1858
|
// finding: `file:line:column: error: message`, path first, and
|
|
1804
1859
|
// the message from the shared table, not a
|
|
@@ -1838,8 +1893,11 @@ function siteCommand() {
|
|
|
1838
1893
|
result.expressionErrors.length ||
|
|
1839
1894
|
result.secretErrors.length ||
|
|
1840
1895
|
result.captionErrors.length ||
|
|
1896
|
+
result.headingErrors.length ||
|
|
1897
|
+
result.footnoteErrors.length ||
|
|
1841
1898
|
result.wikiErrors.length ||
|
|
1842
|
-
result.imageErrors.length
|
|
1899
|
+
result.imageErrors.length ||
|
|
1900
|
+
result.embedErrors.length
|
|
1843
1901
|
) {
|
|
1844
1902
|
process.exitCode = 1;
|
|
1845
1903
|
return;
|
|
@@ -2172,16 +2230,18 @@ async function fetchFromLocalArtifact(config, argv) {
|
|
|
2172
2230
|
|
|
2173
2231
|
/**
|
|
2174
2232
|
* `deps fetch` — fill the caches this build resolves other packages through:
|
|
2175
|
-
* the **content index** of every declared dependency, the **item catalogue
|
|
2176
|
-
* of those additionally declaring `itemCatalog: true
|
|
2177
|
-
*
|
|
2178
|
-
* menu from.
|
|
2179
|
-
*
|
|
2180
|
-
* The
|
|
2181
|
-
* *addresses
|
|
2182
|
-
*
|
|
2183
|
-
*
|
|
2184
|
-
*
|
|
2233
|
+
* the **content index** of every declared dependency, the **item catalogue
|
|
2234
|
+
* or asset archive** of those additionally declaring `itemCatalog: true` or
|
|
2235
|
+
* `assetArchive: true`, and the **site navigation** heroiclands.org
|
|
2236
|
+
* publishes, which the site build writes its menu from.
|
|
2237
|
+
*
|
|
2238
|
+
* The dependency sets differ deliberately. Citing another package's
|
|
2239
|
+
* *addresses*, embedding its *items*, and staging its *asset bytes* are
|
|
2240
|
+
* separate edges, and a package may declare any of them without the others —
|
|
2241
|
+
* `harn-ensemble` cites no foreign address and embeds 324,016 item
|
|
2242
|
+
* references. The navigation is fetched for every package, because every
|
|
2243
|
+
* package publishes a site. A relationship declaring both `itemCatalog: true`
|
|
2244
|
+
* and `assetArchive: true` is fetched once.
|
|
2185
2245
|
*
|
|
2186
2246
|
* Its own command rather than a step of `package compile` or `site`, so that
|
|
2187
2247
|
* neither reaches the network. A build that downloads silently is not
|
|
@@ -2242,7 +2302,7 @@ function depsCommand() {
|
|
|
2242
2302
|
const indexes = await fetchAllMetadata(config);
|
|
2243
2303
|
if (indexes) log.info(`Fetched ${indexes} dependency content index(es).`);
|
|
2244
2304
|
const count = await fetchAllCatalogs(config);
|
|
2245
|
-
if (count) log.info(`Fetched ${count} dependency catalogue(s).`);
|
|
2305
|
+
if (count) log.info(`Fetched ${count} dependency catalogue(s) or archive(s).`);
|
|
2246
2306
|
if (!indexes && !count) {
|
|
2247
2307
|
// Distinguished from a package declaring nothing at all: a
|
|
2248
2308
|
// relationship may still be declared, just narrowed to the
|
|
@@ -2254,8 +2314,8 @@ function depsCommand() {
|
|
|
2254
2314
|
);
|
|
2255
2315
|
log.info(
|
|
2256
2316
|
declared ?
|
|
2257
|
-
"No declared dependency needs a fetched content index
|
|
2258
|
-
"catalogue."
|
|
2317
|
+
"No declared dependency needs a fetched content index, item " +
|
|
2318
|
+
"catalogue, or asset archive."
|
|
2259
2319
|
: "This package declares no dependencies.",
|
|
2260
2320
|
);
|
|
2261
2321
|
}
|
package/bin/package-build.mjs
CHANGED
|
@@ -93,6 +93,7 @@ import { DEPLOY_ROOT } from "../engine/site-config.mjs";
|
|
|
93
93
|
import { compilesFoundryDocuments } from "../content-config.mjs";
|
|
94
94
|
import { loadPackConfig, packConfigPath, resolveConfigFile } from "../engine/pack-config.mjs";
|
|
95
95
|
import { cleanBuildArtifacts, resetStage, stageAssets } from "../stage.mjs";
|
|
96
|
+
import { baseStyleStageEntry } from "../engine/base-styles.mjs";
|
|
96
97
|
import { buildSchemaArtifact } from "../engine/schema-extract.mjs";
|
|
97
98
|
import { emitCalendarArtifacts } from "../engine/calendar-artifacts.mjs";
|
|
98
99
|
import { dateFromCalendar, dateToCalendar } from "../engine/date-conversion.mjs";
|
|
@@ -424,7 +425,7 @@ function assetsCommand() {
|
|
|
424
425
|
builder: (y) => y,
|
|
425
426
|
handler: handler(async () => {
|
|
426
427
|
const config = loadPackageBuildConfig();
|
|
427
|
-
if (!config.assets.length) {
|
|
428
|
+
if (!config.assets.length && !config.baseStyles) {
|
|
428
429
|
console.log("package-build: no `packageBuild.assets` declared; nothing to stage.");
|
|
429
430
|
return;
|
|
430
431
|
}
|
|
@@ -462,10 +463,22 @@ function assetsCommand() {
|
|
|
462
463
|
from,
|
|
463
464
|
path.join(config.stageDir, to),
|
|
464
465
|
]);
|
|
465
|
-
|
|
466
|
+
let { entries: count, files } = stageAssets(entries, {
|
|
466
467
|
cwd: config.rootDir,
|
|
467
468
|
transform,
|
|
468
469
|
});
|
|
470
|
+
|
|
471
|
+
// Staged in its own pass, without the repository's transform: the
|
|
472
|
+
// sheet is this toolchain's file rather than one of the
|
|
473
|
+
// repository's assets, and a `transform` written to retheme a
|
|
474
|
+
// package's own SVGs has no business being handed it.
|
|
475
|
+
if (config.baseStyles) {
|
|
476
|
+
const staged = stageAssets([baseStyleStageEntry(config.stageDir)], {
|
|
477
|
+
cwd: config.rootDir,
|
|
478
|
+
});
|
|
479
|
+
count += staged.entries;
|
|
480
|
+
files += staged.files;
|
|
481
|
+
}
|
|
469
482
|
console.log(`✅ Static assets staged (${count} entries, ${files} files).`);
|
|
470
483
|
}),
|
|
471
484
|
};
|