@jjlmoya/utils-tabletop 1.31.0 → 1.33.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 (74) hide show
  1. package/package.json +2 -2
  2. package/src/category/i18n/de.ts +1 -1
  3. package/src/category/i18n/es.ts +1 -1
  4. package/src/category/i18n/fr.ts +1 -1
  5. package/src/category/i18n/id.ts +1 -1
  6. package/src/category/i18n/it.ts +1 -1
  7. package/src/category/i18n/nl.ts +1 -1
  8. package/src/category/i18n/pl.ts +1 -1
  9. package/src/category/i18n/pt.ts +1 -1
  10. package/src/category/i18n/ru.ts +1 -1
  11. package/src/category/i18n/sv.ts +1 -1
  12. package/src/category/i18n/tr.ts +1 -1
  13. package/src/category/index.ts +25 -25
  14. package/src/components/PreviewNavSidebar.astro +1 -1
  15. package/src/components/PreviewToolbar.astro +1 -1
  16. package/src/entries.ts +43 -43
  17. package/src/env.d.ts +1 -1
  18. package/src/index.ts +24 -24
  19. package/src/layouts/PreviewLayout.astro +93 -93
  20. package/src/pages/[locale]/[slug].astro +143 -143
  21. package/src/pages/index.astro +1 -1
  22. package/src/tests/bibliography_wellformed_export.test.ts +46 -0
  23. package/src/tests/category_seo_quality.test.ts +74 -0
  24. package/src/tests/i18n_coverage.test.ts +36 -36
  25. package/src/tests/mocks/astro_mock.js +1 -1
  26. package/src/tests/no_em_dash.test.ts +47 -47
  27. package/src/tests/no_en_dash.test.ts +70 -70
  28. package/src/tests/seo_length.test.ts +3 -3
  29. package/src/tests/seo_parity.test.ts +2 -2
  30. package/src/tests/seo_wellformed_export.test.ts +65 -0
  31. package/src/tests/spanish_leakage.test.ts +175 -175
  32. package/src/tool/dungeon-map-generator/component.astro +135 -135
  33. package/src/tool/dungeon-map-generator/controller.ts +243 -243
  34. package/src/tool/dungeon-map-generator/dom-views.ts +144 -144
  35. package/src/tool/dungeon-map-generator/i18n/de.ts +172 -172
  36. package/src/tool/dungeon-map-generator/logic.ts +281 -281
  37. package/src/tool/dungeon-map-generator/random-dungeon-map-generator.css +692 -692
  38. package/src/tool/dungeon-map-generator/ui.ts +54 -54
  39. package/src/tool/fantasy-runes-translator/logic.ts +1 -1
  40. package/src/tool/first-player-selector/i18n/tr.ts +1 -1
  41. package/src/tool/investigation-board/i18n/ru.ts +209 -209
  42. package/src/tool/investigation-board/i18n/zh.ts +209 -209
  43. package/src/tool/lunar-tide-tracker/client.ts +264 -264
  44. package/src/tool/rpg-initiative-tracker/i18n/de.ts +3 -3
  45. package/src/tool/rpg-initiative-tracker/i18n/es.ts +1 -1
  46. package/src/tool/rpg-initiative-tracker/i18n/pl.ts +2 -2
  47. package/src/tool/rpg-initiative-tracker/i18n/ru.ts +1 -1
  48. package/src/tool/score-tracker/i18n/pt.ts +1 -1
  49. package/src/tool/score-tracker/i18n/sv.ts +1 -1
  50. package/src/tool/score-tracker/i18n/tr.ts +1 -1
  51. package/src/tool/score-tracker/i18n/zh.ts +1 -1
  52. package/src/tool/token-stamp-studio/component.astro +0 -1
  53. package/src/tool/token-stamp-studio/dom-views.ts +7 -34
  54. package/src/tool/token-stamp-studio/i18n/de.ts +0 -1
  55. package/src/tool/token-stamp-studio/i18n/en.ts +0 -1
  56. package/src/tool/token-stamp-studio/i18n/es.ts +0 -1
  57. package/src/tool/token-stamp-studio/i18n/fr.ts +0 -1
  58. package/src/tool/token-stamp-studio/i18n/id.ts +0 -1
  59. package/src/tool/token-stamp-studio/i18n/it.ts +0 -1
  60. package/src/tool/token-stamp-studio/i18n/ja.ts +0 -1
  61. package/src/tool/token-stamp-studio/i18n/ko.ts +0 -1
  62. package/src/tool/token-stamp-studio/i18n/nl.ts +0 -1
  63. package/src/tool/token-stamp-studio/i18n/pl.ts +0 -1
  64. package/src/tool/token-stamp-studio/i18n/pt.ts +0 -1
  65. package/src/tool/token-stamp-studio/i18n/ru.ts +0 -1
  66. package/src/tool/token-stamp-studio/i18n/sv.ts +0 -1
  67. package/src/tool/token-stamp-studio/i18n/tr.ts +0 -1
  68. package/src/tool/token-stamp-studio/i18n/zh.ts +0 -1
  69. package/src/tool/token-stamp-studio/token-stamp-studio.css +18 -4
  70. package/src/tool/token-stamp-studio/ui.ts +0 -1
  71. package/src/tool/token-stamp-studio/workspace-media.test.ts +20 -0
  72. package/src/tool/token-stamp-studio/workspace-media.ts +96 -2
  73. package/src/tool/token-stamp-studio/workspace.ts +41 -17
  74. package/src/tools.ts +25 -25
