@archivist-gg/dnd5e 0.3.1 → 0.3.5

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 (259) hide show
  1. package/LICENSES/SRD.md +25 -6
  2. package/dist/armor/armor.codec.js +4 -3
  3. package/dist/armor/armor.parser.js +3 -2
  4. package/dist/armor/armor.schema.d.ts +4 -0
  5. package/dist/armor/armor.schema.js +2 -1
  6. package/dist/armor/armor.types.d.ts +8 -0
  7. package/dist/background/background.codec.js +7 -6
  8. package/dist/background/background.parser.js +6 -5
  9. package/dist/background/background.schema.d.ts +26 -0
  10. package/dist/background/background.schema.js +5 -4
  11. package/dist/background/background.types.d.ts +22 -0
  12. package/dist/{chunk-4TIJKN6O.js → chunk-23LZLBJK.js} +1 -1
  13. package/dist/{chunk-AFKTJXRA.js → chunk-2DFENQIJ.js} +18 -0
  14. package/dist/chunk-2FRUSVZS.js +489 -0
  15. package/dist/chunk-2VDTW7QO.js +1580 -0
  16. package/dist/{chunk-ZZGEVJKX.js → chunk-3JOTQW7A.js} +1 -1
  17. package/dist/{chunk-5ZBE4CWV.js → chunk-3PZHBLFG.js} +1 -1
  18. package/dist/chunk-4U55VNC7.js +22 -0
  19. package/dist/{chunk-4JHOHWBI.js → chunk-4XTNPNQB.js} +1 -1
  20. package/dist/{chunk-HCP3GMHS.js → chunk-5N2GW72F.js} +15 -2
  21. package/dist/{chunk-42Y5IJKT.js → chunk-5RKLL2AD.js} +5 -1
  22. package/dist/{chunk-SE7AZDR3.js → chunk-63XQXPZL.js} +29 -3
  23. package/dist/{chunk-4F6AIZ36.js → chunk-6BFWZW6T.js} +1 -1
  24. package/dist/{chunk-GJOI2GHP.js → chunk-6GNXYAYP.js} +1 -1
  25. package/dist/{chunk-66XXW2Z2.js → chunk-6PXTNCBP.js} +2 -2
  26. package/dist/chunk-6X2NV665.js +33 -0
  27. package/dist/{chunk-LV4SNWZQ.js → chunk-6X4KUDMU.js} +8 -1
  28. package/dist/{chunk-ZMR77DDL.js → chunk-AW3EHF3L.js} +1 -1
  29. package/dist/{chunk-TLYDBT5F.js → chunk-CGRLQ34U.js} +64 -7
  30. package/dist/chunk-CJYCVNW2.js +7 -0
  31. package/dist/{chunk-XLSVNUTK.js → chunk-CV5XDJKU.js} +1 -1
  32. package/dist/{chunk-RAWJTA45.js → chunk-DEEHHLAP.js} +1 -1
  33. package/dist/{chunk-6IRYTM5V.js → chunk-DPUJDOKV.js} +119 -28
  34. package/dist/{chunk-GE4TLPWM.js → chunk-EHDATXP7.js} +1 -1
  35. package/dist/chunk-EVMUJYUD.js +195 -0
  36. package/dist/{chunk-K6Q5OUGK.js → chunk-GFZ7PITJ.js} +86 -10
  37. package/dist/{chunk-6NK2MUD3.js → chunk-HZA7OE7N.js} +9 -2
  38. package/dist/{chunk-TN6ZLTNU.js → chunk-I2NDWFDD.js} +51 -4
  39. package/dist/{chunk-3DZ74AKK.js → chunk-IN4M4X7P.js} +8 -2
  40. package/dist/chunk-IUAAXXNO.js +58 -0
  41. package/dist/{chunk-NXSWH3AE.js → chunk-IWRVOCT5.js} +1 -1
  42. package/dist/{chunk-XJNECUPT.js → chunk-JC5UNIVM.js} +19 -0
  43. package/dist/{chunk-24GFQU7T.js → chunk-JSZ4H6AQ.js} +1 -1
  44. package/dist/{chunk-XTIQWSFM.js → chunk-KADJZGZY.js} +1 -1
  45. package/dist/{chunk-L7E2UT5A.js → chunk-KK33PIDN.js} +5 -1
  46. package/dist/chunk-KPEJMNRD.js +302 -0
  47. package/dist/chunk-KU3YLF6D.js +106 -0
  48. package/dist/{chunk-5INR4NSL.js → chunk-LDDCNPHD.js} +1 -1
  49. package/dist/chunk-LVQLWRCU.js +15 -0
  50. package/dist/chunk-MI7P3NX3.js +161 -0
  51. package/dist/{chunk-PHQRGDRQ.js → chunk-N3A5ICBO.js} +5 -1
  52. package/dist/chunk-O4SRD3J5.js +165 -0
  53. package/dist/chunk-OAXWSVJB.js +81 -0
  54. package/dist/chunk-OZP6JFGT.js +162 -0
  55. package/dist/{chunk-NAEPSZAM.js → chunk-PDJSUH24.js} +24 -2
  56. package/dist/chunk-PP2UHLBA.js +50 -0
  57. package/dist/chunk-PVCEA4HZ.js +6 -0
  58. package/dist/{chunk-RSDRMH54.js → chunk-RF4TYCA2.js} +1 -1
  59. package/dist/chunk-RLGQ5PZZ.js +16 -0
  60. package/dist/chunk-RVXC6ZHY.js +89 -0
  61. package/dist/chunk-S7REMWW4.js +21 -0
  62. package/dist/{chunk-7VJ6BOA5.js → chunk-SMLXZUBH.js} +9 -1
  63. package/dist/chunk-TOM66P2P.js +38 -0
  64. package/dist/chunk-UA5KS2PL.js +26 -0
  65. package/dist/{chunk-N6N74K6X.js → chunk-UBBKSYBY.js} +1 -1
  66. package/dist/{chunk-353WXS6S.js → chunk-UIRMA5KM.js} +1 -1
  67. package/dist/{chunk-BIK4DFWK.js → chunk-ULCQ73LA.js} +1 -1
  68. package/dist/{chunk-2BWAID3Y.js → chunk-UMWIPLLM.js} +29 -3
  69. package/dist/chunk-UQ3ZFCWD.js +178 -0
  70. package/dist/chunk-UXPGW4TI.js +101 -0
  71. package/dist/chunk-V2MJE6NC.js +133 -0
  72. package/dist/{chunk-D3CLOBE3.js → chunk-V373TRJE.js} +48 -10
  73. package/dist/chunk-VQAXTIBW.js +100 -0
  74. package/dist/chunk-W74BCA7V.js +159 -0
  75. package/dist/{chunk-WP2CX2JO.js → chunk-WELIKLZF.js} +22 -1
  76. package/dist/{chunk-MDEJHMKK.js → chunk-WHVLNFTG.js} +26 -5
  77. package/dist/{chunk-GZ46OVGZ.js → chunk-WSVMLNTO.js} +1 -1
  78. package/dist/{chunk-4LZJXJJS.js → chunk-WXWPK3LI.js} +6 -2
  79. package/dist/chunk-X3D6LXUU.js +185 -0
  80. package/dist/chunk-XJ2F2WO6.js +8 -0
  81. package/dist/{chunk-73HOFQQ5.js → chunk-Y4AGLCY6.js} +1 -1
  82. package/dist/chunk-YBLDE5CG.js +42 -0
  83. package/dist/{chunk-JEYQU3JT.js → chunk-YHYTW5QA.js} +2 -18
  84. package/dist/{chunk-PZOWBI3B.js → chunk-YLL2QXY2.js} +7 -2
  85. package/dist/class/class.codec.js +12 -9
  86. package/dist/class/class.parser.js +11 -8
  87. package/dist/class/class.schema.d.ts +55 -3
  88. package/dist/class/class.schema.js +9 -7
  89. package/dist/class/class.types.d.ts +48 -3
  90. package/dist/condition/condition.codec.d.ts +9 -0
  91. package/dist/condition/condition.entity-type.d.ts +2 -0
  92. package/dist/condition/condition.parser.d.ts +13 -0
  93. package/dist/condition/condition.parser.js +7 -0
  94. package/dist/condition/condition.schema.d.ts +29 -0
  95. package/dist/condition/condition.types.d.ts +15 -0
  96. package/dist/condition/condition.types.js +0 -0
  97. package/dist/dnd/constants.d.ts +22 -0
  98. package/dist/dnd/constants.js +9 -3
  99. package/dist/dnd/formula-tags.js +2 -2
  100. package/dist/dnd/math.d.ts +26 -0
  101. package/dist/dnd/math.js +12 -2
  102. package/dist/dnd/prose-tags.js +1 -1
  103. package/dist/dnd/resource-formula.d.ts +36 -10
  104. package/dist/dnd/resource-formula.js +10 -155
  105. package/dist/dnd/srd-tag-converter.js +3 -3
  106. package/dist/dnd/tag-grammar.js +1 -1
  107. package/dist/dnd/warn-once.d.ts +2 -0
  108. package/dist/dnd/warn-once.js +8 -0
  109. package/dist/entities/base-item-resolver.js +2 -2
  110. package/dist/entities/slug.d.ts +13 -0
  111. package/dist/entities/slug.js +5 -3
  112. package/dist/entities/wikilink-display.d.ts +3 -0
  113. package/dist/entities/wikilink-display.js +10 -0
  114. package/dist/feat/feat.category-codes.d.ts +32 -0
  115. package/dist/feat/feat.category-codes.js +14 -0
  116. package/dist/feat/feat.codec.js +7 -5
  117. package/dist/feat/feat.parser.js +6 -4
  118. package/dist/feat/feat.schema.d.ts +239 -0
  119. package/dist/feat/feat.schema.js +5 -3
  120. package/dist/feat/feat.types.d.ts +37 -1
  121. package/dist/index.js +2033 -6907
  122. package/dist/item/item.codec.js +4 -3
  123. package/dist/item/item.enrichment.js +4 -4
  124. package/dist/item/item.parser.js +3 -2
  125. package/dist/item/item.schema.d.ts +69 -3
  126. package/dist/item/item.schema.js +2 -1
  127. package/dist/item/item.types.d.ts +69 -3
  128. package/dist/monster/monster.codec.d.ts +7 -6
  129. package/dist/monster/monster.enrichment.js +4 -4
  130. package/dist/monster/monster.format.d.ts +135 -0
  131. package/dist/monster/monster.format.js +78 -0
  132. package/dist/monster/monster.parser.d.ts +6 -1
  133. package/dist/monster/monster.parser.js +10 -1
  134. package/dist/monster/monster.schema.d.ts +369 -0
  135. package/dist/monster/monster.schema.js +34 -0
  136. package/dist/monster/monster.types.d.ts +200 -14
  137. package/dist/optional-feature/optional-feature.codec.js +6 -5
  138. package/dist/optional-feature/optional-feature.parser.js +5 -4
  139. package/dist/optional-feature/optional-feature.schema.d.ts +185 -0
  140. package/dist/optional-feature/optional-feature.schema.js +4 -3
  141. package/dist/pack.d.ts +1 -1
  142. package/dist/pc/conditions.constants.d.ts +0 -1
  143. package/dist/pc/conditions.constants.js +1 -3
  144. package/dist/pc/decision-recognizer.js +1 -1
  145. package/dist/pc/pc.additional-spells.d.ts +47 -0
  146. package/dist/pc/pc.additional-spells.js +23 -0
  147. package/dist/pc/pc.asi-flatten.d.ts +18 -0
  148. package/dist/pc/pc.decision-engine.d.ts +105 -17
  149. package/dist/pc/pc.decision-engine.js +28 -12
  150. package/dist/pc/pc.defense-normalize.d.ts +11 -0
  151. package/dist/pc/pc.defense-normalize.js +6 -0
  152. package/dist/pc/pc.equipment.d.ts +31 -2
  153. package/dist/pc/pc.equipment.js +12 -8
  154. package/dist/pc/pc.feature-effects.d.ts +234 -11
  155. package/dist/pc/pc.feature-effects.js +21 -5
  156. package/dist/pc/pc.parser.js +2 -2
  157. package/dist/pc/pc.pools.d.ts +11 -3
  158. package/dist/pc/pc.pools.js +9 -13
  159. package/dist/pc/pc.proficiencies.d.ts +54 -29
  160. package/dist/pc/pc.proficiencies.js +74 -95
  161. package/dist/pc/pc.proficiency-grants.d.ts +58 -0
  162. package/dist/pc/pc.proficiency-normalize.d.ts +24 -0
  163. package/dist/pc/pc.proficiency-normalize.js +12 -0
  164. package/dist/pc/pc.proficiency-query.d.ts +13 -0
  165. package/dist/pc/pc.proficiency-query.js +1 -1
  166. package/dist/pc/pc.recalc.d.ts +69 -14
  167. package/dist/pc/pc.recalc.js +261 -122
  168. package/dist/pc/pc.resolver.d.ts +34 -8
  169. package/dist/pc/pc.resolver.js +27 -12
  170. package/dist/pc/pc.resource-seed.d.ts +3 -2
  171. package/dist/pc/pc.resource-seed.js +19 -17
  172. package/dist/pc/pc.resources.d.ts +87 -0
  173. package/dist/pc/pc.resources.js +21 -0
  174. package/dist/pc/pc.rest.d.ts +10 -1
  175. package/dist/pc/pc.rest.js +66 -12
  176. package/dist/pc/pc.schema.d.ts +139 -3
  177. package/dist/pc/pc.schema.js +4 -2
  178. package/dist/pc/pc.slotting.js +3 -3
  179. package/dist/pc/pc.spellcasting.d.ts +75 -6
  180. package/dist/pc/pc.spellcasting.js +16 -6
  181. package/dist/pc/pc.table-column.d.ts +23 -0
  182. package/dist/pc/pc.table-column.js +13 -3
  183. package/dist/pc/pc.types.d.ts +251 -12
  184. package/dist/pc/pool-layout.d.ts +47 -0
  185. package/dist/pc/pool-layout.js +16 -0
  186. package/dist/pc/roll-scope.d.ts +2 -0
  187. package/dist/pc/roll-scope.js +8 -0
  188. package/dist/pc/roll-tag-labels.d.ts +40 -0
  189. package/dist/pc/roll-tag-labels.js +17 -0
  190. package/dist/pc/spell-source.d.ts +21 -0
  191. package/dist/pc/spell-source.js +13 -0
  192. package/dist/race/race.codec.js +9 -7
  193. package/dist/race/race.parser.js +8 -6
  194. package/dist/race/race.schema.d.ts +51 -1
  195. package/dist/race/race.schema.js +8 -5
  196. package/dist/race/race.structural.d.ts +7 -0
  197. package/dist/race/race.structural.js +6 -0
  198. package/dist/race/race.types.d.ts +20 -0
  199. package/dist/schemas/attack-schema.d.ts +5 -0
  200. package/dist/schemas/caster-type-schema.d.ts +14 -0
  201. package/dist/schemas/caster-type-schema.js +6 -0
  202. package/dist/schemas/choice-schema.js +2 -2
  203. package/dist/schemas/entity-extras-schema.d.ts +53 -0
  204. package/dist/schemas/entity-extras-schema.js +10 -0
  205. package/dist/schemas/equipment-grant-schema.d.ts +2 -0
  206. package/dist/schemas/equipment-grant-schema.js +1 -1
  207. package/dist/schemas/feature-alias.d.ts +34 -0
  208. package/dist/schemas/feature-effect-schema.d.ts +133 -0
  209. package/dist/schemas/feature-effect-schema.js +1 -1
  210. package/dist/schemas/feature-schema.d.ts +8 -0
  211. package/dist/schemas/feature-schema.js +6 -4
  212. package/dist/schemas/resource-schema.d.ts +43 -0
  213. package/dist/schemas/resource-schema.js +1 -1
  214. package/dist/schemas/selection-pool-schema.d.ts +2 -0
  215. package/dist/schemas/selection-pool-schema.js +1 -1
  216. package/dist/spell/spell.access.js +23 -3
  217. package/dist/spell/spell.codec.js +4 -3
  218. package/dist/spell/spell.enrichment.js +4 -4
  219. package/dist/spell/spell.parser.d.ts +30 -0
  220. package/dist/spell/spell.parser.js +9 -2
  221. package/dist/spell/spell.scaling.d.ts +27 -6
  222. package/dist/spell/spell.scaling.js +25 -6
  223. package/dist/spell/spell.schema.d.ts +44 -2
  224. package/dist/spell/spell.schema.js +2 -1
  225. package/dist/spell/spell.types.d.ts +14 -0
  226. package/dist/subclass/subclass.codec.d.ts +1 -1
  227. package/dist/subclass/subclass.codec.js +11 -8
  228. package/dist/subclass/subclass.parser.js +10 -7
  229. package/dist/subclass/subclass.schema.d.ts +54 -7
  230. package/dist/subclass/subclass.schema.js +8 -6
  231. package/dist/subclass/subclass.types.d.ts +20 -2
  232. package/dist/types/choice.d.ts +53 -2
  233. package/dist/types/choice.js +13 -1
  234. package/dist/types/equipment-grant.d.ts +8 -1
  235. package/dist/types/feature-effect.d.ts +85 -23
  236. package/dist/types/feature.d.ts +70 -1
  237. package/dist/types/optional-feature.types.d.ts +28 -0
  238. package/dist/types/resource.d.ts +21 -1
  239. package/dist/types/selection-pool.d.ts +17 -2
  240. package/dist/weapon/weapon.classify.js +2 -2
  241. package/dist/weapon/weapon.codec.js +4 -3
  242. package/dist/weapon/weapon.parser.js +3 -2
  243. package/dist/weapon/weapon.schema.d.ts +4 -0
  244. package/dist/weapon/weapon.schema.js +2 -1
  245. package/dist/weapon/weapon.types.d.ts +8 -0
  246. package/package.json +2 -2
  247. package/dist/chunk-5XUXXAQJ.js +0 -30
  248. package/dist/chunk-7P65Q426.js +0 -158
  249. package/dist/chunk-7TEK5KK7.js +0 -49
  250. package/dist/chunk-AIRFC5NQ.js +0 -143
  251. package/dist/chunk-CZPMTQOY.js +0 -68
  252. package/dist/chunk-N2JE7BWL.js +0 -81
  253. package/dist/chunk-NXR3BD2V.js +0 -90
  254. package/dist/chunk-O5EYMKFH.js +0 -6
  255. package/dist/chunk-Q5K6LWBZ.js +0 -45
  256. package/dist/chunk-TNUFPIXI.js +0 -1110
  257. package/dist/chunk-TZK36BU7.js +0 -38
  258. package/dist/chunk-W7HWMMBF.js +0 -46
  259. package/dist/chunk-Y4I74YEG.js +0 -33
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseRace
3
- } from "./chunk-PHQRGDRQ.js";
3
+ } from "./chunk-N3A5ICBO.js";
4
4
 
