@heroiclands/package-build 0.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG-content-build.md +965 -0
  2. package/CHANGELOG.md +95 -0
  3. package/CONTENT.md +824 -0
  4. package/MIGRATING.md +127 -0
  5. package/README.md +29 -17
  6. package/bin/content-build.mjs +1082 -0
  7. package/bin/package-build.mjs +2 -2
  8. package/bin/report.mjs +2 -2
  9. package/config.mjs +21 -18
  10. package/content-config.mjs +1424 -0
  11. package/coverage.mjs +1 -1
  12. package/e2e.mjs +1 -1
  13. package/engine/abbreviations.mjs +0 -0
  14. package/engine/base-compiler.mjs +608 -0
  15. package/engine/code-fences.mjs +311 -0
  16. package/engine/compendiums.mjs +353 -0
  17. package/engine/content-address.mjs +141 -0
  18. package/engine/content-links.mjs +438 -0
  19. package/engine/content-lint.mjs +204 -0
  20. package/engine/content-package.mjs +67 -0
  21. package/engine/content-slug.mjs +169 -0
  22. package/engine/content-tables.mjs +1216 -0
  23. package/engine/content-tree.mjs +56 -0
  24. package/engine/diagnostics.mjs +270 -0
  25. package/engine/field-reference.mjs +242 -0
  26. package/engine/field-spec.mjs +218 -0
  27. package/engine/foreign-catalog.mjs +450 -0
  28. package/engine/foreign-manifests.mjs +129 -0
  29. package/engine/frontmatter-lint.mjs +343 -0
  30. package/engine/frontmatter.mjs +258 -0
  31. package/engine/generate.mjs +305 -0
  32. package/engine/helpers.mjs +809 -0
  33. package/engine/ids.mjs +192 -0
  34. package/engine/index.mjs +142 -0
  35. package/engine/item-docs.mjs +153 -0
  36. package/engine/item-registry.mjs +129 -0
  37. package/engine/journals.mjs +374 -0
  38. package/engine/kb-manifest.mjs +473 -0
  39. package/engine/macros.mjs +333 -0
  40. package/engine/manifest-emit.mjs +339 -0
  41. package/engine/map-notes.mjs +1302 -0
  42. package/engine/pack-config.mjs +479 -0
  43. package/engine/pack-router.mjs +254 -0
  44. package/engine/prose-config.mjs +238 -0
  45. package/engine/prose-lint.mjs +294 -0
  46. package/engine/region-events.mjs +79 -0
  47. package/engine/scene-levels.mjs +420 -0
  48. package/engine/scenes.mjs +528 -0
  49. package/engine/site-build.mjs +778 -0
  50. package/engine/site-index.mjs +332 -0
  51. package/engine/web-wikilinks.mjs +330 -0
  52. package/engine/wikilink-syntax.mjs +105 -0
  53. package/engine/wikilinks.mjs +645 -0
  54. package/index.mjs +42 -25
  55. package/lang.mjs +1 -1
  56. package/manifest.mjs +79 -5
  57. package/markdownlint-config.mjs +45 -0
  58. package/package.json +78 -34
  59. package/prettier-config.mjs +34 -0
  60. package/sohl/actors.mjs +581 -0
  61. package/sohl/affiliation-standings.mjs +44 -0
  62. package/sohl/being-info.mjs +173 -0
  63. package/sohl/default-item-art.mjs +82 -0
  64. package/sohl/index.mjs +55 -0
  65. package/sohl/item-builders.mjs +114 -0
  66. package/sohl/item-fields.mjs +867 -0
  67. package/sohl/items.mjs +197 -0
  68. package/sohl/kb-passes.mjs +207 -0
  69. package/sohl/note-schemas.mjs +322 -0
  70. package/templates.mjs +1 -1
  71. package/types/config.d.mts +1 -1
  72. package/types/content-config.d.mts +571 -0
  73. package/types/engine/abbreviations.d.mts +44 -0
  74. package/types/engine/base-compiler.d.mts +320 -0
  75. package/types/engine/code-fences.d.mts +102 -0
  76. package/types/engine/compendiums.d.mts +77 -0
  77. package/types/engine/content-address.d.mts +61 -0
  78. package/types/engine/content-links.d.mts +87 -0
  79. package/types/engine/content-lint.d.mts +47 -0
  80. package/types/engine/content-package.d.mts +36 -0
  81. package/types/engine/content-slug.d.mts +59 -0
  82. package/types/engine/content-tables.d.mts +131 -0
  83. package/types/engine/content-tree.d.mts +12 -0
  84. package/types/engine/diagnostics.d.mts +152 -0
  85. package/types/engine/field-reference.d.mts +20 -0
  86. package/types/engine/field-spec.d.mts +181 -0
  87. package/types/engine/foreign-catalog.d.mts +103 -0
  88. package/types/engine/foreign-manifests.d.mts +43 -0
  89. package/types/engine/frontmatter-lint.d.mts +74 -0
  90. package/types/engine/frontmatter.d.mts +99 -0
  91. package/types/engine/generate.d.mts +56 -0
  92. package/types/engine/helpers.d.mts +348 -0
  93. package/types/engine/ids.d.mts +126 -0
  94. package/types/engine/index.d.mts +33 -0
  95. package/types/engine/item-docs.d.mts +73 -0
  96. package/types/engine/item-registry.d.mts +57 -0
  97. package/types/engine/journals.d.mts +121 -0
  98. package/types/engine/kb-manifest.d.mts +214 -0
  99. package/types/engine/macros.d.mts +201 -0
  100. package/types/engine/manifest-emit.d.mts +137 -0
  101. package/types/engine/map-notes.d.mts +283 -0
  102. package/types/engine/pack-config.d.mts +77 -0
  103. package/types/engine/pack-router.d.mts +53 -0
  104. package/types/engine/prose-config.d.mts +121 -0
  105. package/types/engine/prose-lint.d.mts +59 -0
  106. package/types/engine/region-events.d.mts +43 -0
  107. package/types/engine/scene-levels.d.mts +36 -0
  108. package/types/engine/scenes.d.mts +48 -0
  109. package/types/engine/site-build.d.mts +214 -0
  110. package/types/engine/site-index.d.mts +141 -0
  111. package/types/engine/web-wikilinks.d.mts +67 -0
  112. package/types/engine/wikilink-syntax.d.mts +101 -0
  113. package/types/engine/wikilinks.d.mts +172 -0
  114. package/types/index.d.mts +3 -0
  115. package/types/manifest.d.mts +52 -4
  116. package/types/markdownlint-config.d.mts +8 -0
  117. package/types/prettier-config.d.mts +1 -0
  118. package/types/sohl/actors.d.mts +65 -0
  119. package/types/sohl/affiliation-standings.d.mts +22 -0
  120. package/types/sohl/being-info.d.mts +78 -0
  121. package/types/sohl/default-item-art.d.mts +28 -0
  122. package/types/sohl/index.d.mts +7 -0
  123. package/types/sohl/item-builders.d.mts +11 -0
  124. package/types/sohl/item-fields.d.mts +20 -0
  125. package/types/sohl/items.d.mts +19 -0
  126. package/types/sohl/kb-passes.d.mts +71 -0
  127. package/types/sohl/note-schemas.d.mts +7 -0
