@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.
- package/package.json +1 -1
- package/src/pages/[locale]/[slug].astro +24 -15
- package/src/tests/locale_completeness.test.ts +3 -19
- package/src/tests/seo_length.test.ts +1 -0
- package/src/tests/shared-test-helpers.ts +56 -0
- package/src/tests/title_quality.test.ts +1 -1
- package/src/tests/tool_exports.test.ts +34 -0
- package/src/tool/sorteo/bibliography.astro +2 -10
- package/src/tool/sorteo/bibliography.ts +12 -0
- package/src/tool/sorteo/giveaway.css +6 -6
- package/src/tool/sorteo/i18n/de.ts +2 -14
- package/src/tool/sorteo/i18n/en.ts +2 -14
- package/src/tool/sorteo/i18n/es.ts +2 -14
- package/src/tool/sorteo/i18n/fr.ts +2 -14
- package/src/tool/sorteo/i18n/id.ts +2 -14
- package/src/tool/sorteo/i18n/it.ts +2 -14
- package/src/tool/sorteo/i18n/ja.ts +2 -14
- package/src/tool/sorteo/i18n/ko.ts +2 -14
- package/src/tool/sorteo/i18n/nl.ts +2 -14
- package/src/tool/sorteo/i18n/pl.ts +2 -14
- package/src/tool/sorteo/i18n/pt.ts +2 -14
- package/src/tool/sorteo/i18n/ru.ts +2 -14
- package/src/tool/sorteo/i18n/sv.ts +2 -14
- package/src/tool/sorteo/i18n/tr.ts +2 -14
- package/src/tool/sorteo/i18n/zh.ts +2 -14
- package/src/tool/sorteo/index.ts +3 -0
- package/src/tool/sorteo/seo.astro +2 -1
- package/src/tool/sorteo/ui.ts +0 -2
- package/src/tool/tebasCheck/bibliography.astro +2 -10
- package/src/tool/tebasCheck/bibliography.ts +12 -0
- package/src/tool/tebasCheck/i18n/de.ts +2 -14
- package/src/tool/tebasCheck/i18n/en.ts +2 -14
- package/src/tool/tebasCheck/i18n/es.ts +2 -14
- package/src/tool/tebasCheck/i18n/fr.ts +2 -14
- package/src/tool/tebasCheck/i18n/id.ts +2 -14
- package/src/tool/tebasCheck/i18n/it.ts +2 -14
- package/src/tool/tebasCheck/i18n/ja.ts +2 -14
- package/src/tool/tebasCheck/i18n/ko.ts +2 -14
- package/src/tool/tebasCheck/i18n/nl.ts +2 -14
- package/src/tool/tebasCheck/i18n/pl.ts +2 -14
- package/src/tool/tebasCheck/i18n/pt.ts +2 -14
- package/src/tool/tebasCheck/i18n/ru.ts +2 -14
- package/src/tool/tebasCheck/i18n/sv.ts +2 -14
- package/src/tool/tebasCheck/i18n/tr.ts +2 -14
- package/src/tool/tebasCheck/i18n/zh.ts +2 -14
- package/src/tool/tebasCheck/index.ts +3 -0
- package/src/tool/tebasCheck/seo.astro +2 -1
- package/src/tool/tebasCheck/types.ts +0 -2
- package/src/types.ts +2 -3
package/package.json
CHANGED
|
@@ -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 =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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}
|
|
130
|
+
<FAQSection items={content.faq} inLanguage={locale} />
|
|
122
131
|
</section>
|
|
123
132
|
|
|
124
133
|
<section class="section-bibliography">
|
|
125
|
-
<Bibliography links={content.bibliography}
|
|
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('
|
|
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
|
-
|
|
15
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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',
|