@jjlmoya/utils-tools 1.1.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 +63 -0
- package/src/category/i18n/en.ts +172 -0
- package/src/category/i18n/es.ts +172 -0
- package/src/category/i18n/fr.ts +172 -0
- package/src/category/index.ts +23 -0
- package/src/category/seo.astro +15 -0
- package/src/components/PreviewNavSidebar.astro +116 -0
- package/src/components/PreviewToolbar.astro +143 -0
- package/src/data.ts +11 -0
- package/src/env.d.ts +5 -0
- package/src/index.ts +90 -0
- package/src/layouts/PreviewLayout.astro +117 -0
- package/src/pages/[locale]/[slug].astro +146 -0
- package/src/pages/[locale].astro +251 -0
- package/src/pages/index.astro +4 -0
- package/src/tests/faq_count.test.ts +19 -0
- package/src/tests/locale_completeness.test.ts +42 -0
- package/src/tests/mocks/astro_mock.js +2 -0
- package/src/tests/no_h1_in_components.test.ts +48 -0
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/seo_length.test.ts +23 -0
- package/src/tests/title_quality.test.ts +56 -0
- package/src/tests/tool_validation.test.ts +17 -0
- package/src/tool/date-diff-calculator/bibliography.astro +14 -0
- package/src/tool/date-diff-calculator/component.astro +370 -0
- package/src/tool/date-diff-calculator/i18n/en.ts +132 -0
- package/src/tool/date-diff-calculator/i18n/es.ts +132 -0
- package/src/tool/date-diff-calculator/i18n/fr.ts +132 -0
- package/src/tool/date-diff-calculator/index.ts +22 -0
- package/src/tool/date-diff-calculator/seo.astro +14 -0
- package/src/tool/date-diff-calculator/ui.ts +17 -0
- package/src/tool/drive-direct-link/bibliography.astro +14 -0
- package/src/tool/drive-direct-link/component.astro +280 -0
- package/src/tool/drive-direct-link/i18n/en.ts +118 -0
- package/src/tool/drive-direct-link/i18n/es.ts +118 -0
- package/src/tool/drive-direct-link/i18n/fr.ts +118 -0
- package/src/tool/drive-direct-link/index.ts +22 -0
- package/src/tool/drive-direct-link/seo.astro +14 -0
- package/src/tool/drive-direct-link/ui.ts +10 -0
- package/src/tool/email-list-cleaner/bibliography.astro +14 -0
- package/src/tool/email-list-cleaner/component.astro +375 -0
- package/src/tool/email-list-cleaner/i18n/en.ts +140 -0
- package/src/tool/email-list-cleaner/i18n/es.ts +140 -0
- package/src/tool/email-list-cleaner/i18n/fr.ts +140 -0
- package/src/tool/email-list-cleaner/index.ts +22 -0
- package/src/tool/email-list-cleaner/seo.astro +14 -0
- package/src/tool/email-list-cleaner/ui.ts +15 -0
- package/src/tool/env-badge-spain/bibliography.astro +14 -0
- package/src/tool/env-badge-spain/component.astro +303 -0
- package/src/tool/env-badge-spain/components/BadgeForm.astro +243 -0
- package/src/tool/env-badge-spain/components/BadgeResult.astro +151 -0
- package/src/tool/env-badge-spain/i18n/en.ts +153 -0
- package/src/tool/env-badge-spain/i18n/es.ts +153 -0
- package/src/tool/env-badge-spain/i18n/fr.ts +153 -0
- package/src/tool/env-badge-spain/index.ts +22 -0
- package/src/tool/env-badge-spain/seo.astro +14 -0
- package/src/tool/env-badge-spain/ui.ts +53 -0
- package/src/tool/morse-beacon/bibliography.astro +14 -0
- package/src/tool/morse-beacon/component.astro +534 -0
- package/src/tool/morse-beacon/i18n/en.ts +157 -0
- package/src/tool/morse-beacon/i18n/es.ts +157 -0
- package/src/tool/morse-beacon/i18n/fr.ts +157 -0
- package/src/tool/morse-beacon/index.ts +22 -0
- package/src/tool/morse-beacon/logic/MorseEngine.ts +124 -0
- package/src/tool/morse-beacon/seo.astro +14 -0
- package/src/tool/morse-beacon/ui.ts +18 -0
- package/src/tool/password-generator/bibliography.astro +14 -0
- package/src/tool/password-generator/component.astro +259 -0
- package/src/tool/password-generator/components/Config.astro +227 -0
- package/src/tool/password-generator/components/Display.astro +147 -0
- package/src/tool/password-generator/components/Strength.astro +70 -0
- package/src/tool/password-generator/i18n/en.ts +166 -0
- package/src/tool/password-generator/i18n/es.ts +166 -0
- package/src/tool/password-generator/i18n/fr.ts +166 -0
- package/src/tool/password-generator/index.ts +22 -0
- package/src/tool/password-generator/seo.astro +14 -0
- package/src/tool/password-generator/ui.ts +16 -0
- package/src/tool/routes/bibliography.astro +14 -0
- package/src/tool/routes/component.astro +543 -0
- package/src/tool/routes/i18n/en.ts +157 -0
- package/src/tool/routes/i18n/es.ts +157 -0
- package/src/tool/routes/i18n/fr.ts +157 -0
- package/src/tool/routes/index.ts +22 -0
- package/src/tool/routes/logic/GeocodingService.ts +60 -0
- package/src/tool/routes/logic/RouteManager.ts +192 -0
- package/src/tool/routes/logic/RouteService.ts +66 -0
- package/src/tool/routes/seo.astro +14 -0
- package/src/tool/routes/ui.ts +16 -0
- package/src/tool/rule-of-three/bibliography.astro +14 -0
- package/src/tool/rule-of-three/component.astro +369 -0
- package/src/tool/rule-of-three/i18n/en.ts +171 -0
- package/src/tool/rule-of-three/i18n/es.ts +171 -0
- package/src/tool/rule-of-three/i18n/fr.ts +171 -0
- package/src/tool/rule-of-three/index.ts +22 -0
- package/src/tool/rule-of-three/seo.astro +14 -0
- package/src/tool/rule-of-three/ui.ts +13 -0
- package/src/tool/seo-content-optimizer/bibliography.astro +14 -0
- package/src/tool/seo-content-optimizer/component.astro +552 -0
- package/src/tool/seo-content-optimizer/i18n/en.ts +136 -0
- package/src/tool/seo-content-optimizer/i18n/es.ts +136 -0
- package/src/tool/seo-content-optimizer/i18n/fr.ts +136 -0
- package/src/tool/seo-content-optimizer/index.ts +22 -0
- package/src/tool/seo-content-optimizer/seo.astro +14 -0
- package/src/tool/seo-content-optimizer/ui.ts +29 -0
- package/src/tool/speed-reader/bibliography.astro +14 -0
- package/src/tool/speed-reader/component.astro +586 -0
- package/src/tool/speed-reader/i18n/en.ts +152 -0
- package/src/tool/speed-reader/i18n/es.ts +152 -0
- package/src/tool/speed-reader/i18n/fr.ts +152 -0
- package/src/tool/speed-reader/index.ts +22 -0
- package/src/tool/speed-reader/logic/RSVPEngine.ts +106 -0
- package/src/tool/speed-reader/seo.astro +14 -0
- package/src/tool/speed-reader/ui.ts +14 -0
- package/src/tool/text-pixel-calculator/bibliography.astro +14 -0
- package/src/tool/text-pixel-calculator/component.astro +315 -0
- package/src/tool/text-pixel-calculator/components/Editor.astro +240 -0
- package/src/tool/text-pixel-calculator/components/Preview.astro +155 -0
- package/src/tool/text-pixel-calculator/components/Stats.astro +87 -0
- package/src/tool/text-pixel-calculator/i18n/en.ts +133 -0
- package/src/tool/text-pixel-calculator/i18n/es.ts +133 -0
- package/src/tool/text-pixel-calculator/i18n/fr.ts +133 -0
- package/src/tool/text-pixel-calculator/index.ts +22 -0
- package/src/tool/text-pixel-calculator/seo.astro +14 -0
- package/src/tool/text-pixel-calculator/ui.ts +15 -0
- package/src/tool/whatsapp-link/bibliography.astro +14 -0
- package/src/tool/whatsapp-link/component.astro +455 -0
- package/src/tool/whatsapp-link/i18n/en.ts +128 -0
- package/src/tool/whatsapp-link/i18n/es.ts +128 -0
- package/src/tool/whatsapp-link/i18n/fr.ts +128 -0
- package/src/tool/whatsapp-link/index.ts +22 -0
- package/src/tool/whatsapp-link/seo.astro +14 -0
- package/src/tool/whatsapp-link/ui.ts +15 -0
- package/src/tools.ts +15 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
2
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
3
|
+
import type { SeoContentOptimizerUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const faqData = [
|
|
6
|
+
{
|
|
7
|
+
question: '¿Cómo ayuda esta herramienta a mi posicionamiento SEO?',
|
|
8
|
+
answer: 'Al analizar la densidad de keywords y la legibilidad de las frases, aseguras que tu contenido sea fácil de entender para los usuarios y relevante para los buscadores, evitando penalizaciones por sobreoptimización.',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
question: '¿Qué aspectos técnicos del HTML analiza?',
|
|
12
|
+
answer: 'Verifica la existencia y unicidad de la etiqueta H1, la presencia de subencabezados H2/H3 y los atributos alt en las imágenes.',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
question: '¿Mis textos se guardan en el servidor?',
|
|
16
|
+
answer: 'No. El análisis se realiza 100% de forma local en tu navegador. Tu contenido nunca sale de tu ordenador.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
question: '¿Es compatible con los criterios de Yoast SEO?',
|
|
20
|
+
answer: 'Sí, implementamos criterios similares: longitud de frases, distribución de párrafos y jerarquía de encabezados.',
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const howToData = [
|
|
25
|
+
{ name: 'Escribe o pega tu texto', text: 'Introduce el contenido que deseas analizar en el área de texto principal.' },
|
|
26
|
+
{ name: 'Revisa el checklist de optimización', text: 'Comprueba las alertas de longitud, legibilidad y densidad de keywords en el panel lateral.' },
|
|
27
|
+
{ name: 'Analiza el HTML técnico', text: 'Cambia a la pestaña de análisis técnico para verificar etiquetas H1, alts de imagen y estructura de metadatos.' },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
31
|
+
'@context': 'https://schema.org',
|
|
32
|
+
'@type': 'FAQPage',
|
|
33
|
+
mainEntity: faqData.map((item) => ({
|
|
34
|
+
'@type': 'Question',
|
|
35
|
+
name: item.question,
|
|
36
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
37
|
+
})),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const howToSchema: WithContext<HowTo> = {
|
|
41
|
+
'@context': 'https://schema.org',
|
|
42
|
+
'@type': 'HowTo',
|
|
43
|
+
name: 'Cómo optimizar contenido para SEO',
|
|
44
|
+
step: howToData.map((s) => ({ '@type': 'HowToStep', name: s.name, text: s.text })),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
48
|
+
'@context': 'https://schema.org',
|
|
49
|
+
'@type': 'SoftwareApplication',
|
|
50
|
+
name: 'Optimizador de Contenido SEO',
|
|
51
|
+
applicationCategory: 'UtilitiesApplication',
|
|
52
|
+
operatingSystem: 'Web',
|
|
53
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
54
|
+
description: 'Analiza la densidad de palabras clave, legibilidad y estructura técnica HTML de tus textos en tiempo real, sin enviar datos a ningún servidor.',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const ui: SeoContentOptimizerUI = {
|
|
58
|
+
tabText: 'Análisis de Texto',
|
|
59
|
+
tabHtml: 'Análisis HTML Técnico',
|
|
60
|
+
textareaPlaceholder: 'Escribe tu texto o pega tu código HTML aquí...',
|
|
61
|
+
statsChars: 'Caracteres',
|
|
62
|
+
statsWords: 'Palabras',
|
|
63
|
+
statsReading: 'Lectura',
|
|
64
|
+
statsSentences: 'Frases',
|
|
65
|
+
checklistTitle: 'Checklist de Optimización',
|
|
66
|
+
keywordsTitle: 'Densidad de Keywords',
|
|
67
|
+
technicalTitle: 'Análisis Técnico HTML',
|
|
68
|
+
h1Label: 'H1 Detectados',
|
|
69
|
+
linksLabel: 'Enlaces (a)',
|
|
70
|
+
imgsLabel: 'Imágenes (img)',
|
|
71
|
+
altsLabel: 'Alts faltantes',
|
|
72
|
+
emptyState: 'Sin datos',
|
|
73
|
+
analyzing: 'Analizando...',
|
|
74
|
+
checkInsufficient: 'Longitud insuficiente (< 300 pal.)',
|
|
75
|
+
checkPillar: 'Contenido pilar excelente (> 900 pal.)',
|
|
76
|
+
checkGoodLength: 'Longitud buena para SEO',
|
|
77
|
+
checkLongSentences: 'Demasiadas frases largas (> 25% del texto)',
|
|
78
|
+
checkGoodReadability: 'Legibilidad de frases óptima',
|
|
79
|
+
checkLongParagraphs: 'Divide párrafos muy largos (> 150 pal.)',
|
|
80
|
+
checkMissingH1: 'Falta etiqueta H1',
|
|
81
|
+
checkMultipleH1: 'Múltiples H1 detectados',
|
|
82
|
+
checkMissingH2: 'Faltan subencabezados (H2)',
|
|
83
|
+
checkMissingTitle: 'Falta etiqueta de título meta',
|
|
84
|
+
stopWords: JSON.stringify(['el', 'la', 'los', 'las', 'un', 'una', 'unos', 'unas', 'y', 'o', 'u', 'en', 'de', 'del', 'por', 'para', 'con', 'sin', 'sobre', 'que', 'si', 'no', 'es', 'son', 'fue', 'era', 'esta', 'esto', 'estos', 'estas', 'a', 'ante', 'bajo', 'contra', 'desde', 'durante', 'entre', 'hacia', 'hasta', 'mediante', 'tras']),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const content: ToolLocaleContent<SeoContentOptimizerUI> = {
|
|
88
|
+
slug: 'optimizador-contenido-seo',
|
|
89
|
+
title: 'Optimizador de Contenido SEO',
|
|
90
|
+
description: 'Analiza la densidad de palabras clave, legibilidad y estructura técnica HTML de tus textos en tiempo real. Herramienta SEO privada y gratuita.',
|
|
91
|
+
ui,
|
|
92
|
+
faqTitle: 'Preguntas Frecuentes',
|
|
93
|
+
faq: faqData,
|
|
94
|
+
howTo: howToData,
|
|
95
|
+
bibliographyTitle: 'Referencias',
|
|
96
|
+
bibliography: [
|
|
97
|
+
{ name: 'Guía de inicio de SEO de Google', url: 'https://developers.google.com/search/docs/fundamentals/seo-starter-guide' },
|
|
98
|
+
{ name: 'Criterios de legibilidad Yoast SEO', url: 'https://yoast.com/what-is-readability/' },
|
|
99
|
+
],
|
|
100
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
101
|
+
seo: [
|
|
102
|
+
{ type: 'title', level: 2, text: 'Optimizador de Contenido SEO: Keywords, Legibilidad y Estructura' },
|
|
103
|
+
{
|
|
104
|
+
type: 'paragraph',
|
|
105
|
+
html: 'La calidad del contenido ya no se mide solo por las palabras clave que incluyes, sino por cómo estructuras tu información para que sea digerible tanto para humanos como para los rastreadores de Google. Nuestra herramienta de <strong>análisis SEO en tiempo real</strong> te ofrece control total sobre la densidad de keywords, la legibilidad de tus párrafos y los elementos técnicos fundamentales del HTML.',
|
|
106
|
+
},
|
|
107
|
+
{ type: 'title', level: 3, text: 'Densidad de Keywords y Relevancia Semántica' },
|
|
108
|
+
{
|
|
109
|
+
type: 'paragraph',
|
|
110
|
+
html: 'La <strong>densidad de palabras clave</strong> indica con qué frecuencia aparece un término en comparación con el resto del texto. Un exceso activa los filtros de <em>keyword stuffing</em>, mientras que una densidad muy baja dificulta que los buscadores identifiquen el tema central de tu artículo.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'list',
|
|
114
|
+
items: [
|
|
115
|
+
'<strong>Análisis de relevancia:</strong> Identifica si las palabras más repetidas coinciden con tu intención de búsqueda.',
|
|
116
|
+
'<strong>Prevención de penalizaciones:</strong> Evita repetir excesivamente términos que puedan dar imagen de spam.',
|
|
117
|
+
'<strong>Optimización semántica:</strong> Ayuda a encontrar equilibrio entre términos técnicos y lenguaje natural.',
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
{ type: 'title', level: 3, text: 'Legibilidad al Estilo Yoast' },
|
|
121
|
+
{
|
|
122
|
+
type: 'paragraph',
|
|
123
|
+
html: 'La legibilidad es un factor de ranking indirecto pero crucial. Si un usuario abandona la página porque los párrafos son bloques interminables, tu <em>Dwell Time</em> bajará. El analizador detecta frases largas (más de 20 palabras), párrafos de más de 150 palabras y la presencia de subencabezados.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'tip',
|
|
127
|
+
title: 'Tiempo de lectura',
|
|
128
|
+
html: 'La mayoría de los usuarios decide si leer un artículo en menos de 10 segundos. Conocer el tiempo estimado de lectura (calculado sobre una media de 200 palabras por minuto) ayuda a reducir la tasa de rebote ajustando las expectativas del lector.',
|
|
129
|
+
},
|
|
130
|
+
{ type: 'title', level: 3, text: 'Análisis Técnico HTML' },
|
|
131
|
+
{
|
|
132
|
+
type: 'paragraph',
|
|
133
|
+
html: 'Pega tu código fuente para verificar elementos clave: unicidad del <strong>H1</strong>, presencia de subencabezados H2/H3, imágenes sin atributo <code>alt</code> y existencia de la etiqueta <code>title</code>. Todo el procesamiento ocurre en tu navegador sin enviar datos a ningún servidor.',
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
2
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
3
|
+
import type { SeoContentOptimizerUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const faqData = [
|
|
6
|
+
{
|
|
7
|
+
question: 'Comment cet outil améliore-t-il mon référencement SEO ?',
|
|
8
|
+
answer: 'En analysant la densité des mots-clés et la lisibilité des phrases, vous vous assurez que votre contenu est compréhensible pour les utilisateurs et pertinent pour les moteurs de recherche, en évitant les pénalités de sur-optimisation.',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
question: "Quels éléments HTML l'analyse technique vérifie-t-elle ?",
|
|
12
|
+
answer: "Elle vérifie l'existence et l'unicité de la balise H1, la présence de sous-titres H2/H3 et les attributs alt sur les images.",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
question: 'Mon contenu est-il stocké sur un serveur ?',
|
|
16
|
+
answer: "Non. L'analyse s'effectue à 100 % localement dans votre navigateur. Votre contenu ne quitte jamais votre ordinateur.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
question: 'Est-il compatible avec les critères Yoast SEO ?',
|
|
20
|
+
answer: "Oui, nous appliquons des critères similaires à Yoast : longueur des phrases, distribution des paragraphes et hiérarchie des titres.",
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const howToData = [
|
|
25
|
+
{ name: 'Écrivez ou collez votre texte', text: 'Entrez le contenu que vous souhaitez analyser dans la zone de texte principale.' },
|
|
26
|
+
{ name: "Consultez la checklist d'optimisation", text: 'Vérifiez les alertes de longueur, de lisibilité et de densité de mots-clés dans le panneau latéral.' },
|
|
27
|
+
{ name: 'Analysez le HTML technique', text: "Passez à l'onglet d'analyse technique pour vérifier les balises H1, les alts d'images et la structure des métadonnées." },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
31
|
+
'@context': 'https://schema.org',
|
|
32
|
+
'@type': 'FAQPage',
|
|
33
|
+
mainEntity: faqData.map((item) => ({
|
|
34
|
+
'@type': 'Question',
|
|
35
|
+
name: item.question,
|
|
36
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
37
|
+
})),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const howToSchema: WithContext<HowTo> = {
|
|
41
|
+
'@context': 'https://schema.org',
|
|
42
|
+
'@type': 'HowTo',
|
|
43
|
+
name: 'Comment optimiser le contenu pour le SEO',
|
|
44
|
+
step: howToData.map((s) => ({ '@type': 'HowToStep', name: s.name, text: s.text })),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
48
|
+
'@context': 'https://schema.org',
|
|
49
|
+
'@type': 'SoftwareApplication',
|
|
50
|
+
name: 'Optimiseur de Contenu SEO',
|
|
51
|
+
applicationCategory: 'UtilitiesApplication',
|
|
52
|
+
operatingSystem: 'Web',
|
|
53
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
54
|
+
description: "Analysez la densité des mots-clés, la lisibilité et la structure HTML technique de vos textes en temps réel, sans envoyer de données à un serveur.",
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const ui: SeoContentOptimizerUI = {
|
|
58
|
+
tabText: 'Analyse de Texte',
|
|
59
|
+
tabHtml: 'Analyse HTML Technique',
|
|
60
|
+
textareaPlaceholder: 'Écrivez votre texte ou collez votre code HTML ici...',
|
|
61
|
+
statsChars: 'Caractères',
|
|
62
|
+
statsWords: 'Mots',
|
|
63
|
+
statsReading: 'Lecture',
|
|
64
|
+
statsSentences: 'Phrases',
|
|
65
|
+
checklistTitle: "Checklist d'Optimisation",
|
|
66
|
+
keywordsTitle: 'Densité de Mots-Clés',
|
|
67
|
+
technicalTitle: 'Analyse HTML Technique',
|
|
68
|
+
h1Label: 'H1 Détectés',
|
|
69
|
+
linksLabel: 'Liens (a)',
|
|
70
|
+
imgsLabel: 'Images (img)',
|
|
71
|
+
altsLabel: 'Alts manquants',
|
|
72
|
+
emptyState: 'Aucune donnée',
|
|
73
|
+
analyzing: 'Analyse...',
|
|
74
|
+
checkInsufficient: 'Longueur insuffisante (< 300 mots)',
|
|
75
|
+
checkPillar: 'Excellent contenu pilier (> 900 mots)',
|
|
76
|
+
checkGoodLength: 'Bonne longueur pour le SEO',
|
|
77
|
+
checkLongSentences: 'Trop de phrases longues (> 25 % du texte)',
|
|
78
|
+
checkGoodReadability: 'Lisibilité des phrases optimale',
|
|
79
|
+
checkLongParagraphs: 'Divisez les paragraphes trop longs (> 150 mots)',
|
|
80
|
+
checkMissingH1: 'Balise H1 manquante',
|
|
81
|
+
checkMultipleH1: 'Plusieurs balises H1 détectées',
|
|
82
|
+
checkMissingH2: 'Sous-titres (H2) manquants',
|
|
83
|
+
checkMissingTitle: 'Balise title méta manquante',
|
|
84
|
+
stopWords: JSON.stringify(['le', 'la', 'les', 'un', 'une', 'des', 'et', 'ou', 'mais', 'en', 'de', 'du', 'au', 'aux', 'par', 'pour', 'avec', 'sans', 'sur', 'que', 'qui', 'si', 'non', 'est', 'sont', 'ce', 'cet', 'cette', 'ces', 'il', 'elle', 'ils', 'elles', 'nous', 'vous', 'je', 'me', 'tu', 'se', 'y', 'dont', 'pas', 'plus', 'ne']),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const content: ToolLocaleContent<SeoContentOptimizerUI> = {
|
|
88
|
+
slug: 'optimiseur-contenu-seo',
|
|
89
|
+
title: 'Optimiseur de Contenu SEO',
|
|
90
|
+
description: "Analysez la densité des mots-clés, la lisibilité et la structure HTML technique de vos textes en temps réel. Outil SEO gratuit et privé.",
|
|
91
|
+
ui,
|
|
92
|
+
faqTitle: 'Questions Fréquentes',
|
|
93
|
+
faq: faqData,
|
|
94
|
+
howTo: howToData,
|
|
95
|
+
bibliographyTitle: 'Références',
|
|
96
|
+
bibliography: [
|
|
97
|
+
{ name: 'Guide de démarrage SEO de Google', url: 'https://developers.google.com/search/docs/fundamentals/seo-starter-guide' },
|
|
98
|
+
{ name: 'Critères de lisibilité Yoast SEO', url: 'https://yoast.com/what-is-readability/' },
|
|
99
|
+
],
|
|
100
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
101
|
+
seo: [
|
|
102
|
+
{ type: 'title', level: 2, text: 'Optimiseur de Contenu SEO : Mots-Clés, Lisibilité et Structure' },
|
|
103
|
+
{
|
|
104
|
+
type: 'paragraph',
|
|
105
|
+
html: "La qualité du contenu ne se mesure plus seulement aux mots-clés inclus, mais à la façon dont vous structurez l'information pour qu'elle soit compréhensible à la fois par les humains et les robots de Google. Notre outil d'<strong>analyse SEO en temps réel</strong> vous offre un contrôle total sur la densité des mots-clés, la lisibilité des paragraphes et les éléments techniques HTML fondamentaux.",
|
|
106
|
+
},
|
|
107
|
+
{ type: 'title', level: 3, text: 'Densité de Mots-Clés et Pertinence Sémantique' },
|
|
108
|
+
{
|
|
109
|
+
type: 'paragraph',
|
|
110
|
+
html: 'La <strong>densité de mots-clés</strong> indique la fréquence d\'apparition d\'un terme par rapport au reste du texte. Un excès déclenche les filtres de <em>keyword stuffing</em>, tandis qu\'une densité trop faible peut rendre difficile l\'identification du sujet principal de votre article par les moteurs de recherche.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'list',
|
|
114
|
+
items: [
|
|
115
|
+
'<strong>Analyse de pertinence :</strong> Identifiez si les mots les plus répétés correspondent à votre intention de recherche.',
|
|
116
|
+
'<strong>Prévention des pénalités :</strong> Évitez de répéter excessivement des termes qui pourraient paraître indésirables.',
|
|
117
|
+
"<strong>Optimisation sémantique :</strong> Trouvez l'équilibre entre termes techniques et langage naturel.",
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
{ type: 'title', level: 3, text: 'Lisibilité à la Manière Yoast' },
|
|
121
|
+
{
|
|
122
|
+
type: 'paragraph',
|
|
123
|
+
html: 'La lisibilité est un facteur de classement indirect mais crucial. Si les utilisateurs quittent la page parce que les paragraphes sont de longs blocs de texte, votre <em>Dwell Time</em> diminuera. L\'analyseur détecte les phrases longues (plus de 20 mots), les paragraphes de plus de 150 mots et vérifie la présence de sous-titres.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'tip',
|
|
127
|
+
title: 'Temps de lecture',
|
|
128
|
+
html: 'La plupart des utilisateurs décident de lire un article en moins de 10 secondes. Connaître le temps de lecture estimé (calculé sur une moyenne de 200 mots par minute) aide à réduire le taux de rebond en ajustant les attentes du lecteur.',
|
|
129
|
+
},
|
|
130
|
+
{ type: 'title', level: 3, text: 'Analyse HTML Technique' },
|
|
131
|
+
{
|
|
132
|
+
type: 'paragraph',
|
|
133
|
+
html: 'Collez votre code source pour vérifier les éléments clés : unicité du <strong>H1</strong>, présence de sous-titres H2/H3, images sans attribut <code>alt</code> et existence de la balise <code>title</code>. Tout le traitement se fait dans votre navigateur sans envoyer de données à un serveur.',
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ToolDefinition, ToolsToolEntry } from '../../types';
|
|
2
|
+
import type { SeoContentOptimizerUI } from './ui';
|
|
3
|
+
import SeoContentOptimizerComponent from './component.astro';
|
|
4
|
+
import SeoContentOptimizerSEO from './seo.astro';
|
|
5
|
+
import SeoContentOptimizerBibliography from './bibliography.astro';
|
|
6
|
+
|
|
7
|
+
export const seoContentOptimizer: ToolsToolEntry<SeoContentOptimizerUI> = {
|
|
8
|
+
id: 'seo-content-optimizer',
|
|
9
|
+
icons: { bg: 'mdi:file-search', fg: 'mdi:shield-check-outline' },
|
|
10
|
+
i18n: {
|
|
11
|
+
es: () => import('./i18n/es').then((m) => m.content),
|
|
12
|
+
en: () => import('./i18n/en').then((m) => m.content),
|
|
13
|
+
fr: () => import('./i18n/fr').then((m) => m.content),
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const SEO_CONTENT_OPTIMIZER_TOOL: ToolDefinition = {
|
|
18
|
+
entry: seoContentOptimizer,
|
|
19
|
+
Component: SeoContentOptimizerComponent,
|
|
20
|
+
SEOComponent: SeoContentOptimizerSEO,
|
|
21
|
+
BibliographyComponent: SeoContentOptimizerBibliography,
|
|
22
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { seoContentOptimizer } 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 seoContentOptimizer.i18n[locale]?.();
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{content && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface SeoContentOptimizerUI extends Record<string, string> {
|
|
2
|
+
tabText: string;
|
|
3
|
+
tabHtml: string;
|
|
4
|
+
textareaPlaceholder: string;
|
|
5
|
+
statsChars: string;
|
|
6
|
+
statsWords: string;
|
|
7
|
+
statsReading: string;
|
|
8
|
+
statsSentences: string;
|
|
9
|
+
checklistTitle: string;
|
|
10
|
+
keywordsTitle: string;
|
|
11
|
+
technicalTitle: string;
|
|
12
|
+
h1Label: string;
|
|
13
|
+
linksLabel: string;
|
|
14
|
+
imgsLabel: string;
|
|
15
|
+
altsLabel: string;
|
|
16
|
+
emptyState: string;
|
|
17
|
+
analyzing: string;
|
|
18
|
+
checkInsufficient: string;
|
|
19
|
+
checkPillar: string;
|
|
20
|
+
checkGoodLength: string;
|
|
21
|
+
checkLongSentences: string;
|
|
22
|
+
checkGoodReadability: string;
|
|
23
|
+
checkLongParagraphs: string;
|
|
24
|
+
checkMissingH1: string;
|
|
25
|
+
checkMultipleH1: string;
|
|
26
|
+
checkMissingH2: string;
|
|
27
|
+
checkMissingTitle: string;
|
|
28
|
+
stopWords: string;
|
|
29
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { speedReader } 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 speedReader.i18n[locale]?.();
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{content && <SharedBibliography links={content.bibliography} />}
|