package/index.mjs CHANGED
@@ -13,58 +13,75 @@
13
13
 
14
14
  /**
15
15
  * `@heroiclands/package-build` — the shared toolchain for building and shipping
16
- * a HeroicLands **Foundry package**.
16
+ * a HeroicLands **Foundry package**, content and all.
17
17
  *
18
- * It is the counterpart to `@heroiclands/content-build`, and the two split by
19
- * **input**, not by repository:
18
+ * This package was two: `content-build`, which read `assets/content/**` and
19
+ * produced compendium packs, site content and the link manifest, and this one,
20
+ * which read `lang/`, `styles/`, `src/` and the manifest template. They were
21
+ * split by *input* on the theory that a module would use either — an adventure
22
+ * shipping only notes needs no bundler, a variant shipping only behavior needs
23
+ * no Markdown pipeline.
20
24
  *
21
- * - content-build reads `assets/content/**` and produces compendium packs, site
22
- * content and the link manifest. It answers for what a package *says*.
23
- * - this package reads `lang/`, `styles/`, `src/`, `assets/` and the manifest
24
- * template. It answers for what a package *is* the parts Foundry loads
25
- * whether or not the package ships any content at all.
26
- *
27
- * A module uses either, or both. An adventure module that ships only notes
28
- * needs no bundler; a variant module that ships only behavior needs no Markdown
29
- * pipeline. The coupling between the two packages runs one way — this one asks
30
- * content-build for the compiled `packs[]` block, never the reverse.
25
+ * **No consumer ever used one alone.** All three installed both, and this
26
+ * package depended on the other besides, so the packaging half dragged the
27
+ * content half in regardless. What the boundary actually cost was a
28
+ * configuration file with two owners, two CLIs with a colliding `manifest`
29
+ * command, and a two-repository dance for changes that touched one idea. The
30
+ * two halves are now one package; the split survives as the shape of this
31
+ * barrel and nothing more.
31
32
  *
32
33
  * **Everything exported here is pure.** Functions take source text and return
33
34
  * findings or values; discovery, I/O and reporting stay with the caller. That
34
35
  * is what lets one rule set serve a `lint` script, a build step and a unit test
35
36
  * without any of them having to agree on how files are found or how findings
36
- * are printed — and it is what makes the rules testable at all, which the
37
- * scripts these were extracted from were not.
37
+ * are printed.
38
38
  *
39
39
  * @module
40
40
  */
