@jjlmoya/utils-diy 1.4.0 → 1.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-diy",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -15,7 +15,7 @@ export type {
15
15
  ToolDefinition,
16
16
  } from './types';
17
17
 
18
- export { ALL_TOOLS } from './tools';
18
+ export { ALL_ENTRIES, ALL_TOOLS } from './tools';
19
19
 
20
20
  export { ClayCalculatorComponent, ClayCalculatorSEO, ClayCalculatorBibliography } from './tool/clayCalculator';
21
21
  export { CLAY_CALCULATOR_TOOL } from './tool/clayCalculator/index';
@@ -0,0 +1,18 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { diyCategory as toolsCategory } from '../category/index';
3
+
4
+ const EXPECTED_LOCALES = [
5
+ 'de', 'en', 'es', 'fr', 'id', 'it', 'ja', 'ko', 'nl', 'pl', 'pt', 'ru', 'sv', 'tr', 'zh'
6
+ ];
7
+
8
+ describe('Category Validation', () => {
9
+ it('should have all 15 required locales', () => {
10
+ const registeredLocales = Object.keys(toolsCategory.i18n);
11
+ EXPECTED_LOCALES.forEach((locale) => {
12
+ expect(
13
+ registeredLocales,
14
+ `Category is missing locale "${locale}"`,
15
+ ).toContain(locale);
16
+ });
17
+ });
18
+ });
@@ -0,0 +1,23 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_TOOLS } from '../tools';
3
+ import type { ToolLocaleContent } from '../types';
4
+
5
+ describe('Slug Language Code Format Validation', () => {
6
+ ALL_TOOLS.forEach((tool) => {
7
+ describe(`Tool: ${tool.entry.id}`, () => {
8
+ it('slug should not end with 2-letter language codes like -ja, -ru, -ko', async () => {
9
+ const locales = Object.keys(tool.entry.i18n);
10
+
11
+ for (const locale of locales) {
12
+ const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
13
+ const content = (await loader?.()) as ToolLocaleContent;
14
+
15
+ expect(
16
+ content.slug,
17
+ `Tool "${tool.entry.id}" locale "${locale}" slug ("${content.slug}") cannot end with a 2-letter language code (e.g., -ja, -ru, -ko).`,
18
+ ).not.toMatch(/-[a-z]{2}$/);
19
+ }
20
+ });
21
+ });
22
+ });
23
+ });
@@ -2,6 +2,54 @@ import { describe, it, expect } from 'vitest';
2
2
  import { ALL_TOOLS } from '../tools';
3
3
  import type { ToolLocaleContent } from '../types';
4
4
 