5
5
  // src/race/race.codec.ts
6
6
  import yaml from "js-yaml";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  backgroundEntitySchema
3
- } from "./chunk-SE7AZDR3.js";
3
+ } from "./chunk-63XQXPZL.js";
4
4
 
5
5
  // src/background/background.parser.ts
6
6
  import { parseYaml } from "@archivist-gg/core";
@@ -0,0 +1,22 @@
1
+ // src/schemas/feature-alias.ts
2
+ function aliasFeatureActionCost(f) {
3
+ if (f.action === void 0 && typeof f.action_cost === "string") f.action = f.action_cost;
4
+ }
5
+ function aliasFeatureListActionCost(list) {
6
+ if (Array.isArray(list)) {
7
+ for (const f of list) if (f && typeof f === "object") aliasFeatureActionCost(f);
8
+ }
9
+ }
10
+ function aliasFeaturesByLevelActionCost(byLevel) {
11
+ if (byLevel && typeof byLevel === "object")
12
+ for (const list of Object.values(byLevel)) aliasFeatureListActionCost(list);
13
+ }
14
+ function withResolvedActionCost(f) {
15
+ return f.action === void 0 && typeof f.action_cost === "string" ? { ...f, action: f.action_cost } : f;
16
+ }
17
+
18
+ export {
19
+ aliasFeatureListActionCost,
20
+ aliasFeaturesByLevelActionCost,
21
+ withResolvedActionCost
22
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseItem
3
- } from "./chunk-7VJ6BOA5.js";
3
+ } from "./chunk-SMLXZUBH.js";
4
4
 