41
41
 
42
- /** The Foundry package manifest: `system.json` / `module.json`. */
42
+ // ── Content: notes to compendium packs, site content, link manifests ────────
43
+
44
+ /** The configuration contract a consuming repository declares its build with. */
45
+ export {
46
+ defineConfig,
47
+ PACKAGE_KINDS,
48
+ PACK_DOCUMENT_TYPES,
49
+ } from "./content-config.mjs";
50
+
51
+ /** The content pipeline — walking, compiling, linking, emitting. */
52
+ export * as engine from "./engine/index.mjs";
53
+
54
+ /** The `sohl` system's own item and actor builders. */
55
+ export * as sohl from "./sohl/index.mjs";
56
+
57
+ // ── Package: manifest, localization, staging, bundle, release, deployment ───
58
+
59
+ /** Foundry package manifest generation. */
43
60
  export * as manifest from "./manifest.mjs";
44
61
 
45
- /** The code bundle, and whether the manifest agrees with how it parses. */
62
+ /** Bundle construction and the bundle-loading check. */
46
63
  export * as bundle from "./bundle.mjs";
47
64
 
48
- /** Assembling the build stage, and clearing it away again. */
65
+ /** Staging a built package into a Foundry data directory. */
49
66
  export * as stage from "./stage.mjs";
50
67
 
51
- /** The release archive a GitHub Release carries. */
68
+ /** The changesets-driven release pipeline. */
52
69
  export * as release from "./release.mjs";
53
70
 
54
- /** Deploying a staged package into a Foundry data directory. */
71
+ /** Deployment to a remote host. */
55
72
  export * as deploy from "./deploy.mjs";
56
73
 
57
- /** Running a built package inside a Foundry VTT container. */
74
+ /** Container stages for a reproducible Foundry environment. */
58
75
  export * as container from "./container.mjs";
59
76
 
60
- /** The end-to-end harness: a disposable world, served, with a suite driven at it. */
77
+ /** The end-to-end harness. */
61
78
  export * as e2e from "./e2e.mjs";
62
79
 
63
- /** Localization files: what a shippable `lang/*.json` must satisfy. */
80
+ /** Localization shape and coverage rules. */
64
81
  export * as lang from "./lang.mjs";
65
82
 
66
- /** Localization coverage: the keys a package references against the keys it declares. */
83
+ /** Coverage reporting. */
67
84
  export * as coverage from "./coverage.mjs";
68
85
 
69
- /** Templates: whether their user-visible text is localized, and whether they compile. */
86
+ /** Handlebars template rules. */
70
87
  export * as templates from "./templates.mjs";
