@jjlmoya/utils-streaming 1.10.0 → 1.12.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 (49) hide show
  1. package/package.json +1 -1
  2. package/src/pages/[locale]/[slug].astro +24 -15
  3. package/src/tests/locale_completeness.test.ts +3 -19
  4. package/src/tests/seo_length.test.ts +1 -0
  5. package/src/tests/shared-test-helpers.ts +56 -0
  6. package/src/tests/title_quality.test.ts +1 -1
  7. package/src/tests/tool_exports.test.ts +34 -0
  8. package/src/tool/sorteo/bibliography.astro +2 -10
  9. package/src/tool/sorteo/bibliography.ts +12 -0
  10. package/src/tool/sorteo/giveaway.css +6 -6
  11. package/src/tool/sorteo/i18n/de.ts +2 -14
  12. package/src/tool/sorteo/i18n/en.ts +2 -14
  13. package/src/tool/sorteo/i18n/es.ts +2 -14
  14. package/src/tool/sorteo/i18n/fr.ts +2 -14
  15. package/src/tool/sorteo/i18n/id.ts +2 -14
  16. package/src/tool/sorteo/i18n/it.ts +2 -14
  17. package/src/tool/sorteo/i18n/ja.ts +2 -14
  18. package/src/tool/sorteo/i18n/ko.ts +2 -14
  19. package/src/tool/sorteo/i18n/nl.ts +2 -14
  20. package/src/tool/sorteo/i18n/pl.ts +2 -14
  21. package/src/tool/sorteo/i18n/pt.ts +2 -14
  22. package/src/tool/sorteo/i18n/ru.ts +2 -14
  23. package/src/tool/sorteo/i18n/sv.ts +2 -14
  24. package/src/tool/sorteo/i18n/tr.ts +2 -14
  25. package/src/tool/sorteo/i18n/zh.ts +2 -14
  26. package/src/tool/sorteo/index.ts +3 -0
  27. package/src/tool/sorteo/seo.astro +2 -1
  28. package/src/tool/sorteo/ui.ts +0 -2
  29. package/src/tool/tebasCheck/bibliography.astro +2 -10
  30. package/src/tool/tebasCheck/bibliography.ts +12 -0
  31. package/src/tool/tebasCheck/i18n/de.ts +2 -14
  32. package/src/tool/tebasCheck/i18n/en.ts +2 -14
  33. package/src/tool/tebasCheck/i18n/es.ts +2 -14
  34. package/src/tool/tebasCheck/i18n/fr.ts +2 -14
  35. package/src/tool/tebasCheck/i18n/id.ts +2 -14
  36. package/src/tool/tebasCheck/i18n/it.ts +2 -14
  37. package/src/tool/tebasCheck/i18n/ja.ts +2 -14
  38. package/src/tool/tebasCheck/i18n/ko.ts +2 -14
  39. package/src/tool/tebasCheck/i18n/nl.ts +2 -14
  40. package/src/tool/tebasCheck/i18n/pl.ts +2 -14
  41. package/src/tool/tebasCheck/i18n/pt.ts +2 -14
  42. package/src/tool/tebasCheck/i18n/ru.ts +2 -14
  43. package/src/tool/tebasCheck/i18n/sv.ts +2 -14
  44. package/src/tool/tebasCheck/i18n/tr.ts +2 -14
  45. package/src/tool/tebasCheck/i18n/zh.ts +2 -14
  46. package/src/tool/tebasCheck/index.ts +3 -0
  47. package/src/tool/tebasCheck/seo.astro +2 -1
  48. package/src/tool/tebasCheck/types.ts +0 -2
  49. package/src/types.ts +2 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-streaming",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -14,7 +14,7 @@ import type { UtilitySEOContent } from "@jjlmoya/utils-shared";