5
5
  // src/item/item.codec.ts
6
6
  import yaml from "js-yaml";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  armorEntitySchema
3
- } from "./chunk-XJNECUPT.js";
3
+ } from "./chunk-JC5UNIVM.js";
4
4
 
5
5
  // src/armor/armor.parser.ts
6
6
  import { parseYaml } from "@archivist-gg/core";
@@ -18,12 +18,25 @@ var KNOWN_KEYS = /* @__PURE__ */ new Set([
18
18
  "page",
19
19
  "edition",
20
20
  "entries",
21
- "raw"
21
+ "raw",
22
+ // Root extras declared on armorEntitySchema (spec §5). The schema declaring them is NOT
23
+ // enough: this set is the second, independent gate — a key missing here is copied into
24
+ // `raw` as well, so the two lists must move together.
25
+ "rendering_hint",
26
+ "has_fluff",
27
+ "has_fluff_images",
28
+ "image",
29
+ // The alias is a KNOWN key so it is never copied into `raw` alongside the mapped
30
+ // `strength_requirement` — that duplicate is the census row this fix empties.
31
+ "strength_required"
22
32
  ]);
23
33
  function parseArmor(source) {
24
34
  var _a;
25
35
  const raw = parseYaml(source, ["name", "slug", "category", "ac"]);
26
36
  if (!raw.success) return raw;
37
+ if (raw.data.strength_requirement === void 0 && typeof raw.data.strength_required === "number") {
38
+ raw.data.strength_requirement = raw.data.strength_required;
39
+ }
27
40
  const result = armorEntitySchema.safeParse(raw.data);
28
41
  if (!result.success) {
29
42
  return { success: false, error: `armor schema validation failed: ${result.error.message}` };
@@ -1,12 +1,16 @@
1
+ import {
2
+ aliasFeaturesByLevelActionCost
3
+ } from "./chunk-4U55VNC7.js";
1
4
  import {
2
5
  classEntitySchema
3
- } from "./chunk-TLYDBT5F.js";
6
+ } from "./chunk-CGRLQ34U.js";
4
7
 
5
8
  // src/class/class.parser.ts
6
9
  import { parseYaml } from "@archivist-gg/core";
7
10
  function parseClass(source) {
8
11
  const raw = parseYaml(source, ["name", "slug"]);
9
12
  if (!raw.success) return raw;
13
+ aliasFeaturesByLevelActionCost(raw.data.features_by_level);
10
14
  const result = classEntitySchema.safeParse({ edition: "2014", ...raw.data });
11
15
  if (!result.success) {
12
16
  return { success: false, error: `class schema validation failed: ${result.error.message}` };
@@ -1,9 +1,13 @@
1
1
  import {
2
2
  startingEquipmentEntrySchema
3
- } from "./chunk-3DZ74AKK.js";
3
+ } from "./chunk-IN4M4X7P.js";
4
4
  import {
5
5
  choiceSchema
6
- } from "./chunk-NXSWH3AE.js";
6
+ } from "./chunk-IWRVOCT5.js";
7
+ import {
8
+ additionalSpellsEntrySchema,
9
+ imageField
10
+ } from "./chunk-UA5KS2PL.js";
7
11
 
8
12
  // src/background/background.schema.ts
9
13
  import { z } from "zod";
@@ -75,7 +79,29 @@ var backgroundEntitySchema = z.object({
75
79
  }).nullable(),
76
80
  origin_feat: z.string().regex(wikilinkRegex).nullable(),
77
81
  suggested_characteristics: suggestedCharSchema.nullable(),
78
- choices: z.array(choiceSchema).optional()
82
+ choices: z.array(choiceSchema).optional(),
83
+ rendering_hint: z.string().optional(),
84
+ // 175
85
+ has_fluff_images: z.boolean().optional(),
86
+ // 87
87
+ tables: z.array(z.object({
88
+ // 88 tables / 67 docs; key-sets EXACT (finding 6)
89
+ name: z.string().min(1),
90
+ dice: z.string().min(1),
91
+ rows: z.array(z.object({ roll: z.string(), text: z.string() }))
92
+ })).optional(),
93
+ additional_spells: z.array(additionalSpellsEntrySchema).optional(),
94
+ // 15
95
+ prerequisites: z.array(z.object({
96
+ // 4 docs; kind CLOSED AT THE EMITTER
97
+ kind: z.literal("campaign"),
98
+ slug: z.string().min(1)
99
+ // (background-mapper.ts pushes
100
+ })).optional(),
101
+ // {kind:"campaign", slug} literally — finding 24)
102
+ // The one-arm union STAYS (§2.6 adjudication): it is closed by CONSTRUCTION at the converter's
103
+ // only push site, and a future kind turns into a visible census REFUSAL — the correct loud failure.
104
+ image: imageField
79
105
  });