package/lang.mjs CHANGED
@@ -45,7 +45,7 @@
45
45
  * @module
46
46
  */
47
47
 
48
- import { positionOfLiteral } from "@heroiclands/content-build/engine/diagnostics";
48
+ import { positionOfLiteral } from "./engine/diagnostics.mjs";
49
49
 
50
50
  /**
51
51
  * A single finding, in the fields the shared diagnostic format takes.
package/manifest.mjs CHANGED
@@ -160,7 +160,7 @@ const MANIFEST_KEY_ORDER = Object.freeze([
160
160
  /**
161
161
  * The manifest's `packs`, derived from the one pack list the build already has.
162
162
  *
163
- * The two used to be written separately — `content-build.config.yaml` declared
163
+ * The two used to be written separately — `package-build.config.yaml` declared
164
164
  * a pack's name and type, and the manifest template declared them again beside
165
165
  * a label, a path and a system id, with nothing checking that the pairs agreed.
166
166
  * They are one list now.
@@ -170,7 +170,7 @@ const MANIFEST_KEY_ORDER = Object.freeze([
170
170
  * ships as an ordinary compendium. The order matches `packDirectories`, so the
171
171
  * manifest lists packs in the order the build compiles them.
172
172
  *
173
- * @param {object} config - The resolved content-build configuration.
173
+ * @param {object} config - The resolved content configuration.
174
174
  * @returns {object[]} The manifest's `packs` array.
175
175
  */
176
176
  export function manifestPacks(config) {
@@ -188,6 +188,76 @@ export function manifestPacks(config) {
188
188
  }));
189
189
  }
190
190
 