@@ -1,135 +1,135 @@
1
- ---
2
- import { buildMapSvg } from './dom-views';
3
- import { evaluateMap } from './evaluator';
4
- import { DEFAULT_CONFIG, generateDungeon } from './logic';
5
- import type { DungeonMapGeneratorUI } from './ui';
6
-
7
- interface Props {
8
- ui: DungeonMapGeneratorUI;
9
- }
10
-
11
- const { ui } = Astro.props;
12
- const initialMap = generateDungeon(DEFAULT_CONFIG);
13
- const initialEvaluation = evaluateMap(initialMap, ui);
14
- ---
15
-
16
- <div class="dmg" data-dungeon-generator data-style="dungeon">
17
- <script is:inline type="application/json" data-ui set:html={JSON.stringify(ui)} />
18
- <section class="dmg-controls" aria-label={ui.styleLabel}>
19
- <div class="dmg-field dmg-field-seed">
20
- <label for="dmg-seed-input">{ui.seedLabel}</label>
21
- <div class="dmg-seed-input-group">
22
- <input id="dmg-seed-input" name="seed" type="text" value={DEFAULT_CONFIG.seed} maxlength="48" spellcheck="false" />
23
- <button class="dmg-shuffle" type="button" data-random-seed>{ui.randomSeed}</button>
24
- </div>
25
- </div>
26
-
27
- <fieldset class="dmg-styles">
28
- <legend>{ui.styleLabel}</legend>
29
- <label class="dmg-style-card">
30
- <input type="radio" name="style" value="dungeon" checked />
31
- <span class="dmg-style-mark" aria-hidden="true"></span>
32
- <strong>{ui.dungeonStyle}</strong>
33
- <small>{ui.dungeonStyleHint}</small>
34
- </label>
35
- <label class="dmg-style-card">
36
- <input type="radio" name="style" value="cavern" />
37
- <span class="dmg-style-mark dmg-style-mark-cavern" aria-hidden="true"></span>
38
- <strong>{ui.cavernStyle}</strong>
39
- <small>{ui.cavernStyleHint}</small>
40
- </label>
41
- <label class="dmg-style-card">
42
- <input type="radio" name="style" value="scifi" />
43
- <span class="dmg-style-mark dmg-style-mark-scifi" aria-hidden="true"></span>
44
- <strong>{ui.scifiStyle}</strong>
45
- <small>{ui.scifiStyleHint}</small>
46
- </label>
47
- </fieldset>
48
-
49
- <div class="dmg-size-section">
50
- <span class="dmg-section-label">{ui.sizeLabel}</span>
51
- <div class="dmg-size-presets">
52
- <button type="button" data-size data-columns="24" data-rows="18" data-density="38" aria-pressed="false">
53
- <strong>{ui.sizeCompact}</strong><span>24 x 18</span>
54
- </button>
55
- <button type="button" data-size data-columns="36" data-rows="26" data-density="48" aria-pressed="true">
56
- <strong>{ui.sizeSession}</strong><span>36 x 26</span>
57
- </button>
58
- <button type="button" data-size data-columns="52" data-rows="38" data-density="58" aria-pressed="false">
59
- <strong>{ui.sizeStronghold}</strong><span>52 x 38</span>
60
- </button>
61
- </div>
62
- </div>
63
-
64
- <details class="dmg-grid-tuning">
65
- <summary>{ui.fineTuneGrid}</summary>
66
- <div class="dmg-measurements">
67
- <label class="dmg-range">
68
- <span>{ui.columnsLabel}</span>
69
- <output data-output="columns">{DEFAULT_CONFIG.columns}</output>
70
- <input name="columns" data-live-value type="range" min="16" max="64" value={DEFAULT_CONFIG.columns} />
71
- </label>
72
- <label class="dmg-range">
73
- <span>{ui.rowsLabel}</span>
74
- <output data-output="rows">{DEFAULT_CONFIG.rows}</output>
75
- <input name="rows" data-live-value type="range" min="14" max="48" value={DEFAULT_CONFIG.rows} />
76
- </label>
77
- <label class="dmg-range">
78
- <span>{ui.densityLabel}</span>
79
- <output data-output="density">{DEFAULT_CONFIG.density}</output>
80
- <input name="density" data-live-value type="range" min="20" max="75" value={DEFAULT_CONFIG.density} />
81
- <small>{ui.densityHint}</small>
82
- </label>
83
- </div>
84
- </details>
85
-
86
- <button class="dmg-generate" type="button" data-generate>{ui.generate}</button>
87
- </section>
88
-
89
- <section class="dmg-chart" aria-label={ui.mapRegionLabel}>
90
- <div class="dmg-map-frame">
91
- <span class="dmg-edit-hint">{ui.editHint}</span>
92
- <div class="dmg-map-host" data-map-host set:html={buildMapSvg(initialMap)}></div>
93
- <div class="dmg-context-menu" data-context-menu hidden role="menu" aria-label={ui.editCell}>
94
- <button type="button" data-context-tool="floor" role="menuitem">{ui.paintFloor}</button>
95
- <button type="button" data-context-tool="wall" role="menuitem">{ui.paintWall}</button>
96
- <button type="button" data-context-tool="door" role="menuitem">{ui.paintDoor}</button>
97
- </div>
98
- </div>
99
-
100
- <div class="dmg-map-footer" aria-live="polite">
101
- <dl class="dmg-stats">
102
- <div><dt>{ui.roomsLabel}</dt><dd data-room-count>{initialMap.rooms.length}</dd></div>
103
- <div><dt>{ui.doorsLabel}</dt><dd data-door-count>{initialMap.doorCount}</dd></div>
104
- <div><dt>{ui.floorLabel}</dt><dd data-floor-percent>{initialEvaluation.coverage}%</dd></div>
105
- </dl>
106
- <div class="dmg-legend" aria-label={ui.mapReady}>
107
- <span><i data-tile="floor"></i>{ui.legendFloor}</span>
108
- <span><i data-tile="wall"></i>{ui.legendWall}</span>
109
- <span><i data-tile="door"></i>{ui.legendDoor}</span>
110
- </div>
111
- </div>
112
-
113
- <div class="dmg-actions">
114
- <button class="dmg-action-primary" type="button" data-export-png>{ui.exportPng}</button>
115
- <button type="button" data-export-svg>{ui.exportSvg}</button>
116
- <button type="button" data-export-print>{ui.exportPrint}</button>
117
- <button type="button" data-copy-link>{ui.copyLink}</button>
118
- <details class="dmg-map-data">
119
- <summary>{ui.mapData}</summary>
120
- <div>
121
- <button type="button" data-export-json>{ui.exportJson}</button>
122
- <label class="dmg-import">
123
- <span>{ui.importJson}</span>
124
- <input type="file" accept="application/json,.json" data-import-json />
125
- </label>
126
- </div>
127
- </details>
128
- </div>
129
- </section>
130
- </div>
131
-
132
- <script>
133
- import { mountDungeonMapGenerators } from './controller';
134
- mountDungeonMapGenerators();
135
- </script>
1
+ ---
2
+ import { buildMapSvg } from './dom-views';
3
+ import { evaluateMap } from './evaluator';
4
+ import { DEFAULT_CONFIG, generateDungeon } from './logic';
5
+ import type { DungeonMapGeneratorUI } from './ui';
6
+
7
+ interface Props {
8
+ ui: DungeonMapGeneratorUI;
9
+ }
10
+
11
+ const { ui } = Astro.props;
12
+ const initialMap = generateDungeon(DEFAULT_CONFIG);
13
+ const initialEvaluation = evaluateMap(initialMap, ui);
14
+ ---
15
+
16
+ <div class="dmg" data-dungeon-generator data-style="dungeon">
17
+ <script is:inline type="application/json" data-ui set:html={JSON.stringify(ui)} />
18
+ <section class="dmg-controls" aria-label={ui.styleLabel}>
19
+ <div class="dmg-field dmg-field-seed">
20
+ <label for="dmg-seed-input">{ui.seedLabel}</label>
21
+ <div class="dmg-seed-input-group">
22
+ <input id="dmg-seed-input" name="seed" type="text" value={DEFAULT_CONFIG.seed} maxlength="48" spellcheck="false" />
23
+ <button class="dmg-shuffle" type="button" data-random-seed>{ui.randomSeed}</button>
24
+ </div>
25
+ </div>
26
+
27
+ <fieldset class="dmg-styles">
28
+ <legend>{ui.styleLabel}</legend>
29
+ <label class="dmg-style-card">
30
+ <input type="radio" name="style" value="dungeon" checked />
31
+ <span class="dmg-style-mark" aria-hidden="true"></span>
32
+ <strong>{ui.dungeonStyle}</strong>
33
+ <small>{ui.dungeonStyleHint}</small>
34
+ </label>
35
+ <label class="dmg-style-card">
36
+ <input type="radio" name="style" value="cavern" />
37
+ <span class="dmg-style-mark dmg-style-mark-cavern" aria-hidden="true"></span>
38
+ <strong>{ui.cavernStyle}</strong>
39
+ <small>{ui.cavernStyleHint}</small>
40
+ </label>
41
+ <label class="dmg-style-card">
42
+ <input type="radio" name="style" value="scifi" />
43
+ <span class="dmg-style-mark dmg-style-mark-scifi" aria-hidden="true"></span>
44
+ <strong>{ui.scifiStyle}</strong>
45
+ <small>{ui.scifiStyleHint}</small>
46
+ </label>
47
+ </fieldset>
48
+
49
+ <div class="dmg-size-section">
50
+ <span class="dmg-section-label">{ui.sizeLabel}</span>
51
+ <div class="dmg-size-presets">
52
+ <button type="button" data-size data-columns="24" data-rows="18" data-density="38" aria-pressed="false">
53
+ <strong>{ui.sizeCompact}</strong><span>24 x 18</span>
54
+ </button>
55
+ <button type="button" data-size data-columns="36" data-rows="26" data-density="48" aria-pressed="true">
56
+ <strong>{ui.sizeSession}</strong><span>36 x 26</span>
57
+ </button>
58
+ <button type="button" data-size data-columns="52" data-rows="38" data-density="58" aria-pressed="false">
59
+ <strong>{ui.sizeStronghold}</strong><span>52 x 38</span>
60
+ </button>
61
+ </div>
62
+ </div>
63
+
64
+ <details class="dmg-grid-tuning">
65
+ <summary>{ui.fineTuneGrid}</summary>
66
+ <div class="dmg-measurements">
67
+ <label class="dmg-range">
68
+ <span>{ui.columnsLabel}</span>
69
+ <output data-output="columns">{DEFAULT_CONFIG.columns}</output>
70
+ <input name="columns" data-live-value type="range" min="16" max="64" value={DEFAULT_CONFIG.columns} />
71
+ </label>
72
+ <label class="dmg-range">
73
+ <span>{ui.rowsLabel}</span>
74
+ <output data-output="rows">{DEFAULT_CONFIG.rows}</output>
75
+ <input name="rows" data-live-value type="range" min="14" max="48" value={DEFAULT_CONFIG.rows} />
76
+ </label>
77
+ <label class="dmg-range">
78
+ <span>{ui.densityLabel}</span>
79
+ <output data-output="density">{DEFAULT_CONFIG.density}</output>
80
+ <input name="density" data-live-value type="range" min="20" max="75" value={DEFAULT_CONFIG.density} />
81
+ <small>{ui.densityHint}</small>
82
+ </label>
83
+ </div>
84
+ </details>
85
+
86
+ <button class="dmg-generate" type="button" data-generate>{ui.generate}</button>
87
+ </section>
88
+
89
+ <section class="dmg-chart" aria-label={ui.mapRegionLabel}>
90
+ <div class="dmg-map-frame">
91
+ <span class="dmg-edit-hint">{ui.editHint}</span>
92
+ <div class="dmg-map-host" data-map-host set:html={buildMapSvg(initialMap)}></div>
93
+ <div class="dmg-context-menu" data-context-menu hidden role="menu" aria-label={ui.editCell}>
94
+ <button type="button" data-context-tool="floor" role="menuitem">{ui.paintFloor}</button>
95
+ <button type="button" data-context-tool="wall" role="menuitem">{ui.paintWall}</button>
96
+ <button type="button" data-context-tool="door" role="menuitem">{ui.paintDoor}</button>
97
+ </div>
98
+ </div>
99
+
100
+ <div class="dmg-map-footer" aria-live="polite">
101
+ <dl class="dmg-stats">
102
+ <div><dt>{ui.roomsLabel}</dt><dd data-room-count>{initialMap.rooms.length}</dd></div>
103
+ <div><dt>{ui.doorsLabel}</dt><dd data-door-count>{initialMap.doorCount}</dd></div>
104
+ <div><dt>{ui.floorLabel}</dt><dd data-floor-percent>{initialEvaluation.coverage}%</dd></div>
105
+ </dl>
106
+ <div class="dmg-legend" aria-label={ui.mapReady}>
107
+ <span><i data-tile="floor"></i>{ui.legendFloor}</span>
108
+ <span><i data-tile="wall"></i>{ui.legendWall}</span>
109
+ <span><i data-tile="door"></i>{ui.legendDoor}</span>
110
+ </div>
111
+ </div>
112
+
113
+ <div class="dmg-actions">
114
+ <button class="dmg-action-primary" type="button" data-export-png>{ui.exportPng}</button>
115
+ <button type="button" data-export-svg>{ui.exportSvg}</button>
116
+ <button type="button" data-export-print>{ui.exportPrint}</button>
117
+ <button type="button" data-copy-link>{ui.copyLink}</button>
118
+ <details class="dmg-map-data">
119
+ <summary>{ui.mapData}</summary>
120
+ <div>
121
+ <button type="button" data-export-json>{ui.exportJson}</button>
122
+ <label class="dmg-import">
123
+ <span>{ui.importJson}</span>
124
+ <input type="file" accept="application/json,.json" data-import-json />
125
+ </label>
126
+ </div>
127
+ </details>
128
+ </div>
129
+ </section>
130
+ </div>
131
+
132
+ <script>
133
+ import { mountDungeonMapGenerators } from './controller';
134
+ mountDungeonMapGenerators();
135
+ </script>