@jjlmoya/utils-tabletop 1.3.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 (121) hide show
  1. package/package.json +65 -0
  2. package/scripts/postinstall.mjs +27 -0
  3. package/src/category/TabletopCategorySEO.astro +14 -0
  4. package/src/category/i18n/de.ts +27 -0
  5. package/src/category/i18n/en.ts +27 -0
  6. package/src/category/i18n/es.ts +27 -0
  7. package/src/category/i18n/fr.ts +27 -0
  8. package/src/category/i18n/id.ts +27 -0
  9. package/src/category/i18n/it.ts +27 -0
  10. package/src/category/i18n/ja.ts +27 -0
  11. package/src/category/i18n/ko.ts +27 -0
  12. package/src/category/i18n/nl.ts +27 -0
  13. package/src/category/i18n/pl.ts +27 -0
  14. package/src/category/i18n/pt.ts +27 -0
  15. package/src/category/i18n/ru.ts +27 -0
  16. package/src/category/i18n/sv.ts +27 -0
  17. package/src/category/i18n/tr.ts +27 -0
  18. package/src/category/i18n/zh.ts +27 -0
  19. package/src/category/index.ts +27 -0
  20. package/src/components/PreviewNavSidebar.astro +116 -0
  21. package/src/components/PreviewToolbar.astro +143 -0
  22. package/src/data.ts +10 -0
  23. package/src/entries.ts +10 -0
  24. package/src/env.d.ts +5 -0
  25. package/src/index.ts +21 -0
  26. package/src/layouts/PreviewLayout.astro +117 -0
  27. package/src/pages/[locale]/[slug].astro +161 -0
  28. package/src/pages/[locale].astro +251 -0
  29. package/src/pages/index.astro +4 -0
  30. package/src/tests/faq_count.test.ts +18 -0
  31. package/src/tests/i18n_coverage.test.ts +36 -0
  32. package/src/tests/locale_completeness.test.ts +29 -0
  33. package/src/tests/mocks/astro_mock.js +2 -0
  34. package/src/tests/no_en_dash.test.ts +41 -0
  35. package/src/tests/no_h1_in_components.test.ts +48 -0
  36. package/src/tests/schemas_fulfillment.test.ts +23 -0
  37. package/src/tests/seo_length.test.ts +22 -0
  38. package/src/tests/shared-test-helpers.ts +56 -0
  39. package/src/tests/slug_language_code_format.test.ts +23 -0
  40. package/src/tests/slug_uniqueness.test.ts +81 -0
  41. package/src/tests/title_quality.test.ts +55 -0
  42. package/src/tests/tool_exports.test.ts +34 -0
  43. package/src/tests/tool_validation.test.ts +16 -0
  44. package/src/tool/board-game-timer/bibliography.astro +16 -0
  45. package/src/tool/board-game-timer/bibliography.ts +12 -0
  46. package/src/tool/board-game-timer/board-game-timer.css +1615 -0
  47. package/src/tool/board-game-timer/client.ts +17 -0
  48. package/src/tool/board-game-timer/component.astro +22 -0
  49. package/src/tool/board-game-timer/components/DuelTimer.astro +75 -0
  50. package/src/tool/board-game-timer/components/MultiplayerTimer.astro +58 -0
  51. package/src/tool/board-game-timer/components/SetupPanel.astro +155 -0
  52. package/src/tool/board-game-timer/components/StatsModal.astro +52 -0
  53. package/src/tool/board-game-timer/entry.ts +76 -0
  54. package/src/tool/board-game-timer/i18n/de.ts +303 -0
  55. package/src/tool/board-game-timer/i18n/en.ts +304 -0
  56. package/src/tool/board-game-timer/i18n/es.ts +303 -0
  57. package/src/tool/board-game-timer/i18n/fr.ts +303 -0
  58. package/src/tool/board-game-timer/i18n/id.ts +303 -0
  59. package/src/tool/board-game-timer/i18n/it.ts +303 -0
  60. package/src/tool/board-game-timer/i18n/ja.ts +306 -0
  61. package/src/tool/board-game-timer/i18n/ko.ts +303 -0
  62. package/src/tool/board-game-timer/i18n/nl.ts +303 -0
  63. package/src/tool/board-game-timer/i18n/pl.ts +303 -0
  64. package/src/tool/board-game-timer/i18n/pt.ts +303 -0
  65. package/src/tool/board-game-timer/i18n/ru.ts +303 -0
  66. package/src/tool/board-game-timer/i18n/sv.ts +303 -0
  67. package/src/tool/board-game-timer/i18n/tr.ts +303 -0
  68. package/src/tool/board-game-timer/i18n/zh.ts +303 -0
  69. package/src/tool/board-game-timer/index.ts +9 -0
  70. package/src/tool/board-game-timer/logic.test.ts +282 -0
  71. package/src/tool/board-game-timer/logic.ts +6 -0
  72. package/src/tool/board-game-timer/modules/ColorHelper.ts +26 -0
  73. package/src/tool/board-game-timer/modules/DuelViewManager.ts +120 -0
  74. package/src/tool/board-game-timer/modules/FormatHelper.ts +12 -0
  75. package/src/tool/board-game-timer/modules/GameRunner.ts +136 -0
  76. package/src/tool/board-game-timer/modules/GameState.ts +48 -0
  77. package/src/tool/board-game-timer/modules/MultiplayerViewManager.ts +163 -0
  78. package/src/tool/board-game-timer/modules/SetupPanelManager.ts +209 -0
  79. package/src/tool/board-game-timer/modules/SoundManager.ts +109 -0
  80. package/src/tool/board-game-timer/modules/SpeechManager.ts +1 -0
  81. package/src/tool/board-game-timer/modules/StatsManager.ts +87 -0
  82. package/src/tool/board-game-timer/modules/StatsModalManager.ts +74 -0
  83. package/src/tool/board-game-timer/modules/TimerEngine.ts +175 -0
  84. package/src/tool/board-game-timer/modules/TimerEngineBase.ts +49 -0
  85. package/src/tool/board-game-timer/modules/TimerEngineClock.ts +127 -0
  86. package/src/tool/board-game-timer/modules/TimerStateHelper.ts +55 -0
  87. package/src/tool/board-game-timer/modules/particles.ts +108 -0
  88. package/src/tool/board-game-timer/seo.astro +16 -0
  89. package/src/tool/board-game-timer/types.ts +97 -0
  90. package/src/tool/dice-roller-simulator/bibliography.astro +16 -0
  91. package/src/tool/dice-roller-simulator/bibliography.ts +12 -0
  92. package/src/tool/dice-roller-simulator/client.ts +273 -0
  93. package/src/tool/dice-roller-simulator/component.astro +75 -0
  94. package/src/tool/dice-roller-simulator/components/DiceGrid.astro +55 -0
  95. package/src/tool/dice-roller-simulator/components/RollHistorySection.astro +26 -0
  96. package/src/tool/dice-roller-simulator/components/RollResultBanner.astro +10 -0
  97. package/src/tool/dice-roller-simulator/components/StatsPanel.astro +36 -0
  98. package/src/tool/dice-roller-simulator/dice-roller-simulator.css +1319 -0
  99. package/src/tool/dice-roller-simulator/entry.ts +39 -0
  100. package/src/tool/dice-roller-simulator/i18n/de.ts +305 -0
  101. package/src/tool/dice-roller-simulator/i18n/en.ts +305 -0
  102. package/src/tool/dice-roller-simulator/i18n/es.ts +305 -0
  103. package/src/tool/dice-roller-simulator/i18n/fr.ts +305 -0
  104. package/src/tool/dice-roller-simulator/i18n/id.ts +305 -0
  105. package/src/tool/dice-roller-simulator/i18n/it.ts +305 -0
  106. package/src/tool/dice-roller-simulator/i18n/ja.ts +305 -0
  107. package/src/tool/dice-roller-simulator/i18n/ko.ts +305 -0
  108. package/src/tool/dice-roller-simulator/i18n/nl.ts +305 -0
  109. package/src/tool/dice-roller-simulator/i18n/pl.ts +305 -0
  110. package/src/tool/dice-roller-simulator/i18n/pt.ts +305 -0
  111. package/src/tool/dice-roller-simulator/i18n/ru.ts +305 -0
  112. package/src/tool/dice-roller-simulator/i18n/sv.ts +305 -0
  113. package/src/tool/dice-roller-simulator/i18n/tr.ts +305 -0
  114. package/src/tool/dice-roller-simulator/i18n/zh.ts +305 -0
  115. package/src/tool/dice-roller-simulator/index.ts +9 -0
  116. package/src/tool/dice-roller-simulator/modules/chart.ts +32 -0
  117. package/src/tool/dice-roller-simulator/modules/history.ts +87 -0
  118. package/src/tool/dice-roller-simulator/modules/particles.ts +22 -0
  119. package/src/tool/dice-roller-simulator/seo.astro +16 -0
  120. package/src/tools.ts +9 -0
  121. package/src/types.ts +70 -0