191
+ /**
192
+ * Relationship keys that direct the **build**, rather than describe the
193
+ * package.
194
+ *
195
+ * `relationships` is the one manifest block with a second reader.
196
+ * `@heroiclands/content-build` consumes it too, and v1.8.0 added
197
+ * `itemCatalog: true` as an opt-in on a declared dependency
198
+ * (content-build#82): it selects that package's Item packs as a resolution
199
+ * source for the actors pass. That is an instruction to the build, not a fact
200
+ * about the shipped package — Foundry's relationship schema does not define
201
+ * it, and someone reading a published manifest cannot tell a build directive
202
+ * from a declaration about what the package needs.
203
+ *
204
+ * So the block is filtered rather than copied whole (#29). The rule is the
205
+ * distinction, not the name: a key listed here answers *how is this built?*,
206
+ * and every key that survives answers *what does this package depend on?*.
207
+ * `itemCatalog` is the first build-time key to land on a relationship and is
208
+ * unlikely to be the last.
209
+ *
210
+ * A list is enough, and needs no prefix agreed between the two packages,
211
+ * because the input is already closed: content-build normalises a relationship
212
+ * to `id`, `type`, `manifest`, `compatibility` and its own build keys, and
213
+ * rejects anything else at configuration time. A key that reaches here is one
214
+ * the toolchain itself put there.
215
+ *
216
+ * @type {readonly string[]}
217
+ */
218
+ export const BUILD_ONLY_RELATIONSHIP_KEYS = Object.freeze(["itemCatalog"]);
219
+
220
+ /**
221
+ * The `relationships` block as published — every declared dependency, with the
222
+ * build's own keys dropped.
223
+ *
224
+ * Shape is otherwise preserved: kinds keep their order and their entries, an
225
+ * entry keeps its remaining keys in the order it declared them, and a block
226
+ * carrying no build-only key comes back equal to what went in. Only
227
+ * {@link BUILD_ONLY_RELATIONSHIP_KEYS} are removed — an unrecognised key is
228
+ * left alone, on the same reasoning that lets a declared manifest key through
229
+ * unread: a key Foundry adds later should not need a release of this package.
230
+ *
231
+ * @param {Record<string, unknown>} relationships - The declared block, as
232
+ * content-build resolved it.
233
+ * @returns {Record<string, unknown>} It, without the build-only keys.
234
+ */
235
+ export function publishedRelationships(relationships) {
236
+ const published = {};
237
+ for (const [kind, entries] of Object.entries(relationships)) {
238
+ published[kind] =
239
+ Array.isArray(entries) ? entries.map(withoutBuildKeys) : entries;
240
+ }
241
+ return published;
242
+ }
243
+
244
+ /**
245
+ * One relationship entry, minus the build-only keys.
246
+ *
247
+ * @param {unknown} entry - A declared dependency.
248
+ * @returns {unknown} It, filtered; anything that is not a mapping unchanged.
249
+ */
250
+ function withoutBuildKeys(entry) {
251
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
252
+ return entry;
253
+ }
254
+ return Object.fromEntries(
255
+ Object.entries(entry).filter(
256
+ ([key]) => !BUILD_ONLY_RELATIONSHIP_KEYS.includes(key),
257
+ ),
258
+ );
259
+ }
260
+
191
261
  /**
192
262
  * Build a Foundry package manifest from the resolved configuration.
193
263
  *
@@ -202,8 +272,12 @@ export function manifestPacks(config) {
202
272
  * - **Computed** — namespaced `flags` a repository works out for itself, merged
203
273
  * over any it declared.
204
274
  *
275
+ * `relationships` is derived but not copied whole: the keys that direct the
276
+ * build rather than describe the package are dropped first — see
277
+ * {@link publishedRelationships}.
278
+ *
205
279
  * @param {object} options - Inputs.
206
- * @param {object} options.config - The resolved content-build configuration.
280
+ * @param {object} options.config - The resolved content configuration.
207
281
  * @param {object} options.packageJson - The repository's `package.json`.
208
282
  * @param {string} options.artifact - `system` or `module`.
209
283
  * @param {Record<string, object>} [options.flags] - Namespaced flags to merge.
@@ -221,7 +295,7 @@ export function buildManifest({ config, packageJson, artifact, flags }) {
221
295
  };
222
296
  if (config.compatibility) derived.compatibility = config.compatibility;
223
297
  if (config.relationships && Object.keys(config.relationships).length) {
224
- derived.relationships = config.relationships;
298
+ derived.relationships = publishedRelationships(config.relationships);
225
299
  }
226
300
 
227
301
  const merged = { ...declared, ...derived };
@@ -251,7 +325,7 @@ export function buildManifest({ config, packageJson, artifact, flags }) {
251
325
  * Write the generated manifest into the staged package.
252
326
  *
253
327
  * @param {object} options - As {@link buildManifest}, plus where to write.
254
- * @param {object} options.config - The resolved content-build configuration.
328
+ * @param {object} options.config - The resolved content configuration.
255
329
  * @param {object} options.packageJson - The repository's `package.json`.
256
330
  * @param {string} options.artifact - `system` or `module`.
257
331
  * @param {string} options.outDir - Directory to write into.
@@ -0,0 +1,45 @@
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 shared markdownlint rules, as a markdownlint-cli2 options module.
16
+ *
17
+ * `content-build markdown` applies these without a consumer declaring
18
+ * anything; this is for an editor's markdownlint extension, and for a consumer
19
+ * that wants to *extend* the set rather than replace it:
20
+ *
21
+ * ```js
22
+ * // .markdownlint-cli2.mjs
23
+ * import shared from "@heroiclands/package-build/markdownlint";
24
+ * export default { ...shared, config: { ...shared.config, MD013: true } };
25
+ * ```
26
+ *
27
+ * Spread rather than mutated: {@link MARKDOWNLINT_CONFIG} is frozen, so a
28
+ * consumer that edited it in place would fail loudly rather than change the
29
+ * rules for everything else in its process.
30
+ *
31
+ * @module
32
+ */
33
+
34
+ import {
35
+ MARKDOWNLINT_CONFIG,
36
+ MARKDOWN_GLOBS,
37
+ MARKDOWN_IGNORES,
38
+ } from "./engine/prose-config.mjs";
39
+
40
+ export default {
41
+ config: MARKDOWNLINT_CONFIG,
42
+ globs: [...MARKDOWN_GLOBS],
43
+ ignores: [...MARKDOWN_IGNORES],
44
+ gitignore: true,
45
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@heroiclands/package-build",
3
- "version": "0.6.0",
4
- "description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — manifest, localization, staging, bundle, release and deployment.",
3
+ "version": "3.0.0",
4
+ "description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — content compilation, manifest, localization, staging, bundle, release and deployment.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "type": "module",
7
7
  "main": "./index.mjs",
@@ -11,14 +11,42 @@
11
11
  "types": "./types/index.d.mts",
12
12
  "import": "./index.mjs"
13
13
  },