80
106
 
81
107
  export {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  optionalFeatureEntitySchema
3
- } from "./chunk-MDEJHMKK.js";
3
+ } from "./chunk-WHVLNFTG.js";
4
4
 
5
5
  // src/optional-feature/optional-feature.parser.ts
6
6
  import { parseYaml } from "@archivist-gg/core";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  STATIC_FALLBACK_CONTEXT,
3
3
  convertDescToTags
4
- } from "./chunk-RAWJTA45.js";
4
+ } from "./chunk-DEEHHLAP.js";
5
5
 
6
6
  // src/item/item.enrichment.ts
7
7
  function enrichItem(raw) {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  convertDescToTags,
3
3
  detectSpellcastingAbility
4
- } from "./chunk-RAWJTA45.js";
4
+ } from "./chunk-DEEHHLAP.js";
5
5
  import {
6
6
  abilityModifier
7
- } from "./chunk-NAEPSZAM.js";
7
+ } from "./chunk-PDJSUH24.js";
8
8
 
9
9
  // src/monster/monster.enrichment.ts
10
10
  import { toStringSafe } from "@archivist-gg/core";
@@ -0,0 +1,33 @@
1
+ import {
2
+ imageField
3
+ } from "./chunk-UA5KS2PL.js";
4
+
5
+ // src/condition/condition.parser.ts
6
+ import { parseYaml } from "@archivist-gg/core";
7
+
8
+ // src/condition/condition.schema.ts
9
+ import { z } from "zod";
10
+ var conditionEntitySchema = z.object({
11
+ slug: z.string().min(1),
12
+ name: z.string().min(1),
13
+ edition: z.enum(["2014", "2024"]),
14
+ source: z.string().min(1),
15
+ description: z.string(),
16
+ has_fluff_images: z.boolean().optional(),
17
+ image: imageField
18
+ });
19
+
20
+ // src/condition/condition.parser.ts
21
+ function parseCondition(source) {
22
+ const raw = parseYaml(source, ["name", "slug"]);
23
+ if (!raw.success) return raw;
24
+ const result = conditionEntitySchema.safeParse({ edition: "2014", ...raw.data });
25
+ if (!result.success) {
26
+ return { success: false, error: `condition schema validation failed: ${result.error.message}` };
27
+ }
28
+ return { success: true, data: result.data };
29
+ }
30
+
31
+ export {
32
+ parseCondition
33
+ };
@@ -7,8 +7,15 @@ function bareEntitySlug(slug) {
7
7
  const p = slug.split("_");
8
8
  return p.length >= 3 ? p.slice(2).join("_") : p[p.length - 1];
9
9
  }
