@jjlmoya/utils-creative 1.5.0 → 1.7.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 +62 -62
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/bead-pattern-generator/component.astro +29 -21
- package/src/tool/bead-pattern-generator/i18n/en.ts +73 -19
- package/src/tool/bead-pattern-generator/i18n/es.ts +73 -19
- package/src/tool/bead-pattern-generator/i18n/fr.ts +73 -19
- package/src/tool/bead-pattern-generator/index.ts +14 -2
- package/src/tool/dice-roller/component.astro +42 -30
- package/src/tool/dice-roller/i18n/en.ts +84 -33
- package/src/tool/dice-roller/i18n/es.ts +84 -33
- package/src/tool/dice-roller/i18n/fr.ts +84 -33
- package/src/tool/dice-roller/index.ts +9 -0
- package/src/tool/excuse-generator/i18n/en.ts +60 -18
- package/src/tool/excuse-generator/i18n/es.ts +60 -18
- package/src/tool/excuse-generator/i18n/fr.ts +60 -18
- package/src/tool/fortune-cookie/component.astro +27 -16
- package/src/tool/fortune-cookie/i18n/en.ts +60 -18
- package/src/tool/fortune-cookie/i18n/es.ts +60 -18
- package/src/tool/fortune-cookie/i18n/fr.ts +60 -18
- package/src/tool/synesthesia-painter/component.astro +5 -5
- package/src/tool/synesthesia-painter/i18n/en.ts +74 -32
- package/src/tool/synesthesia-painter/i18n/es.ts +74 -32
- package/src/tool/synesthesia-painter/i18n/fr.ts +74 -32
- package/src/tool/zalgo-generator/component.astro +29 -18
- package/src/tool/zalgo-generator/i18n/en.ts +70 -17
- package/src/tool/zalgo-generator/i18n/es.ts +70 -17
- package/src/tool/zalgo-generator/i18n/fr.ts +70 -17
- package/src/tool/zalgo-generator/index.ts +11 -0
- package/src/tools.ts +14 -1
|
@@ -1,9 +1,77 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
1
2
|
import type { DiceRollerLocaleContent } from '../index';
|
|
2
3
|
|
|
4
|
+
const slug = 'lanceur-de-des';
|
|
5
|
+
const title = 'Lanceur de Dés';
|
|
6
|
+
const description = 'Un simulateur de dés complet pour vos JdR et jeux de société. Lancez des d4, d6, d8, d10, d12, d20 et d100 avec modificateurs et historique.';
|
|
7
|
+
|
|
8
|
+
const faq: DiceRollerLocaleContent['faq'] = [
|
|
9
|
+
{
|
|
10
|
+
question: 'Comment simuler un lancer avec avantage (D&D) ?',
|
|
11
|
+
answer: 'Ajoutez deux dés d20 à votre réserve en cliquant deux fois sur le bouton d20. Lors du lancer, observez les deux résultats individuels et gardez le plus élevé. Le total affiché sera la somme, mais vous pouvez voir chaque dé séparément dans le détail du résultat.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
question: 'Que signifient les couleurs verte ou rouge sur les résultats ?',
|
|
15
|
+
answer: 'Les résultats en vert indiquent que le dé a obtenu sa valeur maximale possible (un "critique"). Les résultats en rouge indiquent la valeur minimale (un "1", le pire résultat possible). Cela permet de repérer les critiques et les échecs d\'un coup d\'œil.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
question: 'Puis-je ajouter plusieurs dés du même type ?',
|
|
19
|
+
answer: 'Oui. Chaque clic sur un dé l\'ajoute à votre réserve. Si vous cliquez trois fois sur le d6, la réserve affichera "3d6". Pour réduire le nombre, cliquez sur le bouton "−" qui apparaît à côté de chaque groupe de dés.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Les dés numériques sont-ils aussi aléatoires que les physiques ?',
|
|
23
|
+
answer: 'Statistiquement, oui. Les moteurs JavaScript modernes utilisent des algorithmes pseudo-aléatoires (xorshift128+) avec une distribution uniforme de très haute qualité. Un vrai dé physique peut présenter de petites imperfections de fabrication qui biaisent les résultats ; le dé numérique n\'a pas ce problème.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
question: 'Qu\'est-ce que le d100 et comment est-il utilisé ?',
|
|
27
|
+
answer: 'Le d100 (ou d%) génère un nombre de 1 à 100 et est utilisé dans les systèmes de jeu basés sur les pourcentages, tels que l\'Appel de Cthulhu ou Warhammer Fantasy. Il représente une "probabilité directe" : si votre compétence en Discrétion est de 65 %, vous devez obtenir 65 ou moins pour réussir.',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const howTo: DiceRollerLocaleContent['howTo'] = [
|
|
32
|
+
{ name: 'Composer la réserve de dés', text: 'Cliquez sur les boutons des dés (d4, d6, d8...) pour les ajouter à votre réserve. Chaque clic ajoute un dé du type sélectionné. Vous pouvez mélanger différents types dans le même lancer.' },
|
|
33
|
+
{ name: 'Ajuster le modificateur', text: 'Utilisez les boutons "+" et "−" à côté du modificateur pour appliquer des bonus ou des pénalités (comme le modificateur de caractéristique dans D&D). Le modificateur est automatiquement ajouté au total.' },
|
|
34
|
+
{ name: 'Lancer les dés', text: 'Appuyez sur le bouton "Lancer les dés". Le panneau de droite affiche le total final et le détail de chaque dé individuel, avec les critiques (maximum) en vert et les échecs (minimum) en rouge.' },
|
|
35
|
+
{ name: 'Consulter l\'historique', text: 'Chaque lancer est enregistré dans l\'historique avec l\'expression de dés utilisée, le résultat total et l\'heure exacte. Vous pouvez effacer l\'historique avec le bouton correspondant.' },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
39
|
+
'@context': 'https://schema.org',
|
|
40
|
+
'@type': 'FAQPage',
|
|
41
|
+
mainEntity: faq.map((item) => ({
|
|
42
|
+
'@type': 'Question',
|
|
43
|
+
name: item.question,
|
|
44
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
45
|
+
})),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const howToSchema: WithContext<HowTo> = {
|
|
49
|
+
'@context': 'https://schema.org',
|
|
50
|
+
'@type': 'HowTo',
|
|
51
|
+
name: title,
|
|
52
|
+
description,
|
|
53
|
+
step: howTo.map((step) => ({
|
|
54
|
+
'@type': 'HowToStep',
|
|
55
|
+
name: step.name,
|
|
56
|
+
text: step.text,
|
|
57
|
+
})),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
61
|
+
'@context': 'https://schema.org',
|
|
62
|
+
'@type': 'SoftwareApplication',
|
|
63
|
+
name: title,
|
|
64
|
+
description,
|
|
65
|
+
applicationCategory: 'UtilitiesApplication',
|
|
66
|
+
operatingSystem: 'Web',
|
|
67
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
68
|
+
inLanguage: 'fr',
|
|
69
|
+
};
|
|
70
|
+
|
|
3
71
|
export const content: DiceRollerLocaleContent = {
|
|
4
|
-
slug
|
|
5
|
-
title
|
|
6
|
-
description
|
|
72
|
+
slug,
|
|
73
|
+
title,
|
|
74
|
+
description,
|
|
7
75
|
faqTitle: 'Questions Fréquemment Posées',
|
|
8
76
|
bibliographyTitle: 'Bibliographie du Hasard',
|
|
9
77
|
ui: {
|
|
@@ -14,7 +82,16 @@ export const content: DiceRollerLocaleContent = {
|
|
|
14
82
|
historyLabel: 'Historique',
|
|
15
83
|
clearHistoryBtn: 'Effacer l\'historique',
|
|
16
84
|
faqTitle: 'FAQ',
|
|
17
|
-
bibliographyTitle: 'Références'
|
|
85
|
+
bibliographyTitle: 'Références',
|
|
86
|
+
addDiceLabel: 'Ajouter des dés au sac',
|
|
87
|
+
bagLabel: 'Sac de dés',
|
|
88
|
+
emptyBagBtn: 'Vider',
|
|
89
|
+
emptyBagText: 'Cliquez sur les dés pour les ajouter',
|
|
90
|
+
modifierLabel: 'Modificateur',
|
|
91
|
+
rollManyLabel: 'Lancer $COUNT dés',
|
|
92
|
+
rollOneLabel: 'Lancer $COUNT dé',
|
|
93
|
+
preRollText: 'Ajoutez des dés et lancez',
|
|
94
|
+
emptyHistoryText: 'L\'historique des lancers apparaîtra ici'
|
|
18
95
|
},
|
|
19
96
|
seo: [
|
|
20
97
|
{ type: 'title', text: 'L\'Art du Hasard : Histoire et Mathématiques des Dés', level: 2 },
|
|
@@ -50,38 +127,12 @@ export const content: DiceRollerLocaleContent = {
|
|
|
50
127
|
{ term: 'Lancer Centile', definition: 'Un lancer utilisant deux d10 pour produire un résultat de 1 à 100, utilisé dans les systèmes basés sur les compétences où les capacités sont mesurées en pourcentages.' },
|
|
51
128
|
]},
|
|
52
129
|
],
|
|
53
|
-
faq
|
|
54
|
-
{
|
|
55
|
-
question: 'Comment simuler un lancer avec avantage (D&D) ?',
|
|
56
|
-
answer: 'Ajoutez deux dés d20 à votre réserve en cliquant deux fois sur le bouton d20. Lors du lancer, observez les deux résultats individuels et gardez le plus élevé. Le total affiché sera la somme, mais vous pouvez voir chaque dé séparément dans le détail du résultat.',
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
question: 'Que signifient les couleurs verte ou rouge sur les résultats ?',
|
|
60
|
-
answer: 'Les résultats en vert indiquent que le dé a obtenu sa valeur maximale possible (un "critique"). Les résultats en rouge indiquent la valeur minimale (un "1", le pire résultat possible). Cela permet de repérer les critiques et les échecs d\'un coup d\'œil.',
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
question: 'Puis-je ajouter plusieurs dés du même type ?',
|
|
64
|
-
answer: 'Oui. Chaque clic sur un dé l\'ajoute à votre réserve. Si vous cliquez trois fois sur le d6, la réserve affichera "3d6". Pour réduire le nombre, cliquez sur le bouton "−" qui apparaît à côté de chaque groupe de dés.',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
question: 'Les dés numériques sont-ils aussi aléatoires que les physiques ?',
|
|
68
|
-
answer: 'Statistiquement, oui. Les moteurs JavaScript modernes utilisent des algorithmes pseudo-aléatoires (xorshift128+) avec une distribution uniforme de très haute qualité. Un vrai dé physique peut présenter de petites imperfections de fabrication qui biaisent les résultats ; le dé numérique n\'a pas ce problème.',
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
question: 'Qu\'est-ce que le d100 et comment est-il utilisé ?',
|
|
72
|
-
answer: 'Le d100 (ou d%) génère un nombre de 1 à 100 et est utilisé dans les systèmes de jeu basés sur les pourcentages, tels que l\'Appel de Cthulhu ou Warhammer Fantasy. Il représente une "probabilité directe" : si votre compétence en Discrétion est de 65 %, vous devez obtenir 65 ou moins pour réussir.',
|
|
73
|
-
},
|
|
74
|
-
],
|
|
130
|
+
faq,
|
|
75
131
|
bibliography: [
|
|
76
132
|
{ name: 'D&D Beyond – Règles des mécaniques de dés', url: 'https://www.dndbeyond.com/sources/basic-rules/using-ability-scores' },
|
|
77
133
|
{ name: 'Roll20 – Table de jeu virtuelle et systèmes de dés', url: 'https://roll20.net/' },
|
|
78
134
|
{ name: 'Pathfinder – Référence du système d20', url: 'https://paizo.com/pathfinder' },
|
|
79
135
|
],
|
|
80
|
-
howTo
|
|
81
|
-
|
|
82
|
-
{ name: 'Ajuster le modificateur', text: 'Utilisez les boutons "+" et "−" à côté du modificateur pour appliquer des bonus ou des pénalités (comme le modificateur de caractéristique dans D&D). Le modificateur est automatiquement ajouté au total.' },
|
|
83
|
-
{ name: 'Lancer les dés', text: 'Appuyez sur le bouton "Lancer les dés". Le panneau de droite affiche le total final et le détail de chaque dé individuel, avec les critiques (maximum) en vert et les échecs (minimum) en rouge.' },
|
|
84
|
-
{ name: 'Consulter l\'historique', text: 'Chaque lancer est enregistré dans l\'historique avec l\'expression de dés utilisée, le résultat total et l\'heure exacte. Vous pouvez effacer l\'historique avec le bouton correspondant.' },
|
|
85
|
-
],
|
|
86
|
-
schemas: []
|
|
136
|
+
howTo,
|
|
137
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
87
138
|
};
|
|
@@ -13,6 +13,15 @@ export interface DiceRollerUI {
|
|
|
13
13
|
clearHistoryBtn: string;
|
|
14
14
|
faqTitle: string;
|
|
15
15
|
bibliographyTitle: string;
|
|
16
|
+
addDiceLabel: string;
|
|
17
|
+
bagLabel: string;
|
|
18
|
+
emptyBagBtn: string;
|
|
19
|
+
emptyBagText: string;
|
|
20
|
+
modifierLabel: string;
|
|
21
|
+
rollManyLabel: string;
|
|
22
|
+
rollOneLabel: string;
|
|
23
|
+
preRollText: string;
|
|
24
|
+
emptyHistoryText: string;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
export type DiceRollerLocaleContent = ToolLocaleContent<DiceRollerUI>;
|
|
@@ -1,9 +1,63 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
1
2
|
import type { ExcuseGeneratorLocaleContent } from '../index';
|
|
2
3
|
|
|
4
|
+
const slug = 'excuse-generator';
|
|
5
|
+
const title = 'Excuse Generator';
|
|
6
|
+
const description = 'Semantic gambling machine to get rid of commitments with style. Generate surreal and irrefutable excuses instantly.';
|
|
7
|
+
|
|
8
|
+
const faq: ExcuseGeneratorLocaleContent['faq'] = [
|
|
9
|
+
{
|
|
10
|
+
question: 'Can this generator save my marriage?',
|
|
11
|
+
answer: 'While we are not therapists, avoiding that dinner with the in-laws using a plausible technical emergency can significantly reduce tension. Use responsibly.'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
question: 'Why such surreal phrases?',
|
|
15
|
+
answer: 'The strategy is based on Cognitive Dissonance. If you say something boring it is verifiable. If you say something absurd, the surprise blocks the capacity for anger.'
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const howTo: ExcuseGeneratorLocaleContent['howTo'] = [
|
|
20
|
+
{ name: 'Generate', text: 'Click the generate button to create a new excuse.' },
|
|
21
|
+
{ name: 'Copy', text: 'Click the copy button to bring the excuse to your clipboard.' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
25
|
+
'@context': 'https://schema.org',
|
|
26
|
+
'@type': 'FAQPage',
|
|
27
|
+
mainEntity: faq.map((item) => ({
|
|
28
|
+
'@type': 'Question',
|
|
29
|
+
name: item.question,
|
|
30
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const howToSchema: WithContext<HowTo> = {
|
|
35
|
+
'@context': 'https://schema.org',
|
|
36
|
+
'@type': 'HowTo',
|
|
37
|
+
name: title,
|
|
38
|
+
description,
|
|
39
|
+
step: howTo.map((step) => ({
|
|
40
|
+
'@type': 'HowToStep',
|
|
41
|
+
name: step.name,
|
|
42
|
+
text: step.text,
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
47
|
+
'@context': 'https://schema.org',
|
|
48
|
+
'@type': 'SoftwareApplication',
|
|
49
|
+
name: title,
|
|
50
|
+
description,
|
|
51
|
+
applicationCategory: 'UtilitiesApplication',
|
|
52
|
+
operatingSystem: 'Web',
|
|
53
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
54
|
+
inLanguage: 'en',
|
|
55
|
+
};
|
|
56
|
+
|
|
3
57
|
export const content: ExcuseGeneratorLocaleContent = {
|
|
4
|
-
slug
|
|
5
|
-
title
|
|
6
|
-
description
|
|
58
|
+
slug,
|
|
59
|
+
title,
|
|
60
|
+
description,
|
|
7
61
|
faqTitle: 'Frequently Asked Questions',
|
|
8
62
|
bibliographyTitle: 'Leisure Bibliography',
|
|
9
63
|
ui: {
|
|
@@ -59,22 +113,10 @@ export const content: ExcuseGeneratorLocaleContent = {
|
|
|
59
113
|
{ pro: 'Creative and humorous tone defuses tension', con: 'Not suitable for formal or professional contexts' },
|
|
60
114
|
]},
|
|
61
115
|
],
|
|
62
|
-
faq
|
|
63
|
-
{
|
|
64
|
-
question: 'Can this generator save my marriage?',
|
|
65
|
-
answer: 'While we are not therapists, avoiding that dinner with the in-laws using a plausible technical emergency can significantly reduce tension. Use responsibly.'
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
question: 'Why such surreal phrases?',
|
|
69
|
-
answer: 'The strategy is based on Cognitive Dissonance. If you say something boring it is verifiable. If you say something absurd, the surprise blocks the capacity for anger.'
|
|
70
|
-
}
|
|
71
|
-
],
|
|
116
|
+
faq,
|
|
72
117
|
bibliography: [
|
|
73
118
|
{ name: 'Procrastinator\'s Manifesto', url: 'https://example.com/manifesto' }
|
|
74
119
|
],
|
|
75
|
-
howTo
|
|
76
|
-
|
|
77
|
-
{ name: 'Copy', text: 'Click the copy button to bring the excuse to your clipboard.' }
|
|
78
|
-
],
|
|
79
|
-
schemas: []
|
|
120
|
+
howTo,
|
|
121
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
80
122
|
};
|
|
@@ -1,9 +1,63 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
1
2
|
import type { ExcuseGeneratorLocaleContent } from '../index';
|
|
2
3
|
|
|
4
|
+
const slug = 'generador-excusas';
|
|
5
|
+
const title = 'Generador de Excusas';
|
|
6
|
+
const description = 'Máquina de azar semántica para librarte de compromisos con estilo.';
|
|
7
|
+
|
|
8
|
+
const faq: ExcuseGeneratorLocaleContent['faq'] = [
|
|
9
|
+
{
|
|
10
|
+
question: '¿Puede este generador salvar mi matrimonio?',
|
|
11
|
+
answer: 'Aunque no somos terapeutas, evitar esa cena con los suegros utilizando una emergencia técnica plausible puede reducir la tensión significativamente.'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
question: '¿Por qué frases tan surrealistas?',
|
|
15
|
+
answer: 'La estrategia se basa en la Disonancia Cognitiva. Si dices algo aburrido es comprobable. Si dices algo absurdo, la sorpresa bloquea la capacidad de enfado.'
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const howTo: ExcuseGeneratorLocaleContent['howTo'] = [
|
|
20
|
+
{ name: 'Generar', text: 'Pulsa el botón de generar para crear una nueva excusa.' },
|
|
21
|
+
{ name: 'Copiar', text: 'Haz clic en el botón de copiar para llevar la excusa a tu portapapeles.' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
25
|
+
'@context': 'https://schema.org',
|
|
26
|
+
'@type': 'FAQPage',
|
|
27
|
+
mainEntity: faq.map((item) => ({
|
|
28
|
+
'@type': 'Question',
|
|
29
|
+
name: item.question,
|
|
30
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const howToSchema: WithContext<HowTo> = {
|
|
35
|
+
'@context': 'https://schema.org',
|
|
36
|
+
'@type': 'HowTo',
|
|
37
|
+
name: title,
|
|
38
|
+
description,
|
|
39
|
+
step: howTo.map((step) => ({
|
|
40
|
+
'@type': 'HowToStep',
|
|
41
|
+
name: step.name,
|
|
42
|
+
text: step.text,
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
47
|
+
'@context': 'https://schema.org',
|
|
48
|
+
'@type': 'SoftwareApplication',
|
|
49
|
+
name: title,
|
|
50
|
+
description,
|
|
51
|
+
applicationCategory: 'UtilitiesApplication',
|
|
52
|
+
operatingSystem: 'Web',
|
|
53
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
54
|
+
inLanguage: 'es',
|
|
55
|
+
};
|
|
56
|
+
|
|
3
57
|
export const content: ExcuseGeneratorLocaleContent = {
|
|
4
|
-
slug
|
|
5
|
-
title
|
|
6
|
-
description
|
|
58
|
+
slug,
|
|
59
|
+
title,
|
|
60
|
+
description,
|
|
7
61
|
faqTitle: 'Preguntas Frecuentes',
|
|
8
62
|
bibliographyTitle: 'Bibliografía del Ocio',
|
|
9
63
|
ui: {
|
|
@@ -63,22 +117,10 @@ export const content: ExcuseGeneratorLocaleContent = {
|
|
|
63
117
|
{ pro: 'El tono creativo y humorístico difunde la tensión', con: 'No apta para contextos formales o profesionales' },
|
|
64
118
|
]},
|
|
65
119
|
],
|
|
66
|
-
faq
|
|
67
|
-
{
|
|
68
|
-
question: '¿Puede este generador salvar mi matrimonio?',
|
|
69
|
-
answer: 'Aunque no somos terapeutas, evitar esa cena con los suegros utilizando una emergencia técnica plausible puede reducir la tensión significativamente.'
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
question: '¿Por qué frases tan surrealistas?',
|
|
73
|
-
answer: 'La estrategia se basa en la Disonancia Cognitiva. Si dices algo aburrido es comprobable. Si dices algo absurdo, la sorpresa bloquea la capacidad de enfado.'
|
|
74
|
-
}
|
|
75
|
-
],
|
|
120
|
+
faq,
|
|
76
121
|
bibliography: [
|
|
77
122
|
{ name: 'Manifesto del Procrastinador', url: 'https://example.com/manifesto' }
|
|
78
123
|
],
|
|
79
|
-
howTo
|
|
80
|
-
|
|
81
|
-
{ name: 'Copiar', text: 'Haz clic en el botón de copiar para llevar la excusa a tu portapapeles.' }
|
|
82
|
-
],
|
|
83
|
-
schemas: []
|
|
124
|
+
howTo,
|
|
125
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
84
126
|
};
|
|
@@ -1,9 +1,63 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
1
2
|
import type { ExcuseGeneratorLocaleContent } from '../index';
|
|
2
3
|
|
|
4
|
+
const slug = 'generateur-d-excuses';
|
|
5
|
+
const title = 'Générateur d\'Excuses';
|
|
6
|
+
const description = 'Une machine à sous sémantique pour vous débarrasser de vos engagements avec style. Générez des excuses surréalistes et irréfutables instantanément.';
|
|
7
|
+
|
|
8
|
+
const faq: ExcuseGeneratorLocaleContent['faq'] = [
|
|
9
|
+
{
|
|
10
|
+
question: 'Ce générateur peut-il sauver mon mariage ?',
|
|
11
|
+
answer: 'Bien que nous ne soyons pas thérapeutes, éviter ce dîner chez les beaux-parents grâce à une urgence technique plausible peut considérablement réduire les tensions. À utiliser avec parcimonie.'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
question: 'Pourquoi des phrases aussi surréalistes ?',
|
|
15
|
+
answer: 'La stratégie repose sur la Dissonance Cognitive. Si vous dites quelque chose d\'ennuyeux, c\'est vérifiable. Si vous dites quelque chose d\'absurde, la surprise paralyse la capacité de colère.'
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const howTo: ExcuseGeneratorLocaleContent['howTo'] = [
|
|
20
|
+
{ name: 'Générer', text: 'Cliquez sur le bouton pour créer une nouvelle excuse.' },
|
|
21
|
+
{ name: 'Copier', text: 'Cliquez sur le bouton de copie pour mettre l\'excuse dans votre presse-papiers.' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
25
|
+
'@context': 'https://schema.org',
|
|
26
|
+
'@type': 'FAQPage',
|
|
27
|
+
mainEntity: faq.map((item) => ({
|
|
28
|
+
'@type': 'Question',
|
|
29
|
+
name: item.question,
|
|
30
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const howToSchema: WithContext<HowTo> = {
|
|
35
|
+
'@context': 'https://schema.org',
|
|
36
|
+
'@type': 'HowTo',
|
|
37
|
+
name: title,
|
|
38
|
+
description,
|
|
39
|
+
step: howTo.map((step) => ({
|
|
40
|
+
'@type': 'HowToStep',
|
|
41
|
+
name: step.name,
|
|
42
|
+
text: step.text,
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
47
|
+
'@context': 'https://schema.org',
|
|
48
|
+
'@type': 'SoftwareApplication',
|
|
49
|
+
name: title,
|
|
50
|
+
description,
|
|
51
|
+
applicationCategory: 'UtilitiesApplication',
|
|
52
|
+
operatingSystem: 'Web',
|
|
53
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
54
|
+
inLanguage: 'fr',
|
|
55
|
+
};
|
|
56
|
+
|
|
3
57
|
export const content: ExcuseGeneratorLocaleContent = {
|
|
4
|
-
slug
|
|
5
|
-
title
|
|
6
|
-
description
|
|
58
|
+
slug,
|
|
59
|
+
title,
|
|
60
|
+
description,
|
|
7
61
|
faqTitle: 'Questions Fréquemment Posées',
|
|
8
62
|
bibliographyTitle: 'Bibliographie du Temps Libre',
|
|
9
63
|
ui: {
|
|
@@ -59,22 +113,10 @@ export const content: ExcuseGeneratorLocaleContent = {
|
|
|
59
113
|
{ pro: 'Le ton créatif et humoristique désamorce la tension', con: 'Inapproprié dans un contexte formel ou professionnel' },
|
|
60
114
|
]},
|
|
61
115
|
],
|
|
62
|
-
faq
|
|
63
|
-
{
|
|
64
|
-
question: 'Ce générateur peut-il sauver mon mariage ?',
|
|
65
|
-
answer: 'Bien que nous ne soyons pas thérapeutes, éviter ce dîner chez les beaux-parents grâce à une urgence technique plausible peut considérablement réduire les tensions. À utiliser avec parcimonie.'
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
question: 'Pourquoi des phrases aussi surréalistes ?',
|
|
69
|
-
answer: 'La stratégie repose sur la Dissonance Cognitive. Si vous dites quelque chose d\'ennuyeux, c\'est vérifiable. Si vous dites quelque chose d\'absurde, la surprise paralyse la capacité de colère.'
|
|
70
|
-
}
|
|
71
|
-
],
|
|
116
|
+
faq,
|
|
72
117
|
bibliography: [
|
|
73
118
|
{ name: 'Manifeste du Procrastinateur', url: 'https://example.com/manifesto' }
|
|
74
119
|
],
|
|
75
|
-
howTo
|
|
76
|
-
|
|
77
|
-
{ name: 'Copier', text: 'Cliquez sur le bouton de copie pour mettre l\'excuse dans votre presse-papiers.' }
|
|
78
|
-
],
|
|
79
|
-
schemas: []
|
|
120
|
+
howTo,
|
|
121
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
80
122
|
};
|
|
@@ -470,25 +470,35 @@ const ASSETS = {
|
|
|
470
470
|
top: 50%;
|
|
471
471
|
left: 50%;
|
|
472
472
|
transform: translate(-50%, -50%) scale(0.5);
|
|
473
|
-
width:
|
|
474
|
-
max-width:
|
|
473
|
+
width: 85%;
|
|
474
|
+
max-width: 320px;
|
|
475
|
+
background-color: #fff;
|
|
476
|
+
border-radius: 2px;
|
|
477
|
+
box-shadow:
|
|
478
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.2),
|
|
479
|
+
0 4px 6px -2px rgba(0, 0, 0, 0.1),
|
|
480
|
+
inset 0 0 20px rgba(0, 0, 0, 0.05);
|
|
475
481
|
opacity: 0;
|
|
476
482
|
transition-property: all;
|
|
477
|
-
transition-timing-function: cubic-bezier(0.
|
|
478
|
-
transition-duration:
|
|
483
|
+
transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
484
|
+
transition-duration: 800ms;
|
|
479
485
|
z-index: 0;
|
|
486
|
+
overflow: hidden;
|
|
480
487
|
}
|
|
481
488
|
|
|
482
489
|
.fortune-cookie-paper.visible {
|
|
483
490
|
opacity: 1;
|
|
484
|
-
transform: translate(-50%, -50%) scale(1);
|
|
491
|
+
transform: translate(-50%, -50%) scale(1) rotate(-1deg);
|
|
485
492
|
z-index: 20;
|
|
486
493
|
}
|
|
487
494
|
|
|
488
495
|
.fortune-cookie-paper-img {
|
|
489
496
|
width: 100%;
|
|
490
|
-
|
|
491
|
-
|
|
497
|
+
height: auto;
|
|
498
|
+
display: block;
|
|
499
|
+
opacity: 0.15;
|
|
500
|
+
pointer-events: none;
|
|
501
|
+
mix-blend-mode: multiply;
|
|
492
502
|
}
|
|
493
503
|
|
|
494
504
|
.fortune-cookie-paper-content {
|
|
@@ -498,23 +508,24 @@ const ASSETS = {
|
|
|
498
508
|
flex-direction: column;
|
|
499
509
|
align-items: center;
|
|
500
510
|
justify-content: center;
|
|
501
|
-
padding:
|
|
511
|
+
padding: 1.5rem;
|
|
502
512
|
text-align: center;
|
|
513
|
+
z-index: 10;
|
|
503
514
|
}
|
|
504
515
|
|
|
505
516
|
.fortune-cookie-text {
|
|
506
|
-
color: #
|
|
507
|
-
font-weight:
|
|
517
|
+
color: #1e293b;
|
|
518
|
+
font-weight: 800;
|
|
508
519
|
font-size: 1.125rem;
|
|
509
|
-
line-height: 1.
|
|
520
|
+
line-height: 1.4;
|
|
510
521
|
transform: rotate(-1deg);
|
|
511
522
|
user-select: text;
|
|
523
|
+
margin: 0;
|
|
512
524
|
}
|
|
513
525
|
|
|
514
526
|
@media (min-width: 768px) {
|
|
515
527
|
.fortune-cookie-text {
|
|
516
528
|
font-size: 1.25rem;
|
|
517
|
-
line-height: 1.75rem;
|
|
518
529
|
}
|
|
519
530
|
}
|
|
520
531
|
|
|
@@ -527,12 +538,12 @@ const ASSETS = {
|
|
|
527
538
|
transform: rotate(-1deg);
|
|
528
539
|
}
|
|
529
540
|
|
|
530
|
-
.fortune-cookie-number {
|
|
541
|
+
:global(.fortune-cookie-number) {
|
|
531
542
|
font-size: 0.75rem;
|
|
532
543
|
line-height: 1rem;
|
|
533
544
|
font-weight: 700;
|
|
534
|
-
background-color:
|
|
535
|
-
color: #
|
|
545
|
+
background-color: #f1f5f9;
|
|
546
|
+
color: #dc2626;
|
|
536
547
|
padding-left: 0.5rem;
|
|
537
548
|
padding-right: 0.5rem;
|
|
538
549
|
padding-top: 0.125rem;
|
|
@@ -621,7 +632,7 @@ const ASSETS = {
|
|
|
621
632
|
40%, 60% { transform: translate3d(4px, 0, 0) rotate(4deg); }
|
|
622
633
|
}
|
|
623
634
|
|
|
624
|
-
.fortune-cookie-crumb {
|
|
635
|
+
:global(.fortune-cookie-crumb) {
|
|
625
636
|
position: absolute;
|
|
626
637
|
width: 20px;
|
|
627
638
|
height: 20px;
|
|
@@ -1,9 +1,63 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
1
2
|
import type { FortuneCookieLocaleContent } from '../index';
|
|
2
3
|
|
|
4
|
+
const slug = 'fortune-cookie';
|
|
5
|
+
const title = 'Fortune Cookie';
|
|
6
|
+
const description = 'Check your daily destiny and discover your lucky numbers. One fortune per day, revealed with a click.';
|
|
7
|
+
|
|
8
|
+
const faq: FortuneCookieLocaleContent['faq'] = [
|
|
9
|
+
{
|
|
10
|
+
question: 'Can I open more than one cookie per day?',
|
|
11
|
+
answer: 'Destiny only speaks once a day. We save your fortune on the device so it guides you throughout the day.'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
question: 'Are the fortunes randomly generated?',
|
|
15
|
+
answer: 'Yes — a random fortune is selected each day and saved locally. Each of the 25 fortunes has an equal chance of being chosen, ensuring variety over time.'
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const howTo: FortuneCookieLocaleContent['howTo'] = [
|
|
20
|
+
{ name: 'Break the cookie', text: 'Click repeatedly on the cookie to crack it open.' },
|
|
21
|
+
{ name: 'Read your fortune', text: 'Discover the hidden message inside and your lucky numbers for the day.' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
25
|
+
'@context': 'https://schema.org',
|
|
26
|
+
'@type': 'FAQPage',
|
|
27
|
+
mainEntity: faq.map((item) => ({
|
|
28
|
+
'@type': 'Question',
|
|
29
|
+
name: item.question,
|
|
30
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const howToSchema: WithContext<HowTo> = {
|
|
35
|
+
'@context': 'https://schema.org',
|
|
36
|
+
'@type': 'HowTo',
|
|
37
|
+
name: title,
|
|
38
|
+
description,
|
|
39
|
+
step: howTo.map((step) => ({
|
|
40
|
+
'@type': 'HowToStep',
|
|
41
|
+
name: step.name,
|
|
42
|
+
text: step.text,
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
47
|
+
'@context': 'https://schema.org',
|
|
48
|
+
'@type': 'SoftwareApplication',
|
|
49
|
+
name: title,
|
|
50
|
+
description,
|
|
51
|
+
applicationCategory: 'UtilitiesApplication',
|
|
52
|
+
operatingSystem: 'Web',
|
|
53
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
54
|
+
inLanguage: 'en',
|
|
55
|
+
};
|
|
56
|
+
|
|
3
57
|
export const content: FortuneCookieLocaleContent = {
|
|
4
|
-
slug
|
|
5
|
-
title
|
|
6
|
-
description
|
|
58
|
+
slug,
|
|
59
|
+
title,
|
|
60
|
+
description,
|
|
7
61
|
faqTitle: 'Frequently Asked Questions',
|
|
8
62
|
bibliographyTitle: 'Destiny Bibliography',
|
|
9
63
|
ui: {
|
|
@@ -64,22 +118,10 @@ export const content: FortuneCookieLocaleContent = {
|
|
|
64
118
|
{ value: '1/day', label: 'One destiny per day', icon: 'mdi:calendar-today' },
|
|
65
119
|
], columns: 4 },
|
|
66
120
|
],
|
|
67
|
-
faq
|
|
68
|
-
{
|
|
69
|
-
question: 'Can I open more than one cookie per day?',
|
|
70
|
-
answer: 'Destiny only speaks once a day. We save your fortune on the device so it guides you throughout the day.'
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
question: 'Are the fortunes randomly generated?',
|
|
74
|
-
answer: 'Yes — a random fortune is selected each day and saved locally. Each of the 25 fortunes has an equal chance of being chosen, ensuring variety over time.'
|
|
75
|
-
}
|
|
76
|
-
],
|
|
121
|
+
faq,
|
|
77
122
|
bibliography: [
|
|
78
123
|
{ name: 'History of the Fortune Cookie', url: 'https://en.wikipedia.org/wiki/Fortune_cookie' }
|
|
79
124
|
],
|
|
80
|
-
howTo
|
|
81
|
-
|
|
82
|
-
{ name: 'Read your fortune', text: 'Discover the hidden message inside and your lucky numbers for the day.' }
|
|
83
|
-
],
|
|
84
|
-
schemas: []
|
|
125
|
+
howTo,
|
|
126
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
85
127
|
};
|