@heroiclands/package-build 23.4.0 → 23.5.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 +34 -0
- package/README.md +29 -25
- package/assets/images/provenance.yaml +1 -0
- package/bin/package-build.mjs +259 -28
- 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 -7
- package/docs/configuration.md +39 -2
- package/docs/content-format.md +30 -6
- package/docs/guides/e2e.md +38 -0
- package/docs/guides/icons.md +5 -0
- package/docs/guides/release-and-deploy.md +36 -1
- package/docs/reference/format-details.md +218 -50
- package/docs/reference/note-types.md +71 -71
- 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 +618 -0
- package/engine/index.mjs +6 -0
- package/engine/note-vocabulary.mjs +40 -2
- package/engine/pathnames.mjs +21 -10
- package/engine/rank-ladder.mjs +40 -16
- package/engine/scenes.mjs +1 -1
- package/engine/standing-terms.mjs +3 -1
- package/package.json +4 -3
- 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 +311 -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/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**
|
|
@@ -1138,7 +1153,9 @@ states it a second time. It also publishes the content index the manifest
|
|
|
1138
1153
|
advertises (`flags.metadataUrl`) and, when the stage carries one,
|
|
1139
1154
|
`schema.json` — a repository that names `build/schema.json` in
|
|
1140
1155
|
`packageBuild.assets` gets it released beside the archive; one that does not
|
|
1141
|
-
gets none. When the
|
|
1156
|
+
gets none. When the stage carries `asset-sets/default.json`, it writes
|
|
1157
|
+
`icons.zip` and `images.zip` too, one per picture root the stage holds, each
|
|
1158
|
+
with that set. When the content tree holds notes beyond its homepage, it
|
|
1142
1159
|
also builds the content-tree book (see `package-build pdf`) and reports it
|
|
1143
1160
|
alongside the archive; `--no-pdf` skips that step for a release that has a
|
|
1144
1161
|
tree but does not want the book this time. A book that fails to build is
|
|
@@ -1246,6 +1263,134 @@ Deployed stage 'test' successfully.
|
|
|
1246
1263
|
`package-build container <stage> <action>`, `package-build e2e <action>`,
|
|
1247
1264
|
[Configuration](configuration.md).
|
|
1248
1265
|
|
|
1266
|
+
### `package-build cdn publish`
|
|
1267
|
+
|
|
1268
|
+
**NAME**
|
|
1269
|
+
|
|
1270
|
+
Upload every picture the package has to the CDN, and publish the art the
|
|
1271
|
+
package leaves out as a named asset set.
|
|
1272
|
+
|
|
1273
|
+
**SYNOPSIS**
|
|
1274
|
+
|
|
1275
|
+
```
|
|
1276
|
+
package-build cdn publish --set <file> --name <display name> [--dry-run]
|
|
1277
|
+
```
|
|
1278
|
+
|
|
1279
|
+
**DESCRIPTION**
|
|
1280
|
+
|
|
1281
|
+
The one writer to `<site.assets>/<contentPackage>/`. It is run by hand, or by
|
|
1282
|
+
a manually dispatched workflow; no build or release runs it.
|
|
1283
|
+
|
|
1284
|
+
Every icon and image under the package's picture roots is uploaded flat, as
|
|
1285
|
+
`icons/<basename>` or `images/<basename>` — shipped and left-out pictures
|
|
1286
|
+
alike, because the website draws every one of them from the same address the
|
|
1287
|
+
site build gives it. `packageBuild.assetTransform` runs on each file exactly
|
|
1288
|
+
as `package-build assets` runs it, so a picture on the CDN holds the bytes the
|
|
1289
|
+
staged package holds. SVG is served as `image/svg+xml`.
|
|
1290
|
+
|
|
1291
|
+
The bucket is served at `site.assets`, so an object's key is its path below
|
|
1292
|
+
that address: `thalorna/images/thorn.webp` is
|
|
1293
|
+
`https://cdn.heroiclands.org/thalorna/images/thorn.webp`.
|
|
1294
|
+
|
|
1295
|
+
`--set` names the set file, written at `<site.assets>/<contentPackage>/<file>`.
|
|
1296
|
+
It lists only the pictures the package leaves out — an address a set does not
|
|
1297
|
+
list resolves to the shipped copy — chosen by the same rule the stage applies,
|
|
1298
|
+
`packageBuild.shippingLicenses` included. Its shape is the shipped set's, with
|
|
1299
|
+
each `source` the file's absolute CDN address:
|
|
1300
|
+
|
|
1301
|
+
```json
|
|
1302
|
+
{
|
|
1303
|
+
"name": "Thalorna — illustrated",
|
|
1304
|
+
"package": "thalorna",
|
|
1305
|
+
"assets": [
|
|
1306
|
+
{
|
|
1307
|
+
"address": "thalorna-none-image-thorn",
|
|
1308
|
+
"source": "https://cdn.heroiclands.org/thalorna/images/thorn.webp",
|
|
1309
|
+
"target": "images/thorn.webp",
|
|
1310
|
+
"size": 48213
|
|
1311
|
+
}
|
|
1312
|
+
]
|
|
1313
|
+
}
|
|
1314
|
+
```
|
|
1315
|
+
|
|
1316
|
+
Several sets may sit side by side under one package, each with its own file
|
|
1317
|
+
name. `default.json` is refused: it is the shipped set's name.
|
|
1318
|
+
|
|
1319
|
+
A picture whose object already exists at the same size is skipped, and the set
|
|
1320
|
+
file is skipped when its bytes are unchanged, so a second run uploads nothing.
|
|
1321
|
+
A picture that fails to upload is reported and the rest carry on; the set file
|
|
1322
|
+
is then withheld, since it would list a file the CDN does not hold.
|
|
1323
|
+
|
|
1324
|
+
**Refusals and reports.** A file under `icons/` or `images/` whose name is no
|
|
1325
|
+
address — a basename that is not a shortcode, or two files claiming one — and
|
|
1326
|
+
a provenance record that cannot be read stop the run before anything is
|
|
1327
|
+
uploaded, each reported against its file. A note naming a picture the package
|
|
1328
|
+
does not have, and a note naming left-out art that is not on the CDN when the
|
|
1329
|
+
run ends, are warnings at the note's line and column: an art slot under
|
|
1330
|
+
`data:`, an embed, or a body image.
|
|
1331
|
+
|
|
1332
|
+
**Credentials.** The store is an S3-compatible bucket — Cloudflare R2 for
|
|
1333
|
+
`cdn.heroiclands.org` — signed with AWS Signature Version 4. Its settings are
|
|
1334
|
+
read from the environment, after `.env.local` and `.env` are loaded:
|
|
1335
|
+
|
|
1336
|
+
| Variable | What it is |
|
|
1337
|
+
| ----------------------- | ------------------------------------------------------------------------- |
|
|
1338
|
+
| `CDN_ENDPOINT` | The S3 endpoint; for R2, `https://<account id>.r2.cloudflarestorage.com`. |
|
|
1339
|
+
| `CDN_BUCKET` | The bucket served at `site.assets`. |
|
|
1340
|
+
| `CDN_ACCESS_KEY_ID` | The access key id of a token that can write the bucket. |
|
|
1341
|
+
| `CDN_SECRET_ACCESS_KEY` | That token's secret. Never printed. |
|
|
1342
|
+
|
|
1343
|
+
Setting some but not all of them is an error naming the missing ones. With
|
|
1344
|
+
none set, `--dry-run` compares against the public CDN at `site.assets`
|
|
1345
|
+
instead, read-only, and an upload is refused.
|
|
1346
|
+
|
|
1347
|
+
A workflow calls the command the same way, passing the four values as named
|
|
1348
|
+
secrets in the step's environment:
|
|
1349
|
+
|
|
1350
|
+
```yaml
|
|
1351
|
+
- run: npx package-build cdn publish --set ai-art.json --name "Thalorna — illustrated"
|
|
1352
|
+
env:
|
|
1353
|
+
CDN_ENDPOINT: ${{ secrets.CDN_ENDPOINT }}
|
|
1354
|
+
CDN_BUCKET: ${{ secrets.CDN_BUCKET }}
|
|
1355
|
+
CDN_ACCESS_KEY_ID: ${{ secrets.CDN_ACCESS_KEY_ID }}
|
|
1356
|
+
CDN_SECRET_ACCESS_KEY: ${{ secrets.CDN_SECRET_ACCESS_KEY }}
|
|
1357
|
+
```
|
|
1358
|
+
|
|
1359
|
+
**OPTIONS**
|
|
1360
|
+
|
|
1361
|
+
| Option | Type | Default | Description |
|
|
1362
|
+
| ----------- | ------- | ------- | --------------------------------------------------------------------------- |
|
|
1363
|
+
| `--set` | string | — | Required. The set file's name under the package's CDN root, a `.json` file. |
|
|
1364
|
+
| `--name` | string | — | Required. The set's display name. |
|
|
1365
|
+
| `--dry-run` | boolean | `false` | List what would upload and what is skipped; write nothing. |
|
|
1366
|
+
|
|
1367
|
+
**EXIT STATUS**
|
|
1368
|
+
|
|
1369
|
+
1 when a picture's file has no address, when a picture fails to upload, when
|
|
1370
|
+
`--set` is `default.json` or a path, when `site.assets` is undeclared, and
|
|
1371
|
+
when an upload has no store configured. Warnings about notes do not change
|
|
1372
|
+
it. Otherwise 0.
|
|
1373
|
+
|
|
1374
|
+
**EXAMPLES**
|
|
1375
|
+
|
|
1376
|
+
```
|
|
1377
|
+
$ package-build cdn publish --set ai-art.json --name "Thalorna — illustrated" --dry-run
|
|
1378
|
+
Dry run: comparing 582 pictures against https://cdn.heroiclands.org, read-only.
|
|
1379
|
+
would upload thalorna/icons/anvilbdg.svg (969 bytes)
|
|
1380
|
+
…
|
|
1381
|
+
would upload thalorna/ai-art.json (582 assets)
|
|
1382
|
+
Would upload 582, skipped 0, failed 0; https://cdn.heroiclands.org/thalorna/ai-art.json lists 582 left-out pictures (would change).
|
|
1383
|
+
|
|
1384
|
+
$ package-build cdn publish --set default.json --name Shipped
|
|
1385
|
+
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
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
**SEE ALSO**
|
|
1389
|
+
|
|
1390
|
+
`package-build assets`, `package-build release`,
|
|
1391
|
+
[Configuration](configuration.md#site),
|
|
1392
|
+
[Release and deploy](guides/release-and-deploy.md#publish-pictures-to-the-cdn).
|
|
1393
|
+
|
|
1249
1394
|
### `package-build container <stage> <action>`
|
|
1250
1395
|
|
|
1251
1396
|
**NAME**
|
|
@@ -1306,7 +1451,9 @@ exact pin takes the major tag of its pin or of `compatibility.minimum`
|
|
|
1306
1451
|
mount), `FOUNDRYVTT_CONTAINER_USER` (passed to `docker run --user`; `0:0`
|
|
1307
1452
|
under rootless Docker makes the data root's files belong to the host user,
|
|
1308
1453
|
because the image otherwise runs Foundry as user 1000 and ignores
|
|
1309
|
-
`FOUNDRY_UID` and `FOUNDRY_GID`)
|
|
1454
|
+
`FOUNDRY_UID` and `FOUNDRY_GID`), `FOUNDRYVTT_CONTAINER_S3` (`1` or `true`
|
|
1455
|
+
runs an S3-compatible server beside the container; see
|
|
1456
|
+
[an S3 server for the container](guides/e2e.md#an-s3-server-for-the-container)).
|
|
1310
1457
|
|
|
1311
1458
|
**EXIT STATUS**
|
|
1312
1459
|
|
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/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
|
|
@@ -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 ai-art.json --name "Thalorna — illustrated" --dry-run
|
|
143
|
+
package-build cdn publish --set ai-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>/ai-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
|