14
- "./bundle": {
15
- "types": "./types/bundle.d.mts",
16
- "import": "./bundle.mjs"
14
+ "./engine": {
15
+ "types": "./types/engine/index.d.mts",
16
+ "import": "./engine/index.mjs"
17
+ },
18
+ "./engine/*": {
19
+ "types": "./types/engine/*.d.mts",
20
+ "import": "./engine/*.mjs"
21
+ },
22
+ "./sohl": {
23
+ "types": "./types/sohl/index.d.mts",
24
+ "import": "./sohl/index.mjs"
25
+ },
26
+ "./sohl/*": {
27
+ "types": "./types/sohl/*.d.mts",
28
+ "import": "./sohl/*.mjs"
29
+ },
30
+ "./content-config": {
31
+ "types": "./types/content-config.d.mts",
32
+ "import": "./content-config.mjs"
17
33
  },
18
34
  "./config": {
19
35
  "types": "./types/config.d.mts",
20
36
  "import": "./config.mjs"
21
37
  },
38
+ "./prettier": {
39
+ "types": "./types/prettier-config.d.mts",
40
+ "import": "./prettier-config.mjs"
41
+ },
42
+ "./markdownlint": {
43
+ "types": "./types/markdownlint-config.d.mts",
44
+ "import": "./markdownlint-config.mjs"
45
+ },
46
+ "./bundle": {
47
+ "types": "./types/bundle.d.mts",
48
+ "import": "./bundle.mjs"
49
+ },
22
50
  "./container": {
23
51
  "types": "./types/container.d.mts",
24
52
  "import": "./container.mjs"
@@ -43,7 +71,6 @@
43
71
  "types": "./types/manifest.d.mts",
44
72
  "import": "./manifest.mjs"
45
73
  },
46
- "./package.json": "./package.json",
47
74
  "./release": {
48
75
  "types": "./types/release.d.mts",
49
76
  "import": "./release.mjs"
@@ -55,55 +82,78 @@
55
82
  "./templates": {
56
83
  "types": "./types/templates.d.mts",
57
84
  "import": "./templates.mjs"
58
- }
85
+ },
86
+ "./package.json": "./package.json"
87
+ },
88
+ "bin": {
89
+ "package-build": "./bin/package-build.mjs",
90
+ "content-build": "./bin/content-build.mjs"
59
91
  },
60
92
  "files": [
93
+ "CHANGELOG-content-build.md",
61
94
  "CHANGELOG.md",
95
+ "CONTENT.md",
96
+ "MIGRATING.md",
62
97
  "README.md",
63
98
  "bin",
64
99
  "bundle.mjs",
65
100
  "config.mjs",
66
101
  "container.mjs",
102
+ "content-config.mjs",
67
103
  "coverage.mjs",
68
104
  "deploy.mjs",
69
105
  "e2e.mjs",
106
+ "engine",
70
107
  "index.mjs",
71
108
  "lang.mjs",
72
109
  "manifest.mjs",
110
+ "markdownlint-config.mjs",
111
+ "prettier-config.mjs",
73
112
  "release.mjs",
113
+ "sohl",
74
114
  "stage.mjs",
75
115
  "templates.mjs",
76
116
  "types"
77
117
  ],
