jaml-ui 0.24.19 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/DESIGN.md +2 -2
  2. package/README.md +0 -13
  3. package/assets/WeeJokerExampleDAilyGame.png +0 -0
  4. package/assets/balatro-stake-chips.png +0 -0
  5. package/dist/assets.d.ts +1 -2
  6. package/dist/chunks/Layer-BBPJFHfs.js +17 -0
  7. package/dist/chunks/Layer-BBPJFHfs.js.map +1 -0
  8. package/dist/chunks/assets-RWUiFSTc.js +37 -0
  9. package/dist/chunks/assets-RWUiFSTc.js.map +1 -0
  10. package/dist/chunks/motelyItemDecoder-CueyZ0XD.js +6039 -0
  11. package/dist/chunks/motelyItemDecoder-CueyZ0XD.js.map +1 -0
  12. package/dist/chunks/spriteMapper-CFjN0_TV.js +2415 -0
  13. package/dist/chunks/spriteMapper-CFjN0_TV.js.map +1 -0
  14. package/dist/chunks/tokens-B65Fzble.js +57 -0
  15. package/dist/chunks/tokens-B65Fzble.js.map +1 -0
  16. package/dist/chunks/ui-5cBy3zAm.js +1387 -0
  17. package/dist/chunks/ui-5cBy3zAm.js.map +1 -0
  18. package/dist/components/AnalyzerExplorer.d.ts +1 -1
  19. package/dist/components/CardFan.d.ts +1 -1
  20. package/dist/components/CardList.d.ts +1 -1
  21. package/dist/components/DeckSprite.d.ts +1 -1
  22. package/dist/components/JamlAestheticSelector.d.ts +1 -1
  23. package/dist/components/JamlAnalyzerFullscreen.d.ts +5 -5
  24. package/dist/components/JamlCurator.d.ts +1 -1
  25. package/dist/components/JamlIde.d.ts +5 -5
  26. package/dist/components/JamlSeedInput.d.ts +1 -1
  27. package/dist/components/JamlSpeedometer.d.ts +1 -1
  28. package/dist/components/MotelyVersionBadge.d.ts +1 -1
  29. package/dist/components/Standardcard.d.ts +1 -1
  30. package/dist/components/jamlMap/CategoryPicker.d.ts +3 -3
  31. package/dist/components/jamlMap/JamlMapEditor.d.ts +1 -1
  32. package/dist/components/jamlMap/JokerPicker.d.ts +1 -1
  33. package/dist/components/jamlMap/MysterySlot.d.ts +2 -2
  34. package/dist/components/jamlMap/index.d.ts +4 -4
  35. package/dist/core.d.ts +5 -5
  36. package/dist/core.js +27 -5
  37. package/dist/core.js.map +1 -0
  38. package/dist/decode/motelyItemDecoder.d.ts +0 -10
  39. package/dist/decode/motelySprite.d.ts +1 -1
  40. package/dist/fonts/m6x11plus.otf +0 -0
  41. package/dist/hooks/analyzerStreamRegistry.d.ts +2 -2
  42. package/dist/hooks/useAnalyzer.d.ts +2 -2
  43. package/dist/hooks/useSearch.d.ts +2 -2
  44. package/dist/index.d.ts +29 -31
  45. package/dist/index.js +16725 -34
  46. package/dist/index.js.map +1 -0
  47. package/dist/lib/const.d.ts +2 -2
  48. package/dist/lib/hooks/useDragScroll.d.ts +1 -1
  49. package/dist/lib/hooks/useJamlFilter.d.ts +2 -2
  50. package/dist/lib/hooks/useSeedAnalyzer.d.ts +2 -2
  51. package/dist/lib/utils.d.ts +1 -1
  52. package/dist/motely.d.ts +4 -3
  53. package/dist/motely.js +65 -3
  54. package/dist/motely.js.map +1 -0
  55. package/dist/motelyBoot.d.ts +2 -0
  56. package/dist/motelyDisplay.d.ts +0 -2
  57. package/dist/r3f/Card3D.d.ts +2 -2
  58. package/dist/r3f/JimboBillboard.d.ts +1 -1
  59. package/dist/r3f.js +235 -3
  60. package/dist/r3f.js.map +1 -0
  61. package/dist/render/CanvasRenderer.d.ts +1 -1
  62. package/dist/sprites/spriteData.d.ts +1 -6
  63. package/dist/sprites/spriteMapper.d.ts +1 -1
  64. package/dist/ui/JimboBadge.d.ts +1 -1
  65. package/dist/ui/JimboFloating.d.ts +1 -1
  66. package/dist/ui/JimboIconButton.d.ts +1 -1
  67. package/dist/ui/JimboSelect.d.ts +1 -1
  68. package/dist/ui/footer.d.ts +2 -3
  69. package/dist/ui/hooks.d.ts +1 -1
  70. package/dist/ui/ide/DeckSprite.d.ts +1 -1
  71. package/dist/ui/jimbo.css +2 -1837
  72. package/dist/ui/jimboApp.d.ts +1 -1
  73. package/dist/ui/jimboBackground.d.ts +4 -4
  74. package/dist/ui/jimboFilterBar.d.ts +1 -1
  75. package/dist/ui/jimboFlankNav.d.ts +1 -1
  76. package/dist/ui/jimboInfoCard.d.ts +1 -1
  77. package/dist/ui/jimboInset.d.ts +1 -1
  78. package/dist/ui/jimboStatGrid.d.ts +1 -1
  79. package/dist/ui/jimboText.d.ts +1 -1
  80. package/dist/ui/jimboTooltip.d.ts +2 -2
  81. package/dist/ui/mascot/SeedMascot.d.ts +2 -2
  82. package/dist/ui/panel.d.ts +1 -1
  83. package/dist/ui/radial/RadialBadge.d.ts +1 -2
  84. package/dist/ui/radial/RadialButton.d.ts +1 -2
  85. package/dist/ui/radial/RadialMenu.d.ts +2 -2
  86. package/dist/ui/radial/RadialPill.d.ts +1 -2
  87. package/dist/ui/radial/index.d.ts +16 -16
  88. package/dist/ui/radial/radialMenuStore.d.ts +1 -1
  89. package/dist/ui/showcase.d.ts +1 -1
  90. package/dist/ui/sprites.d.ts +2 -2
  91. package/dist/ui.d.ts +0 -1
  92. package/dist/ui.js +3 -36
  93. package/dist/utils/gameCardUtils.d.ts +1 -1
  94. package/dist/utils/jamlVisualFilter.d.ts +1 -7
  95. package/package.json +18 -30
  96. package/dist/assets.js +0 -48
  97. package/dist/components/AnalyzerExplorer.js +0 -391
  98. package/dist/components/CardFan.js +0 -80
  99. package/dist/components/CardList.js +0 -5
  100. package/dist/components/DeckSprite.js +0 -75
  101. package/dist/components/GameCard.js +0 -355
  102. package/dist/components/JamlAestheticSelector.js +0 -22
  103. package/dist/components/JamlAnalyzerFullscreen.js +0 -263
  104. package/dist/components/JamlCodeEditor.js +0 -137
  105. package/dist/components/JamlCurator.js +0 -64
  106. package/dist/components/JamlCurator.stories.d.ts +0 -6
  107. package/dist/components/JamlCurator.stories.js +0 -14
  108. package/dist/components/JamlIde.js +0 -193
  109. package/dist/components/JamlIdeToolbar.js +0 -23
  110. package/dist/components/JamlIdeVisual.js +0 -218
  111. package/dist/components/JamlMapPreview.js +0 -121
  112. package/dist/components/JamlSeedInput.js +0 -26
  113. package/dist/components/JamlSpeedometer.js +0 -70
  114. package/dist/components/Jimbolate.js +0 -17
  115. package/dist/components/MotelyVersionBadge.js +0 -19
  116. package/dist/components/PaginatedFilterBrowser.js +0 -54
  117. package/dist/components/RunConfigModal.js +0 -59
  118. package/dist/components/Standardcard.js +0 -80
  119. package/dist/components/jamlMap/CategoryPicker.js +0 -135
  120. package/dist/components/jamlMap/JamlMapEditor.js +0 -304
  121. package/dist/components/jamlMap/JamlMapEditor.stories.d.ts +0 -7
  122. package/dist/components/jamlMap/JamlMapEditor.stories.js +0 -26
  123. package/dist/components/jamlMap/JamlMapEditorDemo.d.ts +0 -8
  124. package/dist/components/jamlMap/JamlMapEditorDemo.js +0 -323
  125. package/dist/components/jamlMap/JokerPicker.js +0 -113
  126. package/dist/components/jamlMap/MysterySlot.js +0 -128
  127. package/dist/components/jamlMap/MysterySlot.stories.d.ts +0 -7
  128. package/dist/components/jamlMap/MysterySlot.stories.js +0 -31
  129. package/dist/components/jamlMap/index.js +0 -4
  130. package/dist/decode/motelyItemDecoder.js +0 -164
  131. package/dist/decode/motelySprite.js +0 -84
  132. package/dist/hooks/analyzerStreamRegistry.js +0 -96
  133. package/dist/hooks/searchWorker.d.ts +0 -1
  134. package/dist/hooks/searchWorker.js +0 -119
  135. package/dist/hooks/searchWorkerCode.d.ts +0 -1
  136. package/dist/hooks/searchWorkerCode.js +0 -85
  137. package/dist/hooks/useAnalyzer.js +0 -91
  138. package/dist/hooks/useIntersectionObserver.js +0 -52
  139. package/dist/hooks/useSearch.js +0 -161
  140. package/dist/hooks/useShopStream.js +0 -85
  141. package/dist/lib/SpriteMapper.js +0 -48
  142. package/dist/lib/cardParser.js +0 -67
  143. package/dist/lib/classes/BuyMetaData.js +0 -1
  144. package/dist/lib/config.js +0 -15
  145. package/dist/lib/const.js +0 -521
  146. package/dist/lib/data/constants.js +0 -14
  147. package/dist/lib/hooks/useDragScroll.js +0 -48
  148. package/dist/lib/hooks/useJamlFilter.js +0 -219
  149. package/dist/lib/hooks/useSeedAnalyzer.js +0 -50
  150. package/dist/lib/jaml/jamlCompletion.js +0 -13
  151. package/dist/lib/jaml/jamlData.js +0 -6
  152. package/dist/lib/jaml/jamlObjectives.js +0 -97
  153. package/dist/lib/jaml/jamlParser.js +0 -47
  154. package/dist/lib/jaml/jamlPresets.js +0 -61
  155. package/dist/lib/jaml/jamlSchema.js +0 -91
  156. package/dist/lib/parseDailyRitual.js +0 -70
  157. package/dist/lib/tts/getRevealPos.js +0 -16
  158. package/dist/lib/tts/splitTtsDisplay.js +0 -35
  159. package/dist/lib/types.js +0 -1
  160. package/dist/lib/utils.js +0 -5
  161. package/dist/motelyDisplay.js +0 -59
  162. package/dist/r3f/Card3D.js +0 -72
  163. package/dist/r3f/JimboBillboard.js +0 -32
  164. package/dist/r3f/JimboText3D.js +0 -8
  165. package/dist/render/CanvasRenderer.js +0 -11
  166. package/dist/render/Layer.js +0 -18
  167. package/dist/sprites/spriteData.js +0 -100
  168. package/dist/sprites/spriteMapper.js +0 -75
  169. package/dist/stories/Button.d.ts +0 -15
  170. package/dist/stories/Button.js +0 -7
  171. package/dist/stories/Button.stories.d.ts +0 -24
  172. package/dist/stories/Button.stories.js +0 -50
  173. package/dist/stories/Header.d.ts +0 -12
  174. package/dist/stories/Header.js +0 -4
  175. package/dist/stories/Header.stories.d.ts +0 -18
  176. package/dist/stories/Header.stories.js +0 -26
  177. package/dist/stories/Page.d.ts +0 -3
  178. package/dist/stories/Page.js +0 -8
  179. package/dist/stories/Page.stories.d.ts +0 -12
  180. package/dist/stories/Page.stories.js +0 -24
  181. package/dist/ui/Jimbo.stories.d.ts +0 -7
  182. package/dist/ui/Jimbo.stories.js +0 -28
  183. package/dist/ui/JimboBadge.js +0 -8
  184. package/dist/ui/JimboFloating.js +0 -17
  185. package/dist/ui/JimboIconButton.js +0 -28
  186. package/dist/ui/JimboInputModal.js +0 -66
  187. package/dist/ui/JimboSelect.js +0 -43
  188. package/dist/ui/JimboToggleList.js +0 -5
  189. package/dist/ui/PanelSplitter.js +0 -78
  190. package/dist/ui/codeBlock.js +0 -14
  191. package/dist/ui/footer.js +0 -20
  192. package/dist/ui/hooks.js +0 -634
  193. package/dist/ui/ide/AgnosticSeedCard.d.ts +0 -19
  194. package/dist/ui/ide/AgnosticSeedCard.js +0 -48
  195. package/dist/ui/ide/DeckSprite.js +0 -2
  196. package/dist/ui/ide/JamlBuilder.d.ts +0 -1
  197. package/dist/ui/ide/JamlBuilder.js +0 -112
  198. package/dist/ui/ide/JamlEditor.js +0 -486
  199. package/dist/ui/ide/JamlEditorMonaco.d.ts +0 -8
  200. package/dist/ui/ide/JamlEditorMonaco.js +0 -78
  201. package/dist/ui/ide/WasmStatus.d.ts +0 -1
  202. package/dist/ui/ide/WasmStatus.js +0 -42
  203. package/dist/ui/jimboApp.js +0 -15
  204. package/dist/ui/jimboBackground.js +0 -26
  205. package/dist/ui/jimboCopyRow.js +0 -18
  206. package/dist/ui/jimboFilterBar.js +0 -16
  207. package/dist/ui/jimboFlankNav.js +0 -18
  208. package/dist/ui/jimboInfoCard.js +0 -26
  209. package/dist/ui/jimboInset.js +0 -9
  210. package/dist/ui/jimboSectionHeader.js +0 -9
  211. package/dist/ui/jimboStatGrid.js +0 -9
  212. package/dist/ui/jimboTabs.js +0 -22
  213. package/dist/ui/jimboText.js +0 -33
  214. package/dist/ui/jimboTooltip.js +0 -39
  215. package/dist/ui/jimboWordmark.js +0 -9
  216. package/dist/ui/mascot/JammySpeechBox.js +0 -30
  217. package/dist/ui/mascot/SeedMascot.js +0 -17
  218. package/dist/ui/mascot/index.js +0 -3
  219. package/dist/ui/mascot/menuConfig.js +0 -12
  220. package/dist/ui/panel.js +0 -24
  221. package/dist/ui/radial/RadialBadge.js +0 -43
  222. package/dist/ui/radial/RadialBreadcrumb.js +0 -18
  223. package/dist/ui/radial/RadialButton.js +0 -102
  224. package/dist/ui/radial/RadialMenu.js +0 -168
  225. package/dist/ui/radial/RadialPill.js +0 -15
  226. package/dist/ui/radial/index.js +0 -18
  227. package/dist/ui/radial/radialMenuStore.js +0 -122
  228. package/dist/ui/radial/radialMenuViewport.js +0 -59
  229. package/dist/ui/radial/useRadialMenu.js +0 -107
  230. package/dist/ui/showcase.js +0 -20
  231. package/dist/ui/sprites.js +0 -77
  232. package/dist/ui/tokens.js +0 -64
  233. package/dist/utils/gameCardUtils.js +0 -15
  234. package/dist/utils/jamlMapPreview.js +0 -106
  235. package/dist/utils/jamlVisualFilter.js +0 -210