@@ -0,0 +1,55 @@
1
+ import { describe, it } from 'vitest';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ function getFiles(dir: string, ext: string[]): string[] {
6
+ const results: string[] = [];
7
+ if (!fs.existsSync(dir)) return results;
8
+ const list = fs.readdirSync(dir);
9
+ for (const file of list) {
10
+ const fullPath = path.join(dir, file);
11
+ const stat = fs.statSync(fullPath);
12
+ if (stat && stat.isDirectory()) {
13
+ results.push(...getFiles(fullPath, ext));
14
+ } else if (ext.some((e) => file.endsWith(e))) {
15
+ results.push(fullPath);
16
+ }
17
+ }
18
+ return results;
19
+ }
20
+
21
+ const SRC_DIR = path.join(process.cwd(), 'src');
22
+
23
+ describe('Project Titles - Separator Validation', () => {
24
+ const files = [
25
+ ...getFiles(path.join(SRC_DIR, 'tool'), ['.ts']),
26
+ ...getFiles(path.join(SRC_DIR, 'category'), ['.ts']),
27
+ ].filter(f => f.includes('i18n'));
28
+
29
+ it.each(files)('Verify that titles in %s do not contain | or -', (filePath) => {
30
+ const content = fs.readFileSync(filePath, 'utf-8');
31
+ const relativePath = path.relative(process.cwd(), filePath);
32
+
33
+ const titlePatterns = [
34
+ /const\s+title\s*=\s*['"]([^'"]+)['"]/g,
35
+ /title\s*:\s*['"]([^'"]+)['"]/g,
36
+ ];
37
+
38
+ const findings: string[] = [];
39
+
40
+ for (const pattern of titlePatterns) {
41
+ let match;
42
+ while ((match = pattern.exec(content)) !== null) {
43
+ const title = match[1];
44
+ if (title.includes('|') || title.includes('-')) {
45
+ findings.push(title);
46
+ }
47
+ }
48
+ }
49
+
50
+ if (findings.length > 0) {
51
+ const list = findings.map((f) => ` - "${f}"`).join('\n');
52
+ throw new Error(`Forbidden separators (| or -) found in titles in ${relativePath}:\n${list}`);
53
+ }
54
+ });
55
+ });
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_TOOLS } from '../tools';
3
+ import { validateToolExports } from './shared-test-helpers';
4
+
5
+ describe('Tool Exports Pattern Validation', () => {
6
+ describe('Component Exports Format', () => {
7
+ ALL_TOOLS.forEach((tool) => {
8
+ it(`${tool.entry.id}: Component should be a lazy-loaded function`, () => {
9
+ expect(typeof tool.Component).toBe('function');
10
+ expect(tool.Component).toBeInstanceOf(Function);
11
+ });
12
+
13
+ it(`${tool.entry.id}: SEOComponent should be a lazy-loaded function`, () => {
14
+ expect(typeof tool.SEOComponent).toBe('function');
15
+ expect(tool.SEOComponent).toBeInstanceOf(Function);
16
+ });
17
+
18
+ it(`${tool.entry.id}: BibliographyComponent should be a lazy-loaded function`, () => {
19
+ expect(typeof tool.BibliographyComponent).toBe('function');
20
+ expect(tool.BibliographyComponent).toBeInstanceOf(Function);
21
+ });
22
+ });
23
+ });
24
+
25
+ describe('Dynamic Import Validation', () => {
26
+ it('all tools must have functional dynamic imports', async () => {
27
+ const result = await validateToolExports(ALL_TOOLS);
28
+ if (!result.passed) {
29
+ throw new Error(`Tool export validation failed:\n${result.failures.join('\n')}`);
30
+ }
31
+ expect(result.passed).toBe(true);
32
+ });
33
+ });
34
+ });
@@ -0,0 +1,16 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_TOOLS } from '../tools';
3
+ import { tabletopCategory } from '../data';
4
+
5
+ describe('Tool Validation Suite', () => {
6
+ describe('Library Registration', () => {
7
+ it('should have tools in ALL_TOOLS', () => {
8
+ expect(ALL_TOOLS.length).toBe(2);
9
+ });
10
+
11
+ it('tabletopCategory should be defined', () => {
12
+ expect(tabletopCategory).toBeDefined();
13
+ expect(tabletopCategory.i18n).toBeDefined();
14
+ });
15
+ });
16
+ });
@@ -0,0 +1,16 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { boardGameTimer } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'en' } = Astro.props as Props;
11
+ const loader = boardGameTimer.i18n[locale] || boardGameTimer.i18n.en;
12
+ const content = await loader?.();
13
+ if (!content) return null;
14
+ ---
15
+
16
+ {content && <SharedBibliography links={content.bibliography} />}
@@ -0,0 +1,12 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: 'Board Game Timer Strategies',
6
+ url: 'https://boardgamegeek.com/thread/3123456/timer-strategies-competitive-play',
7
+ },
8
+ {
9
+ name: 'Chess Clock Rules and Variations',
10
+ url: 'https://en.wikipedia.org/wiki/Chess_clock',
11
+ },
12
+ ];