78
- "scripts": {
79
- "test": "vitest run",
80
- "test:watch": "vitest",
81
- "prepack": "npm run build:types",
82
- "build:types": "tsc -p tsconfig.dts.json",
83
- "format": "prettier --write .",
84
- "format:check": "prettier --check .",
85
- "changeset": "changeset",
86
- "changeset:check": "changeset status --since=origin/main",
87
- "prepare": "git config core.hooksPath .githooks || true"
88
- },
89
118
  "dependencies": {
90
119
  "@foundryvtt/foundryvtt-cli": "^3.0.4",
91
- "@heroiclands/content-build": "^1.0.0",
92
120
  "acorn": "^8.18.0",
93
121
  "archiver": "^8.0.0",
122
+ "classic-level": "^3.0.0",
94
123
  "dotenv": "^17.2.3",
124
+ "fflate": "^0.8.3",
95
125
  "glob": "^11.0.3",
126
+ "gray-matter": "^4.0.3",
96
127
  "handlebars": "^4.7.9",
128
+ "loglevel": "^1.9.2",
129
+ "loglevel-plugin-prefix": "^0.8.4",
130
+ "markdown-it": "^14.1.0",
131
+ "markdownlint-cli2": "^0.23.2",
132
+ "prettier": "^3.9.6",
97
133
  "ssh2-sftp-client": "^12.1.1",
98
134
  "typescript": "^6.0.3",
135
+ "unidecode": "^1.1.0",
136
+ "yaml": "^2.8.1",
99
137
  "yargs": "^18.1.0"
100
138
  },
101
139
  "devDependencies": {
102
140
  "@changesets/cli": "^3.0.0",
103
141
  "@types/node": "^26.2.0",
104
- "prettier": "^3.9.6",
105
142
  "vitest": "^4.1.10"
106
143
  },
144
+ "scripts": {
145
+ "test": "vitest run",
146
+ "test:watch": "vitest",
147
+ "prepack": "npm run build:types",
148
+ "build:types": "tsc -p tsconfig.dts.json",
149
+ "format": "prettier --write .",
150
+ "format:check": "prettier --check .",
151
+ "lint:markdown": "node bin/content-build.mjs markdown",
152
+ "changeset": "changeset",
153
+ "changeset:check": "changeset status --since=origin/main",
154
+ "changeset:version": "changeset version && npm install --package-lock-only",
155
+ "prepare": "git config core.hooksPath .githooks || true"
156
+ },
107
157
  "engines": {
108
158
  "node": ">=24.0.0"
109
159
  },
@@ -111,23 +161,17 @@
111
161
  "access": "public",
112
162
  "provenance": true
113
163
  },
164
+ "repository": {
165
+ "type": "git",
166
+ "url": "git+https://github.com/HeroicLands/package-build.git"
167
+ },
114
168
  "keywords": [
169
+ "build",
170
+ "compendium",
115
171
  "foundry-vtt",
116
172
  "foundryvtt",
117
173
  "heroiclands",
118
174
  "sohl",
119
- "song-of-heroic-lands",
120
- "build"
121
- ],
122
- "homepage": "https://heroiclands.org",
123
- "repository": {
124
- "type": "git",
125
- "url": "git+https://github.com/HeroicLands/package-build.git"
126
- },
127
- "bugs": {
128
- "url": "https://github.com/HeroicLands/package-build/issues"
129
- },
130
- "bin": {
131
- "package-build": "./bin/package-build.mjs"
132
- }
175
+ "song-of-heroic-lands"
176
+ ]
133
177
  }
@@ -0,0 +1,34 @@
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 shared Prettier configuration, as a Prettier config module.
16
+ *
17
+ * `content-build format` already applies these rules without a consumer
18
+ * declaring anything, so this exists for the **editor**: a format-on-save that
19
+ * disagrees with the lint chain is a papercut every contributor hits, and
20
+ * Prettier's editor integrations read a config file rather than asking this
21
+ * package. A consumer gets both to agree with one line:
22
+ *
23
+ * ```js
24
+ * // prettier.config.mjs
25
+ * export { default } from "@heroiclands/package-build/prettier";
26
+ * ```
27
+ *
28
+ * Declaring it this way is still a local config, so it wins over the shipped
29
+ * default in the usual way — it just happens to be the same object.
30
+ *
31
+ * @module
32
+ */
33
+
34
+ export { PRETTIER_CONFIG as default } from "./engine/prose-config.mjs";