14
14
  export async function getStaticPaths() {
15
15
  const paths = [];
16
16
 
17
- for (const { entry, Component: lazyComp } of ALL_TOOLS) {
17
+ for (const { entry, Component: lazyComp, css } of ALL_TOOLS) {
18
18
  const { default: Component } = await lazyComp();
19
19
  const localeEntries = Object.entries(entry.i18n) as [
20
20
  KnownLocale,
@@ -35,18 +35,25 @@ export async function getStaticPaths() {
35
35
  ) as Partial<Record<KnownLocale, string>>;
36
36
 
37
37
  for (const { locale, content } of localeContents) {
38
- const allToolsNav = await Promise.all(
39
- ALL_TOOLS.map(async ({ entry: navEntry }) => ({
40
- id: navEntry.id,
41
- title: (await navEntry.i18n[locale]!()).title,
42
- href: `/${locale}/${(await navEntry.i18n[locale]!()).slug}`,
43
- isActive: navEntry.id === entry.id,
44
- })),
45
- );
38
+ const allToolsNav = (
39
+ await Promise.all(
40
+ ALL_TOOLS.map(async ({ entry: navEntry }) => {
41
+ const loader = navEntry.i18n[locale] ?? navEntry.i18n.en;
42
+ if (!loader) return null;
43
+ const navContent = await loader();
44
+ return {
45
+ id: navEntry.id,
46
+ title: navContent.title,
47
+ href: `/${locale}/${navContent.slug}`,
48
+ isActive: navEntry.id === entry.id,
49
+ };
50
+ }),
51
+ )
52
+ ).filter(Boolean) as NavItem[];
46
53
  const catCont = await streamingCategory.i18n[locale]!();
47
54
  paths.push({
48
55
  params: { locale, slug: content.slug },
49
- props: { Component, locale, content, localeUrls, allToolsNav, categoryTitle: catCont.title },
56
+ props: { Component, locale, content, localeUrls, allToolsNav, categoryTitle: catCont.title, toolCss: css },
50
57
  });
51
58
  }
52
59
  }
@@ -68,11 +75,12 @@ interface Props {
68
75
  localeUrls: Partial<Record<KnownLocale, string>>;
69
76
  allToolsNav: NavItem[];
70
77
  categoryTitle: string;
78
+ toolCss?: string;
71
79
  }
72
80
 
73
- const { Component, locale, content, localeUrls, allToolsNav, categoryTitle } = Astro.props;
81
+ const { Component, locale, content, localeUrls, allToolsNav, categoryTitle, toolCss } = Astro.props;
74
82
 
75
- const seoContent: UtilitySEOContent = { locale, sections: content.seo };
83
+ const seoContent: UtilitySEOContent = { locale, sections: content.seo ?? [] };
76
84
 
77
85
  const words = content.title.split(" ");
78
86
  const titleHighlight = words[0] || "";
@@ -91,8 +99,9 @@ const titleBase = words.slice(1).join(" ") || "";
91
99
  tools={allToolsNav}
92
100
  />
93
101
  <Fragment slot="head">
102
+ {toolCss ? <Fragment set:html={`<style is:inline>${toolCss}</style>`} /> : null}
94
103
  {
95
- content.schemas.map((schema: unknown) => (
104
+ ( content.schemas ?? []).map((schema: unknown) => (
96
105
  <script
97
106
  is:inline
98
107
  type="application/ld+json"
@@ -118,11 +127,11 @@ const titleBase = words.slice(1).join(" ") || "";
118
127
  </section>
119
128
 
120
129
  <section class="section-faq">
121
- <FAQSection items={content.faq} title={content.ui.faqTitle} inLanguage={locale} />
130
+ <FAQSection items={content.faq} inLanguage={locale} />
122
131
  </section>
123
132
 
124
133
  <section class="section-bibliography">
125
- <Bibliography links={content.bibliography} title={content.ui.bibliographyTitle} />
134
+ <Bibliography links={content.bibliography} />
126
135
  </section>
127
136
  </div>
128
137
  </PreviewLayout>
@@ -7,28 +7,12 @@ describe('Locale Completeness Validation', () => {
7
7
  describe(`Tool: ${tool.entry.id}`, () => {
8
8
  Object.keys(tool.entry.i18n).forEach((locale) => {
9
9
  describe(`Locale: ${locale}`, () => {
10
- it('faqTitle should be defined when faq items exist', async () => {
10
+ it('faq and bibliography should be defined', async () => {
11
11
  const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
12
12
  const content = (await loader?.()) as ToolLocaleContent;
13
13
 
14
- if (content.faq.length > 0) {
15
- expect(
16
- content.faqTitle,
17
- `Tool "${tool.entry.id}" locale "${locale}" has ${content.faq.length} FAQ items but is missing faqTitle`,
18
- ).toBeTruthy();
19
- }
20
- });
21
-
22
- it('bibliographyTitle should be defined when bibliography items exist', async () => {
23
- const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
24
- const content = (await loader?.()) as ToolLocaleContent;
25
-
26
- if (content.bibliography.length > 0) {
27
- expect(
28
- content.bibliographyTitle,
29
- `Tool "${tool.entry.id}" locale "${locale}" has ${content.bibliography.length} bibliography items but is missing bibliographyTitle`,
30
- ).toBeTruthy();
31
- }
14
+ expect(content.faq).toBeDefined();
15
+ expect(content.bibliography).toBeDefined();
32
16
  });
33
17
  });
34
18
  });
@@ -11,6 +11,7 @@ describe('SEO Content Length Validation', () => {
11
11
  Object.keys(entry.i18n).forEach((locale) => {
12
12
  it(`${locale}: SEO section should exist`, async () => {
13
13
  const loader = (entry.i18n as Record<string, () => Promise<{ seo?: unknown[] }>>)[locale];
14
+ if (!loader) return;
14
15
  const content = await loader();
15
16
  if (!content.seo) return;
16
17
  expect(Array.isArray(content.seo)).toBe(true);
@@ -0,0 +1,56 @@
1
+ import type { ToolDefinition } from '../types';
2
+
3
+ export interface ToolExportValidationResult {
4
+ passed: boolean;
5
+ failures: string[];
6
+ }
7
+
8
+ function validateComponentType(
9
+ toolId: string,
10
+ componentName: string,
11
+ component: unknown,
12
+ failures: string[],
13
+ ): void {
14
+ if (typeof component !== 'function') {
15
+ failures.push(`${toolId}: ${componentName} is not a function (${typeof component})`);
16
+ }
17
+ }
18
+
19
+ async function validateComponentExecution(
20
+ toolId: string,
21
+ componentName: string,
22
+ fn: () => Promise<unknown>,
23
+ failures: string[],
24
+ ): Promise<void> {
25
+ try {
26
+ const result = await fn();
27
+ if (!result || typeof result !== 'object') {
28
+ failures.push(`${toolId}: ${componentName} import returned invalid result`);
29
+ }
30
+ } catch (error) {
31
+ failures.push(`${toolId}: ${componentName} execution error - ${error instanceof Error ? error.message : 'unknown'}`);
32
+ }
33
+ }
34
+
35
+ export async function validateToolExports(tools: ToolDefinition[]): Promise<ToolExportValidationResult> {
36
+ const failures: string[] = [];
37
+
38
+ for (const tool of tools) {
39
+ validateComponentType(tool.entry.id, 'Component', tool.Component, failures);
40
+ validateComponentType(tool.entry.id, 'SEOComponent', tool.SEOComponent, failures);
41
+ validateComponentType(tool.entry.id, 'BibliographyComponent', tool.BibliographyComponent, failures);
42
+
43
+ const componentFn = tool.Component as () => Promise<unknown>;
44
+ const seoFn = tool.SEOComponent as () => Promise<unknown>;
45
+ const bibFn = tool.BibliographyComponent as () => Promise<unknown>;
46
+
47
+ await validateComponentExecution(tool.entry.id, 'Component', componentFn, failures);
48
+ await validateComponentExecution(tool.entry.id, 'SEOComponent', seoFn, failures);
49
+ await validateComponentExecution(tool.entry.id, 'BibliographyComponent', bibFn, failures);
50
+ }
51
+
52
+ return {
53
+ passed: failures.length === 0,
54
+ failures,
55
+ };
56
+ }
@@ -41,7 +41,7 @@ describe('Project Titles - Separator Validation', () => {
41
41
  let match;
42
42
  while ((match = pattern.exec(content)) !== null) {
43
43
  const title = match[1];
44
- if (title.includes('|') || title.includes('-')) {
44
+ if (title && (title.includes('|') || title.includes('-'))) {
45
45
  findings.push(title);
46
46
  }
47
47
  }
@@ -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
+ });
@@ -1,14 +1,6 @@
1
1
  ---
2
2
  import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
- import { sorteo } from './index';
4
- import type { KnownLocale } from '../../types';
5
-
6
- interface Props {
7
- locale?: KnownLocale;
8
- }
9
-
10
- const { locale = 'es' } = Astro.props;
11
- const content = await sorteo.i18n[locale]?.();
3
+ import { bibliography } from './bibliography';
12
4
  ---
13
5
 
14
- {content && <SharedBibliography links={content.bibliography} />}
6
+ <SharedBibliography links={bibliography} />
@@ -0,0 +1,12 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: 'Web Crypto API: getRandomValues()',
6
+ url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
7
+ },
8
+ {
9
+ name: 'Fisher-Yates Shuffle Algorithm',
10
+ url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
11
+ },
12
+ ];
@@ -18,7 +18,7 @@
18
18
  padding: 1.5rem;
19
19
  }
20
20
 
21
- :global(.theme-dark) .sorteo-container {
21
+ .theme-dark .sorteo-container {
22
22
  --sorteo-bg: #020617;
23
23
  --sorteo-card: #0f172a;
24
24
  --sorteo-border: #1e293b;
@@ -285,7 +285,7 @@
285
285
  cursor: pointer;
286
286
  }
287
287
 
288
- :global(.theme-dark) .sorteo-option-item {
288
+ .theme-dark .sorteo-option-item {
289
289
  background: rgba(255,255,255,0.02);
290
290
  }
291
291
 
@@ -309,7 +309,7 @@
309
309
  transition: all 0.3s;
310
310
  }
311
311
 
312
- :global(.theme-dark) .sorteo-switch-slider {
312
+ .theme-dark .sorteo-switch-slider {
313
313
  background: #334155;
314
314
  }
315
315
 
@@ -426,7 +426,7 @@
426
426
  color: var(--sorteo-primary);
427
427
  }
428
428
 
429
- :global(.theme-dark) .sorteo-zen-btn:hover {
429
+ .theme-dark .sorteo-zen-btn:hover {
430
430
  background: black;
431
431
  }
432
432
 
@@ -743,7 +743,7 @@
743
743
  transition: transform 0.1s;
744
744
  }
745
745
 
746
- :global(.theme-dark) .sorteo-btn-content {
746
+ .theme-dark .sorteo-btn-content {
747
747
  background: #020617;
748
748
  border-color: #1e293b;
749
749
  }
@@ -762,7 +762,7 @@
762
762
  -webkit-text-fill-color: transparent;
763
763
  }
764
764
 
765
- :global(.theme-dark) .sorteo-btn-content span {
765
+ .theme-dark .sorteo-btn-content span {
766
766
  background: linear-gradient(90deg, #818cf8, #c084fc);
767
767
  -webkit-background-clip: text;
768
768
  -webkit-text-fill-color: transparent;
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Häufig gestellte Fragen',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Technische Referenzen',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Fisher-Yates Shuffle Algorithmus',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Häufig gestellte Fragen',
226
- bibliographyTitle: 'Technische Referenzen',
227
215
  title: 'Zufalls Gewinnspiel',
228
216
  totalParticipants: 'Teilnehmer (einmalig)',
229
217
  ready: 'BEREIT',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Frequently Asked Questions',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Technical References',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Fisher-Yates Shuffle Algorithm',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Frequently Asked Questions',
226
- bibliographyTitle: 'Technical References',
227
215
  title: 'Random Giveaway',
228
216
  totalParticipants: 'Total Unique Participants',
229
217
  ready: 'READY',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Preguntas Frecuentes',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Referencias Técnicas',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Fisher-Yates Shuffle Algorithm',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Preguntas Frecuentes',
226
- bibliographyTitle: 'Referencias Técnicas',
227
215
  title: 'Sorteo Aleatorio',
228
216
  totalParticipants: 'Total Participantes Únicos',
229
217
  ready: 'LISTO',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Questions Fréquemment Posées',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Références Techniques',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Fisher-Yates Shuffle Algorithm',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Questions Fréquemment Posées',
226
- bibliographyTitle: 'Références Techniques',
227
215
  title: 'Tirage au Sort Aléatoire',
228
216
  totalParticipants: 'Total Participants Uniques',
229
217
  ready: 'PRÊT',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Pertanyaan yang Sering Diajukan',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Referensi Teknis',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Algoritma Fisher-Yates Shuffle',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Pertanyaan yang Sering Diajukan',
226
- bibliographyTitle: 'Referensi Teknis',
227
215
  title: 'Giveaway Acak',
228
216
  totalParticipants: 'Total Peserta Unik',
229
217
  ready: 'SIAP',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Domande Frequenti',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Riferimenti Tecnici',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Algoritmo Fisher-Yates Shuffle',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Domande Frequenti',
226
- bibliographyTitle: 'Riferimenti Tecnici',
227
215
  title: 'Giveaway Casuale',
228
216
  totalParticipants: 'Partecipanti Unici Totali',
229
217
  ready: 'PRONTO',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'よくある質問',
101
101
  faq: faqData,
102
- bibliographyTitle: '技術リファレンス',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'フィッシャー–イェーツのシャッフル アルゴリズム',
110
- url: 'https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'よくある質問',
226
- bibliographyTitle: '技術リファレンス',
227
215
  title: 'ランダム抽選',
228
216
  totalParticipants: 'ユニーク参加者数',
229
217
  ready: '準備完了',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: '자주 묻는 질문',
101
101
  faq: faqData,
102
- bibliographyTitle: '기술 문서',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Fisher-Yates Shuffle 알고리즘',
110
- url: 'https://ko.wikipedia.org/wiki/%ED%94%BC%EC%85%94-%EC%9G%B4%EC%B8%A0_%EC%85%94%ED%94%8C',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: '자주 묻는 질문',
226
- bibliographyTitle: '기술 문서',
227
215
  title: '랜덤 추첨',
228
216
  totalParticipants: '전체 고유 참가자',
229
217
  ready: '준비 완료',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Veelgestelde vragen',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Technische Referenties',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Fisher-Yates Shuffle Algoritme',
110
- url: 'https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Veelgestelde vragen',
226
- bibliographyTitle: 'Technische Referenties',
227
215
  title: 'Willekeurige Giveaway',
228
216
  totalParticipants: 'Totaal Unieke Deelnemers',
229
217
  ready: 'GEREED',
@@ -1,3 +1,4 @@
1
+ import { bibliography } from '../bibliography';
1
2
  import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
3
  import type { ToolLocaleContent } from '../../../types';
3
4
  import type { SorteoUI } from '../ui';
@@ -97,19 +98,8 @@ export const content: ToolLocaleContent<SorteoUI> = {
97
98
  slug,
98
99
  title,
99
100
  description,
100
- faqTitle: 'Często Zadawane Pytania',
101
101
  faq: faqData,
102
- bibliographyTitle: 'Referencje Techniczne',
103
- bibliography: [
104
- {
105
- name: 'Web Crypto API: getRandomValues()',
106
- url: 'https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues',
107
- },
108
- {
109
- name: 'Algorytm przetasowania Fishera-Yatesa',
110
- url: 'https://pl.wikipedia.org/wiki/Algorytm_Fishera-Yatesa',
111
- },
112
- ],
102
+ bibliography,
113
103
  howTo: howToData,
114
104
  schemas: [faqSchema as any, howToSchema as any, appSchema as any],
115
105
  seo: [
@@ -222,8 +212,6 @@ export const content: ToolLocaleContent<SorteoUI> = {
222
212
  },
223
213
  ],
224
214
  ui: {
225
- faqTitle: 'Często Zadawane Pytania',
226
- bibliographyTitle: 'Referencje Techniczne',
227
215
  title: 'Losowanie',
228
216
  totalParticipants: 'Suma Unikalnych Uczestników',
229
217
  ready: 'GOTOWE',