@heroiclands/package-build 23.4.1 → 23.5.1
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 +35 -0
- package/README.md +29 -25
- package/assets/images/provenance.yaml +1 -0
- package/bin/package-build.mjs +259 -101
- package/ci/prettier.mjs +73 -0
- package/config.mjs +10 -0
- package/container.mjs +232 -1
- package/content-config.mjs +5 -1
- package/docs/api.md +100 -52
- package/docs/authoring/assets.md +16 -1
- package/docs/commands.md +154 -51
- package/docs/configuration.md +39 -2
- package/docs/content-format.md +30 -6
- package/docs/diagnostics.md +1 -2
- package/docs/guides/e2e.md +38 -0
- package/docs/guides/icons.md +5 -0
- package/docs/guides/module-project.md +1 -1
- package/docs/guides/release-and-deploy.md +36 -1
- package/docs/project-setup.md +16 -59
- package/docs/reference/format-details.md +180 -34
- package/docs/reference/note-types.md +69 -69
- package/engine/asset-index.mjs +63 -22
- package/engine/asset-references.mjs +355 -0
- package/engine/asset-shipping.mjs +363 -0
- package/engine/asset-types.mjs +70 -0
- package/engine/base-compiler.mjs +24 -1
- package/engine/cdn-publish.mjs +643 -0
- package/engine/index.mjs +6 -0
- package/engine/note-vocabulary.mjs +4 -1
- package/engine/pathnames.mjs +21 -10
- package/engine/project-init.mjs +4 -29
- package/engine/rank-ladder.mjs +40 -16
- package/engine/scenes.mjs +1 -1
- package/engine/standing-terms.mjs +3 -1
- package/package.json +5 -6
- package/packagebuild-metadata.jsonl +13 -13
- package/release.mjs +69 -7
- package/sohl/actors.mjs +12 -4
- package/sohl/default-item-art.mjs +23 -19
- package/types/config.d.mts +7 -0
- package/types/container.d.mts +137 -1
- package/types/engine/asset-index.d.mts +3 -2
- package/types/engine/asset-references.d.mts +136 -0
- package/types/engine/asset-shipping.d.mts +240 -0
- package/types/engine/asset-types.d.mts +36 -0
- package/types/engine/base-compiler.d.mts +7 -1
- package/types/engine/cdn-publish.d.mts +312 -0
- package/types/engine/index.d.mts +2 -0
- package/types/engine/pathnames.d.mts +2 -1
- package/types/engine/rank-ladder.d.mts +25 -6
- package/types/release.d.mts +5 -3
- package/types/sohl/default-item-art.d.mts +2 -1
- package/labels.mjs +0 -191
- package/types/labels.d.mts +0 -40
package/docs/authoring/assets.md
CHANGED
|
@@ -26,16 +26,31 @@ The embed's label is alternative text. `![[icon-harbor|]]` is decorative. `size=
|
|
|
26
26
|
|
|
27
27
|
## Ownership and source records
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Every asset is covered by a provenance record. Put `provenance.yaml` in an asset directory to describe files there and below, or put a YAML sidecar named for the whole filename — `anvil.svg.yaml` — beside one asset to give that file its own record. A sidecar replaces the directory record for that asset; otherwise the nearest `provenance.yaml` in the file's directory or one above it, up to the type root, answers. Each file resolves on its own, so a directory may hold files its `provenance.yaml` covers beside files a sidecar answers for. A file no record covers is an error at the file. Keep attribution with the authored asset so movement through the tree does not lose its source or license. See the [asset record reference](../reference/format-details.md#the-asset-record) for the accepted keys, inheritance, and examples.
|
|
30
|
+
|
|
31
|
+
Every record states `attribution`, `license` and `ai` — whether a machine made the file, as the YAML boolean `true` or `false`. A record that leaves `ai` out is an error at the record; it is never read as `false`.
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
attribution: Tom Rodriguez
|
|
35
|
+
license: CC-BY-SA-4.0
|
|
36
|
+
ai: false
|
|
37
|
+
```
|
|
30
38
|
|
|
31
39
|
A directory of portraits also states what the pictures in it are for:
|
|
32
40
|
|
|
33
41
|
```yaml
|
|
34
42
|
attribution: Tom Rodriguez
|
|
35
43
|
license: CC-BY-SA-4.0
|
|
44
|
+
ai: false
|
|
36
45
|
role: portrait
|
|
37
46
|
```
|
|
38
47
|
|
|
48
|
+
## What the Foundry package ships
|
|
49
|
+
|
|
50
|
+
The repository keeps every picture; the Foundry package carries a filtered copy, laid out flat. A picture ships when its record says `ai: false` and its licence is one of `LicenseRef-PublicDomain`, `CC0-1.0`, `CC0`, `CC-BY-3.0`, `CC-BY-4.0`, `CC-BY-SA-4.0` or `LicenseRef-NounProject-Pro`, together with any licence the package adds under `packageBuild.shippingLicenses`. A shipped picture sits at `icons/<basename>` or `images/<basename>` at the package root, whatever directories it is kept in here, and the package's asset set, `asset-sets/default.json`, lists what it ships.
|
|
51
|
+
|
|
52
|
+
A note may still name a picture the package does not ship. Its compiled document draws the package's stand-in instead — `icons/missing.<ext>` or `images/missing.<ext>`, which you provide as an ordinary human-made picture licensed to ship, addressed `<package>-none-icon-missing` and `<package>-none-image-missing` — and keeps the real picture's address, so a world that holds the real file can point back at it. A package that leaves out a picture a note names, and ships no stand-in of that type, fails the build at the note. See [what a package ships](../reference/format-details.md#what-a-package-ships).
|
|
53
|
+
|
|
39
54
|
**A hero image is 1792×768.** `data.banner` fills one fixed strip wherever it is drawn, so every banner is cut to that size and a picture of any other size is a finding naming both sizes — resize the picture to match. That is the one size any art field requires.
|
|
40
55
|
|
|
41
56
|
`data.banner` reads in one of three states:
|
package/docs/commands.md
CHANGED
|
@@ -58,7 +58,7 @@ The command entries below list only their own options.
|
|
|
58
58
|
the walk up from the working directory the CLI otherwise does — the only
|
|
59
59
|
environment variable the toolchain itself reads for configuration
|
|
60
60
|
resolution. `deploy`, `container` and `e2e` additionally read `FOUNDRYVTT_*`,
|
|
61
|
-
documented where each applies.
|
|
61
|
+
and `cdn publish` reads `CDN_*`, documented where each applies.
|
|
62
62
|
|
|
63
63
|
An option name recurring across commands is not a recurring meaning —
|
|
64
64
|
`--out`, `--check`, `--from` and `--strict` each carry their own default and
|
|
@@ -300,6 +300,16 @@ names a module in `packageBuild.assetTransform`, exporting
|
|
|
300
300
|
anything else replaces its content. Reads every `from` path; writes into
|
|
301
301
|
`packageBuild.stageDir`.
|
|
302
302
|
|
|
303
|
+
Then stages the package's pictures itself. Every file under `assets/icons/`
|
|
304
|
+
and `assets/images/` whose provenance says `ai: false` and whose licence is on
|
|
305
|
+
the shipping list (the default list plus `packageBuild.shippingLicenses`) is copied flat to `icons/<basename>` or `images/<basename>`
|
|
306
|
+
at the package root, through the same transform, and the package's asset set,
|
|
307
|
+
`asset-sets/default.json`, lists what was staged. Everything else stays in the repository. See
|
|
308
|
+
[what a package ships](reference/format-details.md#what-a-package-ships).
|
|
309
|
+
A `packageBuild.assets` row that copies a picture root, a directory inside
|
|
310
|
+
one, or a directory holding one is refused, because it would ship every file
|
|
311
|
+
unfiltered.
|
|
312
|
+
|
|
303
313
|
**OPTIONS**
|
|
304
314
|
|
|
305
315
|
None.
|
|
@@ -307,15 +317,20 @@ None.
|
|
|
307
317
|
**EXIT STATUS**
|
|
308
318
|
|
|
309
319
|
1 if `packageBuild.assetTransform` is declared but cannot be loaded, or
|
|
310
|
-
exports no `transform` function. 1
|
|
311
|
-
|
|
312
|
-
|
|
320
|
+
exports no `transform` function. 1 when a row copies a picture root, and 1 on
|
|
321
|
+
any asset finding — a file no provenance record covers, a record missing
|
|
322
|
+
`attribution`, `license` or `ai`, two files claiming one address — with
|
|
323
|
+
nothing staged. 1 on any other thrown error. Otherwise 0.
|
|
313
324
|
|
|
314
325
|
**EXAMPLES**
|
|
315
326
|
|
|
316
327
|
```
|
|
317
328
|
$ package-build assets
|
|
318
|
-
|
|
329
|
+
Pictures: 4 staged, 2 left out by provenance.
|
|
330
|
+
✅ Static assets staged (2 entries, 9 files).
|
|
331
|
+
|
|
332
|
+
$ package-build assets
|
|
333
|
+
package-build.config.yaml:14:17: error: `packageBuild.assets[6]` copies `assets/images`, which reaches assets/images/ — the stage copies the icon and image roots itself, flat and filtered by each file's provenance, so a row copying them would ship every file unfiltered. Remove the row
|
|
319
334
|
```
|
|
320
335
|
|
|
321
336
|
**SEE ALSO**
|
|
@@ -774,50 +789,6 @@ package-build: 1 template(s) fully localized and compiling.
|
|
|
774
789
|
`package-build lang check`, `package-build lang coverage`,
|
|
775
790
|
[Diagnostics](diagnostics.md), [Configuration](configuration.md).
|
|
776
791
|
|
|
777
|
-
### `package-build labels check`
|
|
778
|
-
|
|
779
|
-
**NAME**
|
|
780
|
-
|
|
781
|
-
Compare the machine label registry against the documented reference table
|
|
782
|
-
(`check` is the only action).
|
|
783
|
-
|
|
784
|
-
**SYNOPSIS**
|
|
785
|
-
|
|
786
|
-
```
|
|
787
|
-
package-build labels check [--registry <path>] [--doc <path>]
|
|
788
|
-
```
|
|
789
|
-
|
|
790
|
-
**DESCRIPTION**
|
|
791
|
-
|
|
792
|
-
Compares the machine label registry synced to GitHub against the documented
|
|
793
|
-
reference table, and reports where they disagree — a label the registry has
|
|
794
|
-
that the table does not, or the reverse. Neither derives from the other, so
|
|
795
|
-
nothing else notices when they drift. Reads both files named below; writes
|
|
796
|
-
nothing.
|
|
797
|
-
|
|
798
|
-
**OPTIONS**
|
|
799
|
-
|
|
800
|
-
| Option | Type | Default | Description |
|
|
801
|
-
| ------------ | ------ | ---------------------------- | -------------------------------------------------------------- |
|
|
802
|
-
| `--registry` | string | `.github/labels.yml` | The machine registry synced to GitHub. |
|
|
803
|
-
| `--doc` | string | `.github/ISSUE_REPORTING.md` | The documented reference whose §3 table lists the same labels. |
|
|
804
|
-
|
|
805
|
-
**EXIT STATUS**
|
|
806
|
-
|
|
807
|
-
1 if either file does not exist. 1 if the registry and the table disagree on
|
|
808
|
-
any label. Otherwise 0.
|
|
809
|
-
|
|
810
|
-
**EXAMPLES**
|
|
811
|
-
|
|
812
|
-
```
|
|
813
|
-
$ package-build labels check --registry .github/labels.yml --doc .github/ISSUE_REPORTING.md
|
|
814
|
-
package-build: registry and §3 agree (11 labels).
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
**SEE ALSO**
|
|
818
|
-
|
|
819
|
-
None.
|
|
820
|
-
|
|
821
792
|
### `package-build bump [packages..]`
|
|
822
793
|
|
|
823
794
|
**NAME**
|
|
@@ -1138,7 +1109,9 @@ states it a second time. It also publishes the content index the manifest
|
|
|
1138
1109
|
advertises (`flags.metadataUrl`) and, when the stage carries one,
|
|
1139
1110
|
`schema.json` — a repository that names `build/schema.json` in
|
|
1140
1111
|
`packageBuild.assets` gets it released beside the archive; one that does not
|
|
1141
|
-
gets none. When the
|
|
1112
|
+
gets none. When the stage carries `asset-sets/default.json`, it writes
|
|
1113
|
+
`icons.zip` and `images.zip` too, one per picture root the stage holds, each
|
|
1114
|
+
with that set. When the content tree holds notes beyond its homepage, it
|
|
1142
1115
|
also builds the content-tree book (see `package-build pdf`) and reports it
|
|
1143
1116
|
alongside the archive; `--no-pdf` skips that step for a release that has a
|
|
1144
1117
|
tree but does not want the book this time. A book that fails to build is
|
|
@@ -1246,6 +1219,134 @@ Deployed stage 'test' successfully.
|
|
|
1246
1219
|
`package-build container <stage> <action>`, `package-build e2e <action>`,
|
|
1247
1220
|
[Configuration](configuration.md).
|
|
1248
1221
|
|
|
1222
|
+
### `package-build cdn publish`
|
|
1223
|
+
|
|
1224
|
+
**NAME**
|
|
1225
|
+
|
|
1226
|
+
Upload every picture the package has to the CDN, and publish the art the
|
|
1227
|
+
package leaves out as a named asset set.
|
|
1228
|
+
|
|
1229
|
+
**SYNOPSIS**
|
|
1230
|
+
|
|
1231
|
+
```
|
|
1232
|
+
package-build cdn publish --set <file> --name <display name> [--dry-run]
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
**DESCRIPTION**
|
|
1236
|
+
|
|
1237
|
+
The one writer to `<site.assets>/<contentPackage>/`. It is run by hand, or by
|
|
1238
|
+
a manually dispatched workflow; no build or release runs it.
|
|
1239
|
+
|
|
1240
|
+
Every icon and image under the package's picture roots is uploaded flat, as
|
|
1241
|
+
`icons/<basename>` or `images/<basename>` — shipped and left-out pictures
|
|
1242
|
+
alike, because the website draws every one of them from the same address the
|
|
1243
|
+
site build gives it. `packageBuild.assetTransform` runs on each file exactly
|
|
1244
|
+
as `package-build assets` runs it, so a picture on the CDN holds the bytes the
|
|
1245
|
+
staged package holds. SVG is served as `image/svg+xml`.
|
|
1246
|
+
|
|
1247
|
+
The bucket is served at `site.assets`, so an object's key is its path below
|
|
1248
|
+
that address: `thalorna/images/thorn.webp` is
|
|
1249
|
+
`https://cdn.heroiclands.org/thalorna/images/thorn.webp`.
|
|
1250
|
+
|
|
1251
|
+
`--set` names the set file, written at `<site.assets>/<contentPackage>/<file>`.
|
|
1252
|
+
It lists only the pictures the package leaves out — an address a set does not
|
|
1253
|
+
list resolves to the shipped copy — chosen by the same rule the stage applies,
|
|
1254
|
+
`packageBuild.shippingLicenses` included. Its shape is the shipped set's, with
|
|
1255
|
+
each `source` the file's absolute CDN address:
|
|
1256
|
+
|
|
1257
|
+
```json
|
|
1258
|
+
{
|
|
1259
|
+
"name": "Thalorna — illustrated",
|
|
1260
|
+
"package": "thalorna",
|
|
1261
|
+
"assets": [
|
|
1262
|
+
{
|
|
1263
|
+
"address": "thalorna-none-image-thorn",
|
|
1264
|
+
"source": "https://cdn.heroiclands.org/thalorna/images/thorn.webp",
|
|
1265
|
+
"target": "images/thorn.webp",
|
|
1266
|
+
"size": 48213
|
|
1267
|
+
}
|
|
1268
|
+
]
|
|
1269
|
+
}
|
|
1270
|
+
```
|
|
1271
|
+
|
|
1272
|
+
Several sets may sit side by side under one package, each with its own file
|
|
1273
|
+
name. `default.json` is refused: it is the shipped set's name.
|
|
1274
|
+
|
|
1275
|
+
A picture whose object already exists at the same size is skipped, and the set
|
|
1276
|
+
file is skipped when its bytes are unchanged, so a second run uploads nothing.
|
|
1277
|
+
A picture that fails to upload is reported and the rest carry on; the set file
|
|
1278
|
+
is then withheld, since it would list a file the CDN does not hold.
|
|
1279
|
+
|
|
1280
|
+
**Refusals and reports.** A file under `icons/` or `images/` whose name is no
|
|
1281
|
+
address — a basename that is not a shortcode, or two files claiming one — and
|
|
1282
|
+
a provenance record that cannot be read stop the run before anything is
|
|
1283
|
+
uploaded, each reported against its file. A note naming a picture the package
|
|
1284
|
+
does not have, and a note naming left-out art that is not on the CDN when the
|
|
1285
|
+
run ends, are warnings at the note's line and column: an art slot under
|
|
1286
|
+
`data:`, an embed, or a body image.
|
|
1287
|
+
|
|
1288
|
+
**Credentials.** The store is an S3-compatible bucket — Cloudflare R2 for
|
|
1289
|
+
`cdn.heroiclands.org` — signed with AWS Signature Version 4. Its settings are
|
|
1290
|
+
read from the environment, after `.env.local` and `.env` are loaded:
|
|
1291
|
+
|
|
1292
|
+
| Variable | What it is |
|
|
1293
|
+
| ----------------------- | ------------------------------------------------------------------------- |
|
|
1294
|
+
| `CDN_ENDPOINT` | The S3 endpoint; for R2, `https://<account id>.r2.cloudflarestorage.com`. |
|
|
1295
|
+
| `CDN_BUCKET` | The bucket served at `site.assets`. |
|
|
1296
|
+
| `CDN_ACCESS_KEY_ID` | The access key id of a token that can write the bucket. |
|
|
1297
|
+
| `CDN_SECRET_ACCESS_KEY` | That token's secret. Never printed. |
|
|
1298
|
+
|
|
1299
|
+
Setting some but not all of them is an error naming the missing ones. With
|
|
1300
|
+
none set, `--dry-run` compares against the public CDN at `site.assets`
|
|
1301
|
+
instead, read-only, and an upload is refused.
|
|
1302
|
+
|
|
1303
|
+
A workflow calls the command the same way, passing the four values as named
|
|
1304
|
+
secrets in the step's environment:
|
|
1305
|
+
|
|
1306
|
+
```yaml
|
|
1307
|
+
- run: npx package-build cdn publish --set alt-art.json --name "Thalorna — illustrated"
|
|
1308
|
+
env:
|
|
1309
|
+
CDN_ENDPOINT: ${{ secrets.CDN_ENDPOINT }}
|
|
1310
|
+
CDN_BUCKET: ${{ secrets.CDN_BUCKET }}
|
|
1311
|
+
CDN_ACCESS_KEY_ID: ${{ secrets.CDN_ACCESS_KEY_ID }}
|
|
1312
|
+
CDN_SECRET_ACCESS_KEY: ${{ secrets.CDN_SECRET_ACCESS_KEY }}
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
**OPTIONS**
|
|
1316
|
+
|
|
1317
|
+
| Option | Type | Default | Description |
|
|
1318
|
+
| ----------- | ------- | ------- | --------------------------------------------------------------------------- |
|
|
1319
|
+
| `--set` | string | — | Required. The set file's name under the package's CDN root, a `.json` file. |
|
|
1320
|
+
| `--name` | string | — | Required. The set's display name. |
|
|
1321
|
+
| `--dry-run` | boolean | `false` | List what would upload and what is skipped; write nothing. |
|
|
1322
|
+
|
|
1323
|
+
**EXIT STATUS**
|
|
1324
|
+
|
|
1325
|
+
1 when a picture's file has no address, when a picture fails to upload, when
|
|
1326
|
+
`--set` is `default.json` or a path, when `site.assets` is undeclared, and
|
|
1327
|
+
when an upload has no store configured. Warnings about notes do not change
|
|
1328
|
+
it. Otherwise 0.
|
|
1329
|
+
|
|
1330
|
+
**EXAMPLES**
|
|
1331
|
+
|
|
1332
|
+
```
|
|
1333
|
+
$ package-build cdn publish --set alt-art.json --name "Thalorna — illustrated" --dry-run
|
|
1334
|
+
Dry run: comparing 582 pictures against https://cdn.heroiclands.org, read-only.
|
|
1335
|
+
would upload thalorna/icons/anvilbdg.svg (969 bytes)
|
|
1336
|
+
…
|
|
1337
|
+
would upload thalorna/alt-art.json (582 assets)
|
|
1338
|
+
Would upload 582, skipped 0, failed 0; https://cdn.heroiclands.org/thalorna/alt-art.json lists 582 left-out pictures (would change).
|
|
1339
|
+
|
|
1340
|
+
$ package-build cdn publish --set default.json --name Shipped
|
|
1341
|
+
package-build: `--set default.json` is refused: `default.json` is the shipped set's name, the fallback every other set is read against. Name the set for its art
|
|
1342
|
+
```
|
|
1343
|
+
|
|
1344
|
+
**SEE ALSO**
|
|
1345
|
+
|
|
1346
|
+
`package-build assets`, `package-build release`,
|
|
1347
|
+
[Configuration](configuration.md#site),
|
|
1348
|
+
[Release and deploy](guides/release-and-deploy.md#publish-pictures-to-the-cdn).
|
|
1349
|
+
|
|
1249
1350
|
### `package-build container <stage> <action>`
|
|
1250
1351
|
|
|
1251
1352
|
**NAME**
|
|
@@ -1306,7 +1407,9 @@ exact pin takes the major tag of its pin or of `compatibility.minimum`
|
|
|
1306
1407
|
mount), `FOUNDRYVTT_CONTAINER_USER` (passed to `docker run --user`; `0:0`
|
|
1307
1408
|
under rootless Docker makes the data root's files belong to the host user,
|
|
1308
1409
|
because the image otherwise runs Foundry as user 1000 and ignores
|
|
1309
|
-
`FOUNDRY_UID` and `FOUNDRY_GID`)
|
|
1410
|
+
`FOUNDRY_UID` and `FOUNDRY_GID`), `FOUNDRYVTT_CONTAINER_S3` (`1` or `true`
|
|
1411
|
+
runs an S3-compatible server beside the container; see
|
|
1412
|
+
[an S3 server for the container](guides/e2e.md#an-s3-server-for-the-container)).
|
|
1310
1413
|
|
|
1311
1414
|
**EXIT STATUS**
|
|
1312
1415
|
|
package/docs/configuration.md
CHANGED
|
@@ -206,6 +206,9 @@ against — the one reader of it is `resolveImg`
|
|
|
206
206
|
`packageKind` and `foundryPackage`.
|
|
207
207
|
|
|
208
208
|
- For a `systems` or `modules` package, `<packageKind>/<foundryPackage>/assets`.
|
|
209
|
+
A picture under `icons/` or `images/` is served flat from
|
|
210
|
+
`<packageKind>/<foundryPackage>/<icons|images>/<basename>` instead, the
|
|
211
|
+
layout the stage gives it; every other file keeps its path under `assets/`.
|
|
209
212
|
- For a `documentation` package, `null` — Foundry serves no files for a
|
|
210
213
|
package of this kind, and `documentation/null/assets` would be an address
|
|
211
214
|
that resolves nowhere. `resolveImg` refuses rather than rooting a path
|
|
@@ -901,6 +904,12 @@ resolves every relative asset against it:
|
|
|
901
904
|
|
|
902
905
|
> ``package-build config: `site.assets` is not declared, and a site build needs one — it is the host every package's imagery is served from, and the theme resolves every relative asset against it.``
|
|
903
906
|
|
|
907
|
+
`package-build cdn publish` uploads the package's pictures under the same
|
|
908
|
+
host, at `<site.assets>/<contentPackage>/icons/<basename>` and
|
|
909
|
+
`…/images/<basename>`, which is the address the website gives each one. The
|
|
910
|
+
bucket behind the CDN is served at `site.assets`, so an object's key is its
|
|
911
|
+
path below this value.
|
|
912
|
+
|
|
904
913
|
The generated Hugo configuration carries the same host as
|
|
905
914
|
`params.cdnBaseURL`, which the theme resolves a relative asset path against.
|
|
906
915
|
The two are one value read by two readers: the toolchain emits it into a
|
|
@@ -1685,7 +1694,7 @@ validator.
|
|
|
1685
1694
|
packageBuild:
|
|
1686
1695
|
assets:
|
|
1687
1696
|
- { from: lang, to: lang }
|
|
1688
|
-
- { from: assets/
|
|
1697
|
+
- { from: assets/audio, to: assets/audio }
|
|
1689
1698
|
assetTransform: ./utils/svg-theme.mjs
|
|
1690
1699
|
stageDir: build/stage
|
|
1691
1700
|
clean:
|
|
@@ -1701,6 +1710,7 @@ packageBuild:
|
|
|
1701
1710
|
| [`packageBuild.stageDir`](#packagebuildstagedir-and-packagebuildassets) | string | no | `build/stage` |
|
|
1702
1711
|
| [`packageBuild.assets`](#packagebuildstagedir-and-packagebuildassets) | array | no | `[]` |
|
|
1703
1712
|
| [`packageBuild.assetTransform`](#packagebuildassettransform-and-packagebuildmanifestflags) | string (path to a module) | no | `null` |
|
|
1713
|
+
| [`packageBuild.shippingLicenses`](#packagebuildshippinglicenses) | array of strings | no | `[]` |
|
|
1704
1714
|
| [`packageBuild.baseStyles`](#packagebuildbasestyles) | boolean | no | `true` |
|
|
1705
1715
|
| [`packageBuild.manifest`](#packagebuildmanifest) | object, pass-through | no | `{}` |
|
|
1706
1716
|
| [`packageBuild.manifestFlags`](#packagebuildassettransform-and-packagebuildmanifestflags) | string (path to a module) | no | `null` |
|
|
@@ -1715,7 +1725,7 @@ packageBuild:
|
|
|
1715
1725
|
| [`packageBuild.proseLint`](#packagebuildproselint) | object | no | `{age: 21, threshold: 5, minWords: 8, rules: readability}` |
|
|
1716
1726
|
| [`packageBuild.proseScore`](#packagebuildprosescore) | object | no | `{minWords: 80, bands: {}}` |
|
|
1717
1727
|
|
|
1718
|
-
> ``package-build config: `packageBuild.<key>` is not a recognised key (expected one of: stageDir, assets, assetTransform, baseStyles, manifest, manifestFlags, schema, clean, lang, deploy, release, bundle, container, e2e, proseLint, proseScore).``
|
|
1728
|
+
> ``package-build config: `packageBuild.<key>` is not a recognised key (expected one of: stageDir, assets, assetTransform, shippingLicenses, baseStyles, manifest, manifestFlags, schema, clean, lang, deploy, release, bundle, container, e2e, proseLint, proseScore).``
|
|
1719
1729
|
|
|
1720
1730
|
### `packageBuild.proseLint`
|
|
1721
1731
|
|
|
@@ -1765,6 +1775,15 @@ table says `lang`, not `build/stage/lang`.
|
|
|
1765
1775
|
`assets` is the table of staging copies: source path in the repository,
|
|
1766
1776
|
destination under the staged package root.
|
|
1767
1777
|
|
|
1778
|
+
**The picture roots are not in it.** `package-build assets` stages
|
|
1779
|
+
`assets/icons/` and `assets/images/` itself — flat at the package root, and
|
|
1780
|
+
only the files whose provenance allows them to ship (see
|
|
1781
|
+
[what a package ships](reference/format-details.md#what-a-package-ships)). A
|
|
1782
|
+
row whose `from` is a picture root, a directory inside one, or a directory
|
|
1783
|
+
holding one is refused at the row:
|
|
1784
|
+
|
|
1785
|
+
> ``package-build.config.yaml:<line>:<column>: error: `packageBuild.assets[<index>]` copies `<from>`, which reaches assets/images/ — the stage copies the icon and image roots itself, flat and filtered by each file's provenance, so a row copying them would ship every file unfiltered. Remove the row``
|
|
1786
|
+
|
|
1768
1787
|
| Key | Type | Required |
|
|
1769
1788
|
| ------------------------------- | -------------------------- | -------- |
|
|
1770
1789
|
| `packageBuild.assets[].from` | string | yes |
|
|
@@ -1801,6 +1820,24 @@ repository has to compute. Neither declares anything, both default to
|
|
|
1801
1820
|
|
|
1802
1821
|
> ``package-build config: `packageBuild.manifestFlags` must be a non-empty string.``
|
|
1803
1822
|
|
|
1823
|
+
### `packageBuild.shippingLicenses`
|
|
1824
|
+
|
|
1825
|
+
Licences this package adds to the default shipping list. A picture ships in the
|
|
1826
|
+
Foundry package when its provenance says `ai: false` and its `license` is on the
|
|
1827
|
+
default list or on this one; the default list is never replaced, and `ai: true`
|
|
1828
|
+
never ships. Each entry is spelled exactly as provenance spells the licence.
|
|
1829
|
+
|
|
1830
|
+
```yaml
|
|
1831
|
+
packageBuild:
|
|
1832
|
+
shippingLicenses: [CC-BY-NC-SA-4.0]
|
|
1833
|
+
```
|
|
1834
|
+
|
|
1835
|
+
> ``package-build config: `packageBuild.shippingLicenses` must be a list of licence identifiers.``
|
|
1836
|
+
|
|
1837
|
+
> ``package-build config: `packageBuild.shippingLicenses` entry <index> must be a non-empty string.``
|
|
1838
|
+
|
|
1839
|
+
> ``package-build config: `packageBuild.shippingLicenses` lists `<licence>` more than once.``
|
|
1840
|
+
|
|
1804
1841
|
### `packageBuild.baseStyles`
|
|
1805
1842
|
|
|
1806
1843
|
Whether the package takes the shared base stylesheet. It defaults to `true`,
|
package/docs/content-format.md
CHANGED
|
@@ -53,12 +53,36 @@ explains routing for documents and their prose journals.
|
|
|
53
53
|
|
|
54
54
|
A note can also produce a system document: an Actor, Item, Scene, or Macro according to its type and system blocks. The `sohl:` and `hm3:` blocks supply game-specific mechanics and overrides; they do not create separate prose. The JournalEntry is shared between systems.
|
|
55
55
|
|
|
56
|
-
An `affiliation` note declares `data.governance.ranks` with at least
|
|
57
|
-
`level:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
An `affiliation` note declares `data.governance.ranks` with at least two rungs:
|
|
57
|
+
`level: 0`, those the body excludes, and `level: 1`, its ordinary members. Every
|
|
58
|
+
body that can name its members can name those it shuts out, whether or not it
|
|
59
|
+
ever does, so both are required. Each rung states `level`, `title`, and
|
|
60
|
+
`description`, and the level-0 title is the body's own word for the excluded
|
|
61
|
+
rather than a generic "Excluded". A being's `data.affiliations` entry names a
|
|
62
|
+
rank on that body's ladder; level 1 is the ordinary standing when no higher
|
|
63
|
+
rank applies.
|
|
64
|
+
|
|
65
|
+
Add rungs above level 1 only where the body truly has them, generally no more
|
|
66
|
+
than five. A rung is a **standing**, what a member is; an entry in
|
|
67
|
+
`governance.offices` is a **post**, what a member does. Leadership is normally
|
|
68
|
+
an office held by the top rank rather than a rank above it, and a rank never
|
|
69
|
+
falls when an office is left: a bishop stays a bishop after being Presiding
|
|
70
|
+
Bishop.
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
data:
|
|
74
|
+
governance:
|
|
75
|
+
ranks:
|
|
76
|
+
- { level: 0, title: Apostate, description: Put out of the communion. }
|
|
77
|
+
- { level: 1, title: Layman, description: A baptised member of the faith. }
|
|
78
|
+
- { level: 2, title: Priest, description: Ordained to serve a parish. }
|
|
79
|
+
- { level: 3, title: Bishop, description: Consecrated to oversee a diocese. }
|
|
80
|
+
offices:
|
|
81
|
+
Presiding Bishop: Chairs the synod of bishops for a term.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Missing ranks, an empty list, or a ladder without level 0 or level 1 are build
|
|
85
|
+
errors, reported at the `ranks` key.
|
|
62
86
|
|
|
63
87
|
| Authored section | SoHL Actor | HM3 Actor |
|
|
64
88
|
| ---------------- | ------------------- | -------------------- |
|
package/docs/diagnostics.md
CHANGED
|
@@ -284,7 +284,7 @@ when it reports at least one `error`-severity diagnostic. A `warning` alone
|
|
|
284
284
|
never fails a run.** `bin/report.mjs`'s `reportFindings` draws this line once
|
|
285
285
|
for the commands built from the package's pure rule functions (`package-build
|
|
286
286
|
lint`, `package-build lang check`, `package-build lang coverage`,
|
|
287
|
-
`package-build yaml
|
|
287
|
+
`package-build yaml`): it emits every finding
|
|
288
288
|
and returns only the count whose `severity` is `error`, and the command sets
|
|
289
289
|
`process.exitCode = 1` exactly when that count is nonzero. Commands whose
|
|
290
290
|
findings are hand-assembled — `package-build links`, `package-build
|
|
@@ -335,7 +335,6 @@ over one would teach people to stop reading the report.
|
|
|
335
335
|
| `package-build lang check` | any localization finding is `error`-severity |
|
|
336
336
|
| `package-build lang coverage` | a referenced key is missing (`error`-severity); an unreferenced key is always advisory and never fails the run |
|
|
337
337
|
| `package-build yaml [paths..]` | any YAML finding is `error`-severity |
|
|
338
|
-
| `package-build labels check` | the label registry and the documented table disagree on any label |
|
|
339
338
|
|
|
340
339
|
Every command also fails on a thrown error unrelated to a
|
|
341
340
|
diagnostic — a missing configuration, an unreadable file, a network failure —
|
package/docs/guides/e2e.md
CHANGED
|
@@ -159,3 +159,41 @@ major version or moving tag is refused, because the result must name the
|
|
|
159
159
|
build actually tested. A passing sweep provides evidence for choosing a
|
|
160
160
|
new `compatibility.verified` value; a routine run exercises the pinned
|
|
161
161
|
minimum build.
|
|
162
|
+
|
|
163
|
+
## An S3 server for the container
|
|
164
|
+
|
|
165
|
+
A suite that exercises S3 storage needs an S3-compatible server the browser and
|
|
166
|
+
Foundry both reach. Setting `FOUNDRYVTT_CONTAINER_S3=1` when a container is
|
|
167
|
+
created (`start`, `recreate`; through `e2e:fast --recreate` as well) provides one.
|
|
168
|
+
Without it nothing changes: no network, no server, no extra environment.
|
|
169
|
+
|
|
170
|
+
With it, before Foundry starts:
|
|
171
|
+
|
|
172
|
+
- A user-defined network named `<container>-net` is created, and the Foundry
|
|
173
|
+
container is created on it.
|
|
174
|
+
- A SeaweedFS server (`chrislusf/seaweedfs:3.80`) named `<container>-s3` joins
|
|
175
|
+
the network under the alias `s3.localhost` and publishes port 8333. Chromium
|
|
176
|
+
resolves every `*.localhost` name to loopback, so `http://s3.localhost:8333`
|
|
177
|
+
reaches the server from the browser and, through the alias, from the
|
|
178
|
+
container. Its CORS allows every origin.
|
|
179
|
+
- The bucket `sohl-e2e` is created. Anonymous read and the test credentials come
|
|
180
|
+
from the identities file the server is started with.
|
|
181
|
+
- The repository's `cypress/s3/aws-e2e.json` is copied into the data root's
|
|
182
|
+
`Config/`, and the container is created with `FOUNDRY_AWS_CONFIG=aws-e2e.json`.
|
|
183
|
+
|
|
184
|
+
The repository supplies both files: `cypress/s3/s3-identities.json` (the
|
|
185
|
+
SeaweedFS identities, including an `anonymous` identity with `Read`) and
|
|
186
|
+
`cypress/s3/aws-e2e.json` (Foundry's `awsConfig`, pointing at
|
|
187
|
+
`http://s3.localhost:8333`). The credentials are test-only. A missing file stops
|
|
188
|
+
the start and names it.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
FOUNDRYVTT_CONTAINER_S3=1 npm run e2e:fast -- --recreate
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The container's environment is fixed when it is created, so an existing
|
|
195
|
+
container started with the variable set joins the network but keeps the
|
|
196
|
+
environment it was created with; `--recreate` applies `FOUNDRY_AWS_CONFIG`.
|
|
197
|
+
`package-build container <stage> rm` with the variable set removes the server
|
|
198
|
+
and the network along with the container. The server is otherwise left running
|
|
199
|
+
between runs, bucket intact.
|
package/docs/guides/icons.md
CHANGED
|
@@ -68,6 +68,11 @@ defaults point into the system's `assets/images/` and `assets/icons/` trees,
|
|
|
68
68
|
introduced by [HM3's asset-path migration](https://git.pupluppy.org/HeroicLands/HarnMaster-3-FoundryVTT/pulls/60).
|
|
69
69
|
Use these defaults with an HM3 release that includes those assets.
|
|
70
70
|
|
|
71
|
+
A compiled document reaches each icon in the deployed layout — the type root
|
|
72
|
+
and the basename, `systems/sohl/icons/person.svg` — whatever directories hold
|
|
73
|
+
it in the repository, and states its address in `flags.<system>.assets`. See
|
|
74
|
+
[what a package ships](../reference/format-details.md#what-a-package-ships).
|
|
75
|
+
|
|
71
76
|
## Write an inline icon in prose
|
|
72
77
|
|
|
73
78
|
Declare the glyph vocabulary in `package-build.config.yaml` or a separate YAML
|
|
@@ -861,7 +861,7 @@ everything that reads the tree runs before everything that writes the stage.
|
|
|
861
861
|
|
|
862
862
|
[`project-setup.md`](../project-setup.md) turns this into npm scripts, and covers
|
|
863
863
|
everything a repository carries beyond the build itself: the git hooks, the
|
|
864
|
-
changeset directory,
|
|
864
|
+
changeset directory, and what each script in the chain is
|
|
865
865
|
for.
|
|
866
866
|
|
|
867
867
|
## What comes next
|
|
@@ -47,7 +47,10 @@ manifest under `build/dist/`. The ZIP contains the staged tree at its root,
|
|
|
47
47
|
which is the shape Foundry installs. When the manifest advertises a content
|
|
48
48
|
index, the corresponding metadata JSONL is also placed beside the ZIP. A
|
|
49
49
|
manifest that advertises an index the build has not produced fails the
|
|
50
|
-
release. An opted-in staged `schema.json` is published beside it too.
|
|
50
|
+
release. An opted-in staged `schema.json` is published beside it too. A
|
|
51
|
+
package whose stage holds pictures also gets `icons.zip` and `images.zip`:
|
|
52
|
+
each holds one picture root of the stage, flat, with the package's asset
|
|
53
|
+
set `asset-sets/default.json`, so a GM can place the files by hand.
|
|
51
54
|
|
|
52
55
|
When the package publishes content and has a book configuration, the release
|
|
53
56
|
also builds a PDF beside the archive. Book findings are reported without
|
|
@@ -128,6 +131,38 @@ the same stage;
|
|
|
128
131
|
[container command](../commands.md#package-build-container-stage-action) for
|
|
129
132
|
the other actions and environment variables.
|
|
130
133
|
|
|
134
|
+
## Publish pictures to the CDN
|
|
135
|
+
|
|
136
|
+
The website draws every picture a package has from
|
|
137
|
+
`<site.assets>/<contentPackage>/`, and the art a Foundry package leaves out
|
|
138
|
+
reaches a world from there as a named asset set. `package-build cdn publish`
|
|
139
|
+
is the one command that writes there:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
package-build cdn publish --set alt-art.json --name "Thalorna — illustrated" --dry-run
|
|
143
|
+
package-build cdn publish --set alt-art.json --name "Thalorna — illustrated"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
It uploads every icon and image flat, transformed as the stage transforms
|
|
147
|
+
them, skips what the CDN already holds at the same size, and writes
|
|
148
|
+
`<site.assets>/<contentPackage>/alt-art.json` listing the left-out pictures.
|
|
149
|
+
Run it after the pictures or their provenance change; it is not part of a
|
|
150
|
+
build or a release.
|
|
151
|
+
|
|
152
|
+
The bucket's credentials go in `.env.local` beside the stage paths:
|
|
153
|
+
|
|
154
|
+
```dotenv
|
|
155
|
+
CDN_ENDPOINT=https://<account id>.r2.cloudflarestorage.com
|
|
156
|
+
CDN_BUCKET=<bucket>
|
|
157
|
+
CDN_ACCESS_KEY_ID=<access key id>
|
|
158
|
+
CDN_SECRET_ACCESS_KEY=<secret access key>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
A dry run with none of them set compares against the public CDN instead. A
|
|
162
|
+
dispatched workflow passes the same four values as named secrets. See the
|
|
163
|
+
[command reference](../commands.md#package-build-cdn-publish) for the set
|
|
164
|
+
file's shape, the refusals and the exit status.
|
|
165
|
+
|
|
131
166
|
## Publish a package-build npm version
|
|
132
167
|
|
|
133
168
|
For this toolchain's own npm release, a pull request with a change installers
|