@@ -1,106 +0,0 @@
1
- const CLAUSE_VISUAL_TYPES = {
2
- joker: "joker",
3
- jokers: "joker",
4
- commonJoker: "joker",
5
- commonJokers: "joker",
6
- uncommonJoker: "joker",
7
- uncommonJokers: "joker",
8
- rareJoker: "joker",
9
- rareJokers: "joker",
10
- mixedJoker: "joker",
11
- mixedJokers: "joker",
12
- soulJoker: "joker",
13
- legendaryJoker: "joker",
14
- voucher: "voucher",
15
- vouchers: "voucher",
16
- tarot: "consumable",
17
- tarotCard: "consumable",
18
- spectral: "consumable",
19
- spectralCard: "consumable",
20
- planet: "consumable",
21
- planetCard: "consumable",
22
- boss: "boss",
23
- bosses: "boss",
24
- tag: "tag",
25
- tags: "tag",
26
- smallBlindTag: "tag",
27
- bigBlindTag: "tag",
28
- };
29
- function createEmptyGroups() {
30
- return { must: [], should: [], mustNot: [] };
31
- }
32
- function stripWrappingQuotes(value) {
33
- if ((value.startsWith('"') && value.endsWith('"')) ||
34
- (value.startsWith("'") && value.endsWith("'"))) {
35
- return value.slice(1, -1).trim();
36
- }
37
- return value;
38
- }
39
- function normalizeCandidateValue(value) {
40
- const normalized = stripWrappingQuotes(value.trim()).replace(/,$/, "").trim();
41
- if (!normalized)
42
- return null;
43
- if (normalized === "Any")
44
- return null;
45
- return normalized;
46
- }
47
- function parseInlineValues(raw) {
48
- const trimmed = raw.trim();
49
- if (!trimmed)
50
- return [];
51
- if (trimmed.startsWith("[") && trimmed.includes("]")) {
52
- const body = trimmed.slice(1, trimmed.indexOf("]"));
53
- return body
54
- .split(",")
55
- .map((value) => normalizeCandidateValue(value))
56
- .filter((value) => Boolean(value));
57
- }
58
- const normalized = normalizeCandidateValue(trimmed);
59
- return normalized ? [normalized] : [];
60
- }
61
- export function extractVisualJamlItems(jaml) {
62
- const groups = createEmptyGroups();
63
- const seen = new Set();
64
- const safeJaml = jaml || "";
65
- const lines = safeJaml.replace(/\r\n/g, "\n").split("\n");
66
- let currentSection = null;
67
- for (const rawLine of lines) {
68
- const trimmed = rawLine.trim();
69
- if (!trimmed || trimmed.startsWith("#"))
70
- continue;
71
- const sectionMatch = /^(must|should|mustNot):\s*$/.exec(trimmed);
72
- if (sectionMatch) {
73
- currentSection = sectionMatch[1];
74
- continue;
75
- }
76
- const indent = rawLine.search(/\S|$/);
77
- if (indent === 0 && /^[A-Za-z][A-Za-z0-9]*:\s*/.test(trimmed)) {
78
- currentSection = null;
79
- }
80
- if (!currentSection)
81
- continue;
82
- const clauseMatch = /^-?\s*([A-Za-z][A-Za-z0-9]*):\s*(.*?)\s*$/.exec(trimmed);
83
- if (!clauseMatch)
84
- continue;
85
- const clauseKey = clauseMatch[1];
86
- const visualType = CLAUSE_VISUAL_TYPES[clauseKey];
87
- if (!visualType)
88
- continue;
89
- const values = parseInlineValues(clauseMatch[2]);
90
- for (const value of values) {
91
- const dedupeKey = `${currentSection}:${visualType}:${value.toLowerCase()}`;
92
- if (seen.has(dedupeKey))
93
- continue;
94
- seen.add(dedupeKey);
95
- groups[currentSection].push({
96
- id: dedupeKey,
97
- section: currentSection,
98
- clauseKey,
99
- visualType,
100
- value,
101
- source: rawLine,
102
- });
103
- }
104
- }
105
- return groups;
106
- }
@@ -1,210 +0,0 @@
1
- /**
2
- * Utilities for converting between JAML text and JamlVisualFilter.
3
- *
4
- * Intentionally does NOT depend on a YAML library — uses the same
5
- * line-by-line approach as jamlMapPreview.ts to stay zero-dep.
6
- */
7
- // ─── Text → Filter ────────────────────────────────────────────────────────────
8
- function stripQuotes(s) {
9
- if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
10
- return s.slice(1, -1).trim();
11
- }
12
- return s;
13
- }
14
- function parseScalarValue(raw) {
15
- const v = stripQuotes(raw.trim().replace(/,$/, "").trim());
16
- return v || null;
17
- }
18
- function parseInlineList(raw) {
19
- const t = raw.trim();
20
- if (t.startsWith("[") && t.includes("]")) {
21
- const body = t.slice(1, t.indexOf("]"));
22
- return body
23
- .split(",")
24
- .map((s) => parseScalarValue(s))
25
- .filter((s) => s !== null);
26
- }
27
- const v = parseScalarValue(t);
28
- return v ? [v] : [];
29
- }
30
- function topLevelScalar(lines, key) {
31
- for (const line of lines) {
32
- const m = new RegExp(`^${key}:\\s*(.+)$`).exec(line.trim());
33
- if (m)
34
- return stripQuotes(m[1].trim());
35
- }
36
- return undefined;
37
- }
38
- const CLAUSE_ZONE_KEYS = new Set([
39
- "joker", "jokers", "commonJoker", "commonJokers", "uncommonJoker", "uncommonJokers",
40
- "rareJoker", "rareJokers", "mixedJoker", "mixedJokers", "soulJoker", "legendaryJoker",
41
- "voucher", "vouchers",
42
- "tarot", "tarotCard", "spectral", "spectralCard", "planet", "planetCard",
43
- "boss", "bosses",
44
- "tag", "tags", "smallBlindTag", "bigBlindTag", "smallblindtag", "bigblindtag",
45
- ]);
46
- // JAML uses "mustnot" as zone key in some contexts; the visual filter uses "mustnot".
47
- // The text format may use "mustnot" or "must_not" — handle both, normalise to "mustnot".
48
- function sectionToZone(raw) {
49
- if (raw === "must")
50
- return "must";
51
- if (raw === "should")
52
- return "should";
53
- if (raw === "mustnot" || raw === "must_not" || raw === "mustNot")
54
- return "mustnot";
55
- return null;
56
- }
57
- let _uid = 0;
58
- function uid() {
59
- return `clause-${++_uid}`;
60
- }
61
- export function jamlTextToVisualFilter(text) {
62
- const safeText = text || "";
63
- const lines = safeText.replace(/\r\n/g, "\n").split("\n");
64
- const filter = { must: [], should: [], mustnot: [] };
65
- filter.name = topLevelScalar(lines, "name");
66
- filter.author = topLevelScalar(lines, "author");
67
- filter.description = topLevelScalar(lines, "description");
68
- filter.deck = topLevelScalar(lines, "deck");
69
- filter.stake = topLevelScalar(lines, "stake");
70
- let zone = null;
71
- let current = null;
72
- const seen = new Set();
73
- function flushClause() {
74
- if (!current || !zone)
75
- return;
76
- const dedupeKey = `${zone}:${current.type}:${current.value.toLowerCase()}`;
77
- if (!seen.has(dedupeKey)) {
78
- seen.add(dedupeKey);
79
- const clause = { id: uid(), type: current.type, value: current.value };
80
- if (current.antes && current.antes.length > 0)
81
- clause.antes = current.antes;
82
- if (current.boosterPacks && current.boosterPacks.length > 0)
83
- clause.boosterPacks = current.boosterPacks;
84
- if (current.score !== undefined)
85
- clause.score = current.score;
86
- if (current.edition)
87
- clause.edition = current.edition;
88
- clause.label = current.value;
89
- filter[zone].push(clause);
90
- }
91
- current = null;
92
- }
93
- for (const rawLine of lines) {
94
- const trimmed = rawLine.trim();
95
- if (!trimmed || trimmed.startsWith("#"))
96
- continue;
97
- // Top-level section header: must:/should:/mustnot:
98
- const sectionMatch = /^(must|should|mustnot|must_not|mustNot):\s*$/.exec(trimmed);
99
- if (sectionMatch) {
100
- flushClause();
101
- zone = sectionToZone(sectionMatch[1]);
102
- continue;
103
- }
104
- // Top-level key (non-section) resets zone
105
- const indent = rawLine.search(/\S|$/);
106
- if (indent === 0 && /^[A-Za-z]/.test(trimmed) && !trimmed.startsWith("-")) {
107
- flushClause();
108
- if (!sectionToZone(trimmed.replace(/:.*/, "")))
109
- zone = null;
110
- continue;
111
- }
112
- if (!zone)
113
- continue;
114
- // New clause start: " - rareJoker: Blueprint"
115
- const clauseStart = /^-\s*([A-Za-z][A-Za-z0-9]*):\s*(.*?)\s*$/.exec(trimmed);
116
- if (clauseStart) {
117
- flushClause();
118
- const type = clauseStart[1];
119
- const rawVal = clauseStart[2];
120
- if (!CLAUSE_ZONE_KEYS.has(type))
121
- continue;
122
- const value = parseScalarValue(rawVal) ?? "Any";
123
- current = { type, value };
124
- continue;
125
- }
126
- // Continuation line inside a clause: " antes: [1,2,3]"
127
- if (current && indent > 0 && !trimmed.startsWith("-")) {
128
- const contMatch = /^([A-Za-z_][A-Za-z0-9_]*):\s*(.*?)\s*$/.exec(trimmed);
129
- if (contMatch) {
130
- const key = contMatch[1];
131
- const val = contMatch[2];
132
- if (key === "antes") {
133
- const nums = parseInlineList(val)
134
- .map(Number)
135
- .filter((n) => !isNaN(n));
136
- current.antes = nums;
137
- }
138
- else if (key === "boosterPacks") {
139
- const nums = parseInlineList(val)
140
- .map(Number)
141
- .filter((n) => !isNaN(n));
142
- current.boosterPacks = nums;
143
- }
144
- else if (key === "score") {
145
- const n = Number(val);
146
- if (!isNaN(n))
147
- current.score = n;
148
- }
149
- else if (key === "edition") {
150
- current.edition = parseScalarValue(val) ?? undefined;
151
- }
152
- else if (key === "sources") {
153
- // handled by subsequent nested lines like `boosterPacks: [0, 1]`
154
- }
155
- }
156
- }
157
- }
158
- flushClause();
159
- return filter;
160
- }
161
- // ─── Filter → Text ───────────────────────────────────────────────────────────
162
- function q(s) {
163
- if (!s)
164
- return "";
165
- return /[:#[\]{}|>&*!,'"?]/.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
166
- }
167
- function serializeClause(clause) {
168
- let out = ` - ${clause.type}: ${q(clause.value)}\n`;
169
- if (clause.antes && clause.antes.length > 0) {
170
- out += ` antes: [${clause.antes.join(", ")}]\n`;
171
- }
172
- if (clause.boosterPacks && clause.boosterPacks.length > 0) {
173
- out += ` sources:\n`;
174
- out += ` boosterPacks: [${clause.boosterPacks.join(", ")}]\n`;
175
- }
176
- if (clause.score !== undefined) {
177
- out += ` score: ${clause.score}\n`;
178
- }
179
- if (clause.edition) {
180
- out += ` edition: ${q(clause.edition)}\n`;
181
- }
182
- return out;
183
- }
184
- export function visualFilterToJamlText(filter) {
185
- const parts = [];
186
- if (filter.name)
187
- parts.push(`name: ${q(filter.name)}`);
188
- if (filter.author)
189
- parts.push(`author: ${q(filter.author)}`);
190
- if (filter.description)
191
- parts.push(`description: ${q(filter.description)}`);
192
- if (filter.deck)
193
- parts.push(`deck: ${q(filter.deck)}`);
194
- if (filter.stake)
195
- parts.push(`stake: ${q(filter.stake)}`);
196
- const zones = [
197
- { key: "must", label: "must", clauses: filter.must },
198
- { key: "should", label: "should", clauses: filter.should },
199
- { key: "mustnot", label: "mustnot", clauses: filter.mustnot },
200
- ];
201
- for (const { label, clauses } of zones) {
202
- if (clauses.length > 0) {
203
- parts.push(`${label}:`);
204
- for (const c of clauses) {
205
- parts.push(serializeClause(c).trimEnd());
206
- }
207
- }
208
- }
209
- return parts.join("\n") + "\n";
210
- }