5
+ const sharingLocales = ['ja', 'ko', 'zh'];
6
+
7
+ interface ValidateParams {
8
+ toolId: string;
9
+ locale: string;
10
+ content: ToolLocaleContent;
11
+ enSlug: string;
12
+ slugs: Map<string, string>;
13
+ }
14
+
15
+ const validateLocaleSlug = ({
16
+ toolId,
17
+ locale,
18
+ content,
19
+ enSlug,
20
+ slugs,
21
+ }: ValidateParams) => {
22
+ expect(
23
+ content.slug,
24
+ `Tool "${toolId}" locale "${locale}" has an invalid slug ("${content.slug}"). Slugs must be transliterated (only a-z, 0-9, and -).`,
25
+ ).toMatch(/^[a-z0-9-]+$/);
26
+
27
+ if (locale === 'en') {
28
+ return;
29
+ }
30
+
31
+ if (sharingLocales.includes(locale)) {
32
+ expect(
33
+ content.slug,
34
+ `Tool "${toolId}" locale "${locale}" must use the same slug as "en" ("${enSlug}").`,
35
+ ).toBe(enSlug);
36
+ } else {
37
+ expect(
38
+ content.slug,
39
+ `Tool "${toolId}" locale "${locale}" has the same slug as "en" ("${enSlug}"). Cada slug tiene que estar en su propia idioma`,
40
+ ).not.toBe(enSlug);
41
+
42
+ if (slugs.has(content.slug)) {
43
+ const previousLocale = slugs.get(content.slug);
44
+ expect(
45
+ false,
46
+ `Tool "${toolId}" locales "${locale}" and "${previousLocale}" share the same slug ("${content.slug}"). Cada slug tiene que estar en su propia idioma`,
47
+ ).toBe(true);
48
+ }
49
+ slugs.set(content.slug, locale);
50
+ }
51
+ };
52
+
5
53
  describe('Slug Localization and Uniqueness Validation', () => {
6
54
  ALL_TOOLS.forEach((tool) => {
7
55
  describe(`Tool: ${tool.entry.id}`, () => {
@@ -16,43 +64,18 @@ describe('Slug Localization and Uniqueness Validation', () => {
16
64
  enSlug = enContent.slug;
17
65
  }
18
66
 
19
- const sharingLocales = ['ja', 'ko', 'zh'];
20
-
21
67
  for (const locale of locales) {
22
68
  const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
23
69
  const content = (await loader?.()) as ToolLocaleContent;
24
-
25
- expect(
26
- content.slug,
27
- `Tool "${tool.entry.id}" locale "${locale}" has an invalid slug ("${content.slug}"). Slugs must be transliterated (only a-z, 0-9, and -).`,
28
- ).toMatch(/^[a-z0-9-]+$/);
29
-
30
- if (locale === 'en') {
31
- continue;
32
- }
33
-
34
- if (sharingLocales.includes(locale)) {
35
- expect(
36
- content.slug,
37
- `Tool "${tool.entry.id}" locale "${locale}" must use the same slug as "en" ("${enSlug}").`,
38
- ).toBe(enSlug);
39
- } else {
40
- expect(
41
- content.slug,
42
- `Tool "${tool.entry.id}" locale "${locale}" has the same slug as "en" ("${enSlug}"). Cada slug tiene que estar en su propia idioma`,
43
- ).not.toBe(enSlug);
44
-
45
- const previousLocale = slugs.get(content.slug);
46
- if (previousLocale) {
47
- expect(
48
- false,
49
- `Tool "${tool.entry.id}" locales "${locale}" and "${previousLocale}" share the same slug ("${content.slug}"). Cada slug tiene que estar en su propia idioma`,
50
- ).toBe(true);
51
- }
52
- slugs.set(content.slug, locale);
53
- }
70
+ validateLocaleSlug({
71
+ toolId: tool.entry.id,
72
+ locale,
73
+ content,
74
+ enSlug,
75
+ slugs,
76
+ });
54
77
  }
55
78
  });
56
79
  });
57
80
  });
58
- });
81
+ });
package/src/tools.ts CHANGED
@@ -14,3 +14,5 @@ import { STAIR_CALCULATOR_TOOL } from './tool/stairCalculator/index';
14
14
  import { DRILL_SHARPENER_TOOL } from './tool/drillSharpener/index';
15
15
 
16
16
  export const ALL_TOOLS: ToolDefinition[] = [CLAY_CALCULATOR_TOOL, EPOXY_CALCULATOR_TOOL, BALUSTER_CALCULATOR_TOOL, MORTAR_CALCULATOR_TOOL, PASSEPARTOUT_CALCULATOR_TOOL, CONCRETE_CALCULATOR_TOOL, CUT_OPTIMIZER_TOOL, VOLTAGE_DROP_CALCULATOR_TOOL, FURNITURE_FIT_TOOL, THERMAL_EXPANSION_CALCULATOR_TOOL, DRILL_CALCULATOR_TOOL, STAIR_CALCULATOR_TOOL, DRILL_SHARPENER_TOOL];
17
+
18
+ export const ALL_ENTRIES = ALL_TOOLS.map(t => t.entry);