10
+ function wikilinkTailSlug(link) {
11
+ var _a;
12
+ const inner = link.replace(/^\[\[/, "").replace(/\]\]$/, "");
13
+ const tail = (_a = inner.split("/").pop()) != null ? _a : inner;
14
+ return slugify(tail);
15
+ }
10
16
 
11
17
  export {
12
18
  slugify,
13
- bareEntitySlug
19
+ bareEntitySlug,
20
+ wikilinkTailSlug
14
21
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseArmor
3
- } from "./chunk-HCP3GMHS.js";
3
+ } from "./chunk-5N2GW72F.js";
4
4
 
5
5
  // src/armor/armor.codec.ts
6
6
  import yaml from "js-yaml";
@@ -2,17 +2,28 @@ import {
2
2
  poolGrantSchema,
3
3
  selectionPoolSchema,
4
4
  tabDeclSchema
5
- } from "./chunk-4TIJKN6O.js";
5
+ } from "./chunk-23LZLBJK.js";
6
+ import {
7
+ casterTypeEnum
8
+ } from "./chunk-CJYCVNW2.js";
6
9
  import {
7
10
  featureSchema
8
- } from "./chunk-CZPMTQOY.js";
11
+ } from "./chunk-W74BCA7V.js";
9
12
  import {
10
13
  resourceSchema
11
- } from "./chunk-PZOWBI3B.js";
14
+ } from "./chunk-YLL2QXY2.js";
12
15
  import {
13
16
  startingEquipmentEntrySchema,
14
17
  startingGoldSchema
15
- } from "./chunk-3DZ74AKK.js";
18
+ } from "./chunk-IN4M4X7P.js";
19
+ import {
20
+ choiceSchema
21
+ } from "./chunk-IWRVOCT5.js";
22
+ import {
23
+ additionalSpellsEntrySchema,
24
+ imageField,
25
+ progressionSchema
26
+ } from "./chunk-UA5KS2PL.js";
16
27
 
17
28
  // src/class/class.schema.ts
18
29
  import { z } from "zod";
@@ -67,7 +78,6 @@ var toolProficiencySchema = z.object({
67
78
  }, {
68
79
  message: "tool proficiency must declare fixed or choice"
69
80
  });
70
- var casterTypeEnum = z.enum(["full", "half", "third", "pact"]);
71
81
  var spellcastingSchema = z.object({
72
82
  caster_type: casterTypeEnum,
73
83
  ability: abilityEnum,
@@ -75,7 +85,16 @@ var spellcastingSchema = z.object({
75
85
  spell_list: z.string().min(1)
76
86
  });
77
87
  var weaponMasterySchema = z.object({
78
- starting_count: z.number().int().nonnegative(),
88
+ // §2.7's ONE deliberate relaxation, and the phase's only non-additive edit. Measured: `starting_count`
89
+ // has ZERO read sites in either repo, all 24 SRD class records are `weapon_mastery: null`, and the
90
+ // converter population is zero too (26 of 28 class docs null; both object carriers DO carry the count).
91
+ // It exists so the converter can re-emit a countless mastery object later. R4-G5 did NOT make it read: §6 takes
92
+ // the count from the class TABLE COLUMN instead (`COUNT_COLUMNS` in `pc.table-column.ts`), because the column
93
+ // is the truth on BOTH corpora, and `count.column` on the choice itself is booked to the G7 converter handoff.
94
+ // `starting_count` therefore still has ZERO read sites.
95
+ // A THREE-declaration edit (finding 11): here, `class.types.ts`, and the generator's COPIED
96
+ // `interface WeaponMasteryConfig` in tools/srd-canonical/merger-rules/class-merge.ts.
97
+ starting_count: z.number().int().nonnegative().optional(),
79
98
  scaling: z.record(z.string(), z.number().int().nonnegative()).optional()
80
99
  });
81
100
  var classTableRowSchema = z.object({
@@ -101,6 +120,10 @@ var classEntitySchema = z.object({
101
120
  count: z.number().int().positive(),
102
121
  from: z.array(skillEnum).nonempty()
103
122
  }),
123
+ // Zod strips unknown keys by default, so without this declaration an authored
124
+ // `choices:` block is silently deleted by `parseClass`. Same spelling as
125
+ // `raceEntitySchema` / `backgroundEntitySchema`.
126
+ choices: z.array(choiceSchema).optional(),
104
127
  starting_equipment: z.array(startingEquipmentEntrySchema),
105
128
  starting_gold: startingGoldSchema.optional(),
106
129
  spellcasting: spellcastingSchema.nullable(),
@@ -113,7 +136,41 @@ var classEntitySchema = z.object({
113
136
  resources: z.array(resourceSchema),
114
137
  selection_pools: z.array(selectionPoolSchema).optional(),
115
138
  pool_grants: z.array(poolGrantSchema).optional(),
116
- tabs: z.array(tabDeclSchema).optional()
139
+ tabs: z.array(tabDeclSchema).optional(),
140
+ rendering_hint: z.string().optional(),
141
+ // 28
142
+ has_fluff: z.boolean().optional(),
143
+ // 28
144
+ has_fluff_images: z.boolean().optional(),
145
+ // 27
146
+ table_col_labels: z.array(z.string().min(1)).optional(),
147
+ // 28
148
+ starting_equipment_additional_from_background: z.boolean().optional(),
149
+ // 28
150
+ multiclassing: z.unknown().optional(),
151
+ // FOUR arities measured incl. {} ×3; free-form 5etools keys
152
+ // ("thieves' tools", requirements.or[].{dex,str}) — Q1 ruling
153
+ cantrip_progression: z.array(z.number()).optional(),
154
+ // 15
155
+ prepared_spells: z.string().min(1).optional(),
156
+ // formula string "<$level$> / 2 + <$int_mod$>"
157
+ prepared_spells_change: z.string().min(1).optional(),
158
+ // "restLong"
159
+ prepared_spells_progression: z.array(z.number()).optional(),
160
+ spells_known_progression: z.array(z.number()).optional(),
161
+ spells_known_progression_fixed: z.array(z.number()).optional(),
162
+ spells_known_progression_fixed_allow_lower_level: z.boolean().optional(),
163
+ // ⚠️ BOOLEAN (finding 1)
164
+ spells_known_progression_fixed_by_level: z.record(z.string(), z.record(z.string(), z.number())).optional(),
165
+ // ⚠️ two-deep record (finding 1)
166
+ feat_progression: z.array(progressionSchema).optional(),
167
+ // 13
168
+ optionalfeature_progression: z.array(progressionSchema).optional(),
169
+ // 9 carriers; the ARRAY
170
+ // progression arm rides 4 of them
171
+ additional_spells: z.array(additionalSpellsEntrySchema).optional(),
172
+ // 7
173
+ image: imageField
117
174
  });
118
175
 
119
176
  export {
@@ -0,0 +1,7 @@
1
+ // src/schemas/caster-type-schema.ts
2
+ import { z } from "zod";
3
+ var casterTypeEnum = z.enum(["full", "half", "third", "pact", "artificer"]);
4
+
5
+ export {
6
+ casterTypeEnum
7
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseSubclass
3
- } from "./chunk-L7E2UT5A.js";
3
+ } from "./chunk-KK33PIDN.js";
4
4
 
5
5
  // src/subclass/subclass.codec.ts
6
6
  import yaml from "js-yaml";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  abilityModifier
3
- } from "./chunk-NAEPSZAM.js";
3
+ } from "./chunk-PDJSUH24.js";
4
4
 
5
5
  // src/dnd/srd-tag-converter.ts
6
6
  var ABILITY_KEYS = ["str", "dex", "con", "int", "wis", "cha"];
@@ -1,28 +1,32 @@
1
1
  import {
2
2
  readTableColumn
3
- } from "./chunk-5XUXXAQJ.js";
3
+ } from "./chunk-IUAAXXNO.js";
4
4
  import {
5
- bareSlug
5
+ bareSlug,
6
+ baseClassName
6
7
  } from "./chunk-VTTA2ALZ.js";
7
8
  import {
8
9
  abilityModifier
9
- } from "./chunk-NAEPSZAM.js";
10
+ } from "./chunk-PDJSUH24.js";
10
11
 
11
12
  // src/pc/pc.spellcasting.ts
13
+ function hasPreparedColumn(table) {
14
+ return Object.values(table).some((row) => PREPARED_COLUMNS.some((k) => {
15
+ var _a;
16
+ return ((_a = row == null ? void 0 : row.columns) == null ? void 0 : _a[k]) !== void 0;
17
+ }));
18
+ }
12
19
  function resolveSpellcasting(rc) {
13
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
20
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
14
21
  const sub = (_b = (_a = rc.subclass) == null ? void 0 : _a.spellcasting) != null ? _b : null;
15
22
  const cls = (_d = (_c = rc.entity) == null ? void 0 : _c.spellcasting) != null ? _d : null;
16
- const sc = sub != null ? sub : cls;
17
- if (!sc) return null;
18
- const table = (_i = (_h = sub ? (_e = rc.subclass) == null ? void 0 : _e.table : (_f = rc.entity) == null ? void 0 : _f.table) != null ? _h : (_g = rc.entity) == null ? void 0 : _g.table) != null ? _i : {};
19
- return {
20
- ability: sc.ability,
21
- casterType: sc.caster_type,
22
- preparation: sc.preparation,
23
- spellList: sc.spell_list,
24
- table
25
- };
23
+ const casterType = (_f = (_e = sub == null ? void 0 : sub.caster_type) != null ? _e : cls == null ? void 0 : cls.caster_type) != null ? _f : null;
24
+ const ability = (_h = (_g = sub == null ? void 0 : sub.ability) != null ? _g : cls == null ? void 0 : cls.ability) != null ? _h : null;
25
+ if (!casterType || !ability) return null;
26
+ const table = (_l = (_k = (sub == null ? void 0 : sub.caster_type) ? (_i = rc.subclass) == null ? void 0 : _i.table : void 0) != null ? _k : (_j = rc.entity) == null ? void 0 : _j.table) != null ? _l : {};
27
+ const preparation = (_n = (_m = sub == null ? void 0 : sub.preparation) != null ? _m : cls == null ? void 0 : cls.preparation) != null ? _n : hasPreparedColumn(table) ? "prepared" : "known";
28
+ const spellList = (_p = (_o = sub == null ? void 0 : sub.spell_list) != null ? _o : cls == null ? void 0 : cls.spell_list) != null ? _p : null;
29
+ return { ability, casterType, preparation, spellList, table };
26
30
  }
27
31
  function effectiveSpellcastingAbility(classSlug, dataAbility, overrides) {
28
32
  var _a, _b;
@@ -41,6 +45,43 @@ function normalizeKnownSpell(entry) {
41
45
  alwaysPrepared: (_b = entry.always_prepared) != null ? _b : false
42
46
  };
43
47
  }
48
+ function firstListedCasterClass(spellClasses, casterClassSlugs) {
49
+ var _a;
50
+ if (!Array.isArray(spellClasses) || spellClasses.length === 0) return null;
51
+ const listed = new Set(spellClasses.map((c) => baseClassName(String(c))));
52
+ return (_a = casterClassSlugs.find((slug) => listed.has(baseClassName(slug)))) != null ? _a : null;
53
+ }
54
+ var LISTED_CLASS_NAMES = /* @__PURE__ */ new WeakMap();
55
+ var NO_NAMES = /* @__PURE__ */ new Set();
56
+ function listedSpellClassNames(registry, compendium) {
57
+ var _a;
58
+ const count = registry.count();
59
+ let cached = LISTED_CLASS_NAMES.get(registry);
60
+ if (!cached || cached.count !== count) {
61
+ const byCompendium = /* @__PURE__ */ new Map();
62
+ for (const e of registry.search("", "spell", Number.POSITIVE_INFINITY)) {
63
+ const classes = e.data.classes;
64
+ if (!Array.isArray(classes)) continue;
65
+ let names = byCompendium.get(e.compendium);
66
+ if (!names) byCompendium.set(e.compendium, names = /* @__PURE__ */ new Set());
67
+ for (const c of classes) names.add(baseClassName(String(c)));
68
+ }
69
+ cached = { count, byCompendium };
70
+ LISTED_CLASS_NAMES.set(registry, cached);
71
+ }
72
+ return (_a = cached.byCompendium.get(compendium)) != null ? _a : NO_NAMES;
73
+ }
74
+ function attributeUnclassedSpell(spellClasses, casters, registry) {
75
+ var _a;
76
+ const first = casters[0];
77
+ if (!first) return null;
78
+ const listed = firstListedCasterClass(spellClasses, casters.map((c) => c.classSlug));
79
+ if (listed == null || listed === first.classSlug) return first.classSlug;
80
+ if (first.spellList == null) return first.classSlug;
81
+ const compendium = (_a = registry.getByTypeAndSlug("class", first.classSlug)) == null ? void 0 : _a.compendium;
82
+ if (compendium == null || !listedSpellClassNames(registry, compendium).has(baseClassName(first.classSlug))) return first.classSlug;
83
+ return listed;
84
+ }
44
85
  var FULL_CASTER_SLOTS = [
45
86
  /* 1 */
46
87
  [2, 0, 0, 0, 0, 0, 0, 0, 0],
@@ -209,6 +250,24 @@ var PACT_MAGIC = [
209
250
  /* 20 */
210
251
  { level: 5, total: 4 }
211
252
  ];
253
+ var ARTIFICER_CASTER_SLOTS = HALF_CASTER_SLOTS.map((row) => [...row]);
254
+ ARTIFICER_CASTER_SLOTS[0] = [2, 0, 0, 0, 0];
255
+ function slotTableFor(caster) {
256
+ switch (caster) {
257
+ case "full":
258
+ return FULL_CASTER_SLOTS;
259
+ case "half":
260
+ return HALF_CASTER_SLOTS;
261
+ case "third":
262
+ return THIRD_CASTER_SLOTS;
263
+ case "artificer":
264
+ return ARTIFICER_CASTER_SLOTS;
265
+ default: {
266
+ const _n = caster;
267
+ throw new Error(`unknown caster type ${String(_n)}`);
268
+ }
269
+ }
270
+ }
212
271
  function rowToRecord(row) {
213
272
  const out = {};
214
273
  row.forEach((n, i) => {
@@ -217,7 +276,7 @@ function rowToRecord(row) {
217
276
  return out;
218
277
  }
219
278
  function deriveSpellSlots(classes) {
220
- let fullLevels = 0, halfLevels = 0, thirdLevels = 0, warlockLevel = 0;
279
+ let fullLevels = 0, halfLevels = 0, thirdLevels = 0, artificerLevels = 0, warlockLevel = 0;
221
280
  const regular = [];
222
281
  for (const c of classes) {
223
282
  if (c.casterType === "pact") {
@@ -225,28 +284,55 @@ function deriveSpellSlots(classes) {
225
284
  continue;
226
285
  }
227
286
  regular.push({ caster: c.casterType, level: c.level });
228
- if (c.casterType === "full") fullLevels += c.level;
229
- else if (c.casterType === "half") halfLevels += c.level;
230
- else if (c.casterType === "third") thirdLevels += c.level;
287
+ switch (c.casterType) {
288
+ case "full":
289
+ fullLevels += c.level;
290
+ break;
291
+ case "half":
292
+ halfLevels += c.level;
293
+ break;
294
+ case "third":
295
+ thirdLevels += c.level;
296
+ break;
297
+ case "artificer":
298
+ artificerLevels += c.level;
299
+ break;
300
+ default: {
301
+ const _n = c.casterType;
302
+ throw new Error(`unknown caster type ${String(_n)}`);
303
+ }
304
+ }
231
305
  }
232
306
  let standard = {};
233
307
  if (regular.length === 1) {
234
308
  const only = regular[0];
309
+ const table = slotTableFor(only.caster);
235
310
  const idx = only.level - 1;
236
- if (only.caster === "half") {
237
- if (idx >= 0 && idx < HALF_CASTER_SLOTS.length) standard = rowToRecord(HALF_CASTER_SLOTS[idx]);
238
- } else if (only.caster === "third") {
239
- if (idx >= 0 && idx < THIRD_CASTER_SLOTS.length) standard = rowToRecord(THIRD_CASTER_SLOTS[idx]);
240
- } else {
241
- if (only.level >= 1 && only.level <= FULL_CASTER_SLOTS.length) standard = rowToRecord(FULL_CASTER_SLOTS[only.level - 1]);
242
- }
311
+ if (idx >= 0 && idx < table.length) standard = rowToRecord(table[idx]);
243
312
  } else if (regular.length >= 2) {
244
- const cl = fullLevels + Math.floor(halfLevels / 2) + Math.floor(thirdLevels / 3);
313
+ const cl = fullLevels + Math.floor(halfLevels / 2) + Math.floor(thirdLevels / 3) + Math.ceil(artificerLevels / 2);
245
314
  if (cl >= 1 && cl <= FULL_CASTER_SLOTS.length) standard = rowToRecord(FULL_CASTER_SLOTS[cl - 1]);
246
315
  }
247
316
  const pact = warlockLevel >= 1 && warlockLevel <= PACT_MAGIC.length ? PACT_MAGIC[warlockLevel - 1] : null;
248
317
  return { standard, pact };
249
318
  }
319
+ var PREPARED_COLUMNS = ["Prepared Spells", "Spells Prepared"];
320
+ function preparedLevelTerm(caster, level) {
321
+ switch (caster) {
322
+ case "full":
323
+ case "pact":
324
+ return level;
325
+ case "half":
326
+ case "artificer":
327
+ return Math.floor(level / 2);
328
+ case "third":
329
+ return Math.floor(level / 3);
330
+ default: {
331
+ const _n = caster;
332
+ throw new Error(`unknown caster type ${String(_n)}`);
333
+ }
334
+ }
335
+ }
250
336
  function computeSpellLimits(inputs) {
251
337
  const out = [];
252
338
  for (const i of inputs) {
@@ -255,8 +341,8 @@ function computeSpellLimits(inputs) {
255
341
  const mod = abilityModifier(i.abilityScore);
256
342
  let preparedOrKnown;
257
343
  if (p.preparation === "prepared") {
258
- const levelTerm = p.casterType === "half" ? Math.floor(i.level / 2) : i.level;
259
- preparedOrKnown = Math.max(1, mod + levelTerm);
344
+ const fromTable = readTableColumn(p.table, i.level, PREPARED_COLUMNS);
345
+ preparedOrKnown = fromTable !== null ? fromTable : Math.max(1, mod + preparedLevelTerm(p.casterType, i.level));
260
346
  } else {
261
347
  preparedOrKnown = readTableColumn(p.table, i.level, ["Spells Known", "Prepared Spells"]);
262
348
  }
@@ -269,6 +355,11 @@ export {
269
355
  resolveSpellcasting,
270
356
  effectiveSpellcastingAbility,
271
357
  normalizeKnownSpell,
358
+ listedSpellClassNames,
359
+ attributeUnclassedSpell,
360
+ slotTableFor,
272
361
  deriveSpellSlots,
362
+ PREPARED_COLUMNS,
363
+ preparedLevelTerm,
273
364
  computeSpellLimits
274
365
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseClass
3
- } from "./chunk-42Y5IJKT.js";
3
+ } from "./chunk-5RKLL2AD.js";
4
4
 
5
5
  // src/class/class.codec.ts
6
6
  import yaml from "js-yaml";