@jjlmoya/utils-developer 1.2.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 +64 -0
- package/src/category/i18n/en.ts +34 -0
- package/src/category/i18n/es.ts +34 -0
- package/src/category/i18n/fr.ts +34 -0
- package/src/category/index.ts +31 -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 +78 -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/css_specificity_logic.test.ts +39 -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 +22 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tests/tool_validation.test.ts +17 -0
- package/src/tool/aspectRatio/bibliography.astro +14 -0
- package/src/tool/aspectRatio/component.astro +468 -0
- package/src/tool/aspectRatio/i18n/en.ts +177 -0
- package/src/tool/aspectRatio/i18n/es.ts +177 -0
- package/src/tool/aspectRatio/i18n/fr.ts +177 -0
- package/src/tool/aspectRatio/index.ts +34 -0
- package/src/tool/aspectRatio/seo.astro +14 -0
- package/src/tool/aspectRatio/ui.ts +12 -0
- package/src/tool/calculadoraTiempoDatos/bibliography.astro +14 -0
- package/src/tool/calculadoraTiempoDatos/component.astro +829 -0
- package/src/tool/calculadoraTiempoDatos/i18n/en.ts +150 -0
- package/src/tool/calculadoraTiempoDatos/i18n/es.ts +163 -0
- package/src/tool/calculadoraTiempoDatos/i18n/fr.ts +150 -0
- package/src/tool/calculadoraTiempoDatos/index.ts +33 -0
- package/src/tool/calculadoraTiempoDatos/seo.astro +14 -0
- package/src/tool/calculadoraTiempoDatos/ui.ts +24 -0
- package/src/tool/colorConverter/bibliography.astro +14 -0
- package/src/tool/colorConverter/component.astro +504 -0
- package/src/tool/colorConverter/i18n/en.ts +126 -0
- package/src/tool/colorConverter/i18n/es.ts +126 -0
- package/src/tool/colorConverter/i18n/fr.ts +126 -0
- package/src/tool/colorConverter/index.ts +33 -0
- package/src/tool/colorConverter/seo.astro +14 -0
- package/src/tool/colorConverter/ui.ts +16 -0
- package/src/tool/conversorExcelCsvHtml/bibliography.astro +14 -0
- package/src/tool/conversorExcelCsvHtml/component.astro +595 -0
- package/src/tool/conversorExcelCsvHtml/i18n/en.ts +129 -0
- package/src/tool/conversorExcelCsvHtml/i18n/es.ts +129 -0
- package/src/tool/conversorExcelCsvHtml/i18n/fr.ts +129 -0
- package/src/tool/conversorExcelCsvHtml/index.ts +33 -0
- package/src/tool/conversorExcelCsvHtml/seo.astro +14 -0
- package/src/tool/conversorExcelCsvHtml/ui.ts +14 -0
- package/src/tool/cronGenerator/bibliography.astro +14 -0
- package/src/tool/cronGenerator/component.astro +667 -0
- package/src/tool/cronGenerator/i18n/en.ts +191 -0
- package/src/tool/cronGenerator/i18n/es.ts +191 -0
- package/src/tool/cronGenerator/i18n/fr.ts +191 -0
- package/src/tool/cronGenerator/index.ts +34 -0
- package/src/tool/cronGenerator/seo.astro +14 -0
- package/src/tool/cronGenerator/ui.ts +45 -0
- package/src/tool/cssSpecificityCalculator/bibliography.astro +14 -0
- package/src/tool/cssSpecificityCalculator/component.astro +292 -0
- package/src/tool/cssSpecificityCalculator/i18n/en.ts +168 -0
- package/src/tool/cssSpecificityCalculator/i18n/es.ts +168 -0
- package/src/tool/cssSpecificityCalculator/i18n/fr.ts +168 -0
- package/src/tool/cssSpecificityCalculator/index.ts +34 -0
- package/src/tool/cssSpecificityCalculator/logic.ts +100 -0
- package/src/tool/cssSpecificityCalculator/seo.astro +14 -0
- package/src/tool/cssSpecificityCalculator/ui-controller.ts +57 -0
- package/src/tool/cssSpecificityCalculator/ui.ts +11 -0
- package/src/tool/cssToInlineConverter/bibliography.astro +14 -0
- package/src/tool/cssToInlineConverter/component.astro +308 -0
- package/src/tool/cssToInlineConverter/i18n/en.ts +160 -0
- package/src/tool/cssToInlineConverter/i18n/es.ts +160 -0
- package/src/tool/cssToInlineConverter/i18n/fr.ts +160 -0
- package/src/tool/cssToInlineConverter/index.ts +34 -0
- package/src/tool/cssToInlineConverter/seo.astro +14 -0
- package/src/tool/cssToInlineConverter/ui.ts +12 -0
- package/src/tool/duplicateCssRemover/bibliography.astro +14 -0
- package/src/tool/duplicateCssRemover/component.astro +353 -0
- package/src/tool/duplicateCssRemover/i18n/en.ts +167 -0
- package/src/tool/duplicateCssRemover/i18n/es.ts +167 -0
- package/src/tool/duplicateCssRemover/i18n/fr.ts +167 -0
- package/src/tool/duplicateCssRemover/index.ts +34 -0
- package/src/tool/duplicateCssRemover/seo.astro +14 -0
- package/src/tool/duplicateCssRemover/ui.ts +12 -0
- package/src/tool/generadorSecurityTxt/bibliography.astro +14 -0
- package/src/tool/generadorSecurityTxt/component.astro +473 -0
- package/src/tool/generadorSecurityTxt/i18n/en.ts +173 -0
- package/src/tool/generadorSecurityTxt/i18n/es.ts +173 -0
- package/src/tool/generadorSecurityTxt/i18n/fr.ts +173 -0
- package/src/tool/generadorSecurityTxt/index.ts +33 -0
- package/src/tool/generadorSecurityTxt/seo.astro +14 -0
- package/src/tool/generadorSecurityTxt/ui.ts +27 -0
- package/src/tool/hashGenerator/bibliography.astro +14 -0
- package/src/tool/hashGenerator/component.astro +367 -0
- package/src/tool/hashGenerator/i18n/en.ts +118 -0
- package/src/tool/hashGenerator/i18n/es.ts +118 -0
- package/src/tool/hashGenerator/i18n/fr.ts +118 -0
- package/src/tool/hashGenerator/index.ts +33 -0
- package/src/tool/hashGenerator/md5.ts +138 -0
- package/src/tool/hashGenerator/seo.astro +14 -0
- package/src/tool/hashGenerator/ui.ts +11 -0
- package/src/tool/inspectorCertificadosSsl/bibliography.astro +14 -0
- package/src/tool/inspectorCertificadosSsl/component.astro +580 -0
- package/src/tool/inspectorCertificadosSsl/i18n/en.ts +214 -0
- package/src/tool/inspectorCertificadosSsl/i18n/es.ts +214 -0
- package/src/tool/inspectorCertificadosSsl/i18n/fr.ts +214 -0
- package/src/tool/inspectorCertificadosSsl/index.ts +33 -0
- package/src/tool/inspectorCertificadosSsl/seo.astro +14 -0
- package/src/tool/inspectorCertificadosSsl/ui.ts +29 -0
- package/src/tool/jsonFormatter/bibliography.astro +14 -0
- package/src/tool/jsonFormatter/component.astro +590 -0
- package/src/tool/jsonFormatter/i18n/en.ts +156 -0
- package/src/tool/jsonFormatter/i18n/es.ts +156 -0
- package/src/tool/jsonFormatter/i18n/fr.ts +156 -0
- package/src/tool/jsonFormatter/index.ts +34 -0
- package/src/tool/jsonFormatter/seo.astro +14 -0
- package/src/tool/jsonFormatter/ui.ts +15 -0
- package/src/tool/keycode/bibliography.astro +14 -0
- package/src/tool/keycode/component.astro +540 -0
- package/src/tool/keycode/i18n/en.ts +160 -0
- package/src/tool/keycode/i18n/es.ts +160 -0
- package/src/tool/keycode/i18n/fr.ts +160 -0
- package/src/tool/keycode/index.ts +34 -0
- package/src/tool/keycode/seo.astro +14 -0
- package/src/tool/keycode/ui.ts +10 -0
- package/src/tool/llmCostCalculator/bibliography.astro +14 -0
- package/src/tool/llmCostCalculator/component.astro +488 -0
- package/src/tool/llmCostCalculator/data.ts +99 -0
- package/src/tool/llmCostCalculator/i18n/en.ts +165 -0
- package/src/tool/llmCostCalculator/i18n/es.ts +165 -0
- package/src/tool/llmCostCalculator/i18n/fr.ts +165 -0
- package/src/tool/llmCostCalculator/index.ts +34 -0
- package/src/tool/llmCostCalculator/seo.astro +14 -0
- package/src/tool/llmCostCalculator/ui.ts +11 -0
- package/src/tool/mobileMockupGenerator/app.ts +614 -0
- package/src/tool/mobileMockupGenerator/bibliography.astro +14 -0
- package/src/tool/mobileMockupGenerator/component.astro +1044 -0
- package/src/tool/mobileMockupGenerator/constants.ts +48 -0
- package/src/tool/mobileMockupGenerator/i18n/en.ts +121 -0
- package/src/tool/mobileMockupGenerator/i18n/es.ts +121 -0
- package/src/tool/mobileMockupGenerator/i18n/fr.ts +121 -0
- package/src/tool/mobileMockupGenerator/index.ts +33 -0
- package/src/tool/mobileMockupGenerator/rendering.ts +189 -0
- package/src/tool/mobileMockupGenerator/seo.astro +14 -0
- package/src/tool/mobileMockupGenerator/store.ts +145 -0
- package/src/tool/mobileMockupGenerator/types.ts +41 -0
- package/src/tool/mobileMockupGenerator/ui.ts +48 -0
- package/src/tool/musicalTypography/bibliography.astro +14 -0
- package/src/tool/musicalTypography/component.astro +480 -0
- package/src/tool/musicalTypography/i18n/en.ts +179 -0
- package/src/tool/musicalTypography/i18n/es.ts +179 -0
- package/src/tool/musicalTypography/i18n/fr.ts +179 -0
- package/src/tool/musicalTypography/index.ts +33 -0
- package/src/tool/musicalTypography/seo.astro +14 -0
- package/src/tool/musicalTypography/ui.ts +25 -0
- package/src/tool/placeholderGenerator/bibliography.astro +14 -0
- package/src/tool/placeholderGenerator/component.astro +499 -0
- package/src/tool/placeholderGenerator/i18n/en.ts +176 -0
- package/src/tool/placeholderGenerator/i18n/es.ts +176 -0
- package/src/tool/placeholderGenerator/i18n/fr.ts +176 -0
- package/src/tool/placeholderGenerator/index.ts +34 -0
- package/src/tool/placeholderGenerator/seo.astro +14 -0
- package/src/tool/placeholderGenerator/ui.ts +14 -0
- package/src/tool/promptLibrary/bibliography.astro +14 -0
- package/src/tool/promptLibrary/component.astro +1131 -0
- package/src/tool/promptLibrary/controller.ts +49 -0
- package/src/tool/promptLibrary/i18n/en.ts +131 -0
- package/src/tool/promptLibrary/i18n/es.ts +131 -0
- package/src/tool/promptLibrary/i18n/fr.ts +126 -0
- package/src/tool/promptLibrary/index.ts +33 -0
- package/src/tool/promptLibrary/seo.astro +14 -0
- package/src/tool/promptLibrary/ui.ts +29 -0
- package/src/tool/readabilityCalculator/bibliography.astro +14 -0
- package/src/tool/readabilityCalculator/component.astro +534 -0
- package/src/tool/readabilityCalculator/i18n/en.ts +133 -0
- package/src/tool/readabilityCalculator/i18n/es.ts +133 -0
- package/src/tool/readabilityCalculator/i18n/fr.ts +133 -0
- package/src/tool/readabilityCalculator/index.ts +33 -0
- package/src/tool/readabilityCalculator/seo.astro +14 -0
- package/src/tool/readabilityCalculator/ui.ts +27 -0
- package/src/tool/svgSanitizer/bibliography.astro +14 -0
- package/src/tool/svgSanitizer/component.astro +554 -0
- package/src/tool/svgSanitizer/i18n/en.ts +125 -0
- package/src/tool/svgSanitizer/i18n/es.ts +125 -0
- package/src/tool/svgSanitizer/i18n/fr.ts +125 -0
- package/src/tool/svgSanitizer/index.ts +33 -0
- package/src/tool/svgSanitizer/seo.astro +14 -0
- package/src/tool/svgSanitizer/ui.ts +18 -0
- package/src/tool/svgToCss/bibliography.astro +14 -0
- package/src/tool/svgToCss/component.astro +381 -0
- package/src/tool/svgToCss/i18n/en.ts +174 -0
- package/src/tool/svgToCss/i18n/es.ts +174 -0
- package/src/tool/svgToCss/i18n/fr.ts +174 -0
- package/src/tool/svgToCss/index.ts +34 -0
- package/src/tool/svgToCss/seo.astro +14 -0
- package/src/tool/svgToCss/ui.ts +13 -0
- package/src/tool/urlCleaner/bibliography.astro +14 -0
- package/src/tool/urlCleaner/component.astro +458 -0
- package/src/tool/urlCleaner/i18n/en.ts +116 -0
- package/src/tool/urlCleaner/i18n/es.ts +116 -0
- package/src/tool/urlCleaner/i18n/fr.ts +116 -0
- package/src/tool/urlCleaner/index.ts +33 -0
- package/src/tool/urlCleaner/seo.astro +14 -0
- package/src/tool/urlCleaner/ui.ts +12 -0
- package/src/tool/urlEncoderDecoder/bibliography.astro +14 -0
- package/src/tool/urlEncoderDecoder/component.astro +291 -0
- package/src/tool/urlEncoderDecoder/i18n/en.ts +162 -0
- package/src/tool/urlEncoderDecoder/i18n/es.ts +162 -0
- package/src/tool/urlEncoderDecoder/i18n/fr.ts +162 -0
- package/src/tool/urlEncoderDecoder/index.ts +34 -0
- package/src/tool/urlEncoderDecoder/seo.astro +14 -0
- package/src/tool/urlEncoderDecoder/ui.ts +11 -0
- package/src/tool/utmGenerator/bibliography.astro +14 -0
- package/src/tool/utmGenerator/component.astro +270 -0
- package/src/tool/utmGenerator/i18n/en.ts +117 -0
- package/src/tool/utmGenerator/i18n/es.ts +117 -0
- package/src/tool/utmGenerator/i18n/fr.ts +117 -0
- package/src/tool/utmGenerator/index.ts +33 -0
- package/src/tool/utmGenerator/seo.astro +14 -0
- package/src/tool/utmGenerator/ui.ts +13 -0
- package/src/tools.ts +27 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { GeneradorSecurityTxtUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'generador-security-txt-rfc-9116';
|
|
6
|
+
const title = 'Generador de Security.txt RFC 9116';
|
|
7
|
+
const description = 'Crea tu archivo security.txt profesional para facilitar el reporte de vulnerabilidades y cumplir con los estándares internacionales de seguridad web.';
|
|
8
|
+
|
|
9
|
+
const faqData = [
|
|
10
|
+
{
|
|
11
|
+
question: '¿Qué es el archivo security.txt?',
|
|
12
|
+
answer: 'Es un estándar (RFC 9116) que permite a los sitios web definir cómo los investigadores de seguridad deben contactar con ellos para reportar vulnerabilidades de forma responsable.',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
question: '¿Dónde se debe colocar el archivo security.txt?',
|
|
16
|
+
answer: 'La ubicación estándar recomendada es en la carpeta /.well-known/ de tu dominio, resultando en la URL https://ejemplo.com/.well-known/security.txt.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
question: '¿Por qué es obligatoria la fecha de expiración?',
|
|
20
|
+
answer: 'Para asegurar que la información de contacto no quede obsoleta. Si el archivo no tiene una fecha de expiración válida, los investigadores podrían no confiar en que los canales de comunicación sigan activos.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
question: '¿Qué campos son requeridos en un security.txt?',
|
|
24
|
+
answer: 'Según el RFC 9116, los campos requeridos son "Contact" (con una dirección de correo o URL) y "Expires" (con una fecha futura en formato ISO 8601).',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const howToData = [
|
|
29
|
+
{ name: 'Rellena los campos', text: 'Completa tu dirección de correo o URL de contacto y selecciona una fecha de expiración.' },
|
|
30
|
+
{ name: 'Añade campos opcionales', text: 'Incluye información adicional como tu clave PGP, política de seguridad o bolsa de trabajo.' },
|
|
31
|
+
{ name: 'Descarga o copia el archivo', text: 'Haz clic en "Descargar .txt" o copia el contenido y guárdalo como security.txt.' },
|
|
32
|
+
{ name: 'Sube al servidor', text: 'Coloca el archivo en la carpeta /.well-known/ de tu dominio.' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
36
|
+
'@context': 'https://schema.org',
|
|
37
|
+
'@type': 'FAQPage',
|
|
38
|
+
mainEntity: faqData.map((item) => ({
|
|
39
|
+
'@type': 'Question',
|
|
40
|
+
name: item.question,
|
|
41
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
42
|
+
})),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
46
|
+
'@context': 'https://schema.org',
|
|
47
|
+
'@type': 'HowTo',
|
|
48
|
+
name: title,
|
|
49
|
+
description,
|
|
50
|
+
step: howToData.map((s, i) => ({ '@type': 'HowToStep', position: i + 1, name: s.name, text: s.text })),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
54
|
+
'@context': 'https://schema.org',
|
|
55
|
+
'@type': 'SoftwareApplication',
|
|
56
|
+
name: title,
|
|
57
|
+
description,
|
|
58
|
+
applicationCategory: 'UtilityApplication',
|
|
59
|
+
operatingSystem: 'All',
|
|
60
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
61
|
+
inLanguage: 'es',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const ui: GeneradorSecurityTxtUI = {
|
|
65
|
+
titleBasicFields: 'Campos Básicos (REQUERIDOS)',
|
|
66
|
+
labelContact: 'Contacto (Email o URL)',
|
|
67
|
+
placeholderContact: 'mailto:seguridad@ejemplo.com o https://ejemplo.com/contacto',
|
|
68
|
+
contactTip: 'Dirección a la que enviar los reportes de vulnerabilidades.',
|
|
69
|
+
labelExpires: 'Fecha de Expiración',
|
|
70
|
+
expiresTip: 'No debe ser superior a un año en el futuro.',
|
|
71
|
+
titleOptionalFields: 'Campos Opcionales',
|
|
72
|
+
labelEncryption: 'Clave Pública',
|
|
73
|
+
placeholderEncryption: 'https://ejemplo.com/pgp-key.txt',
|
|
74
|
+
encryptionTip: 'Enlace a tu llave PGP para reportes cifrados.',
|
|
75
|
+
labelPolicy: 'Política de Seguridad',
|
|
76
|
+
placeholderPolicy: 'https://ejemplo.com/seguridad/politica/',
|
|
77
|
+
policyTip: 'Página que detalla cómo manejar vulnerabilidades.',
|
|
78
|
+
labelAcknowledgments: 'Agradecimientos',
|
|
79
|
+
placeholderAcknowledgments: 'https://ejemplo.com/seguridad/hall-of-fame/',
|
|
80
|
+
acknowledgmentsTip: 'Página de agradecimiento a investigadores.',
|
|
81
|
+
labelHiring: 'Bolsa de Trabajo',
|
|
82
|
+
placeholderHiring: 'https://ejemplo.com/jobs',
|
|
83
|
+
hiringTip: 'Enlace a ofertas de empleo de seguridad.',
|
|
84
|
+
resultTitle: 'Vista Previa (security.txt)',
|
|
85
|
+
btnCopy: 'Copiar Código',
|
|
86
|
+
btnDownload: 'Descargar .txt',
|
|
87
|
+
copiedMessage: 'Copiado',
|
|
88
|
+
generatingMessage: 'Generando archivo security.txt...',
|
|
89
|
+
comment: 'Generado',
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const content: ToolLocaleContent<GeneradorSecurityTxtUI> = {
|
|
93
|
+
slug,
|
|
94
|
+
title,
|
|
95
|
+
description,
|
|
96
|
+
ui,
|
|
97
|
+
faqTitle: 'Preguntas Frecuentes',
|
|
98
|
+
faq: faqData,
|
|
99
|
+
bibliographyTitle: 'Recursos Técnicos sobre Security.txt',
|
|
100
|
+
bibliography: [
|
|
101
|
+
{ name: 'RFC 9116: A File Format to Aid in Security Vulnerability Disclosure', url: 'https://datatracker.ietf.org/doc/html/rfc9116' },
|
|
102
|
+
{ name: 'Security.txt Official Website', url: 'https://securitytxt.org/' },
|
|
103
|
+
{ name: 'OWASP: Vulnerability Disclosure Cheat Sheet', url: 'https://cheatsheetseries.owasp.org/cheatsheets/Vulnerability_Disclosure_Cheat_Sheet.html' },
|
|
104
|
+
],
|
|
105
|
+
howTo: howToData,
|
|
106
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
107
|
+
seo: [
|
|
108
|
+
{ type: 'title', text: '¿Qué es un archivo Security.txt y por qué necesitas generarlo?', level: 2 },
|
|
109
|
+
{
|
|
110
|
+
type: 'paragraph',
|
|
111
|
+
html: 'En el panorama actual de la ciberseguridad, la transparencia y la comunicación son fundamentales. Si eres administrador de sistemas, desarrollador web o dueño de un negocio digital, probablemente ya conozcas los archivos de texto que ayudan a las máquinas a entender tu web, como <code>robots.txt</code> o <code>ads.txt</code>. Sin embargo, existe un estándar menos conocido pero vital para la integridad de tu plataforma: el <strong>Security.txt</strong>, definido por el <strong>RFC 9116</strong>.',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'paragraph',
|
|
115
|
+
html: 'El propósito de <strong>generar un archivo security.txt</strong> es proporcionar a los investigadores de seguridad un método estandarizado para contactar con los responsables de un sitio web cuando descubren una vulnerabilidad. Sin este archivo, un "hacker ético" que encuentre un fallo en tu sistema podría no saber a quién reportarlo, lo que a menudo lleva a que la información se pierda, se publique sin previo aviso o, en el peor de los casos, sea explotada por actores maliciosos.',
|
|
116
|
+
},
|
|
117
|
+
{ type: 'title', text: 'Cómo crear e instalar el archivo Security.txt siguiendo el RFC 9116', level: 2 },
|
|
118
|
+
{
|
|
119
|
+
type: 'paragraph',
|
|
120
|
+
html: 'El <strong>estándar de contacto para investigadores de seguridad</strong> dicta que este archivo debe residir en una ubicación específica de tu servidor: la carpeta <code>/.well-known/</code>. Por lo tanto, la ruta final suele ser <code>https://tudominio.com/.well-known/security.txt</code>. Aunque también se permite colocarlo en la raíz (<code>/security.txt</code>), la primera opción es la preferida por las herramientas de escaneo automático.',
|
|
121
|
+
},
|
|
122
|
+
{ type: 'title', text: 'Campos requeridos que no pueden faltar', level: 3 },
|
|
123
|
+
{
|
|
124
|
+
type: 'paragraph',
|
|
125
|
+
html: 'Al <strong>obtener tu código de security.txt</strong>, debes asegurarte de que incluya al menos dos elementos críticos:',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: 'list',
|
|
129
|
+
items: [
|
|
130
|
+
'<strong>Contact:</strong> La dirección de correo electrónico o URL de un formulario donde recibir los reportes. Debe empezar con <code>mailto:</code> o <code>https://</code>.',
|
|
131
|
+
'<strong>Expires:</strong> Una fecha en formato ISO 8601 que indique cuándo deja de ser válida la información del archivo. Se recomienda no poner una fecha superior a un año.',
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
{ type: 'code', text: 'Contact: mailto:seguridad@tuempresa.es\nExpires: 2025-12-31T23:59:59.000Z' },
|
|
135
|
+
{ type: 'title', text: 'Campos opcionales para una seguridad avanzada', level: 3 },
|
|
136
|
+
{
|
|
137
|
+
type: 'paragraph',
|
|
138
|
+
html: 'Para los sitios que buscan una <strong>protección de sitio web</strong> más robusta, el estándar ofrece campos adicionales:',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'list',
|
|
142
|
+
items: [
|
|
143
|
+
'<strong>Encryption:</strong> Un enlace a tu clave pública PGP para que los investigadores puedan enviarte información cifrada y segura.',
|
|
144
|
+
'<strong>Policy:</strong> Un enlace a tu página de política de seguridad donde expliques el proceso de divulgación responsable (Responsible Disclosure).',
|
|
145
|
+
'<strong>Acknowledgments:</strong> Un enlace a tu "Hall of Fame" o muro de agradecimientos para investigadores.',
|
|
146
|
+
'<strong>Hiring:</strong> Un enlace a tus ofertas de empleo relacionadas con la ciberseguridad.',
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{ type: 'title', text: 'Beneficios de usar nuestro generador de Security.txt gratuito', level: 2 },
|
|
150
|
+
{
|
|
151
|
+
type: 'paragraph',
|
|
152
|
+
html: 'Mucha gente se pregunta <strong>cómo sacar el contacto de seguridad</strong> de una web de forma rápida. Al utilizar nuestra herramienta, te aseguras de cumplir estrictamente con el formato del RFC 9116 sin tener que leer documentos técnicos complejos.',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'paragraph',
|
|
156
|
+
html: 'Usar un generador te ahorra errores comunes de sintaxis. Por ejemplo, olvidar el prefijo <code>mailto:</code> o formatear mal la zona horaria en la fecha de expiración puede hacer que las herramientas automatizadas de los investigadores ignoren tu archivo.',
|
|
157
|
+
},
|
|
158
|
+
{ type: 'title', text: 'Impacto en el posicionamiento y reputación web', level: 3 },
|
|
159
|
+
{
|
|
160
|
+
type: 'paragraph',
|
|
161
|
+
html: 'Aunque el archivo <code>security.txt</code> no es un factor de ranking directo en Google como lo puede ser la velocidad de carga o el HTTPS, sí influye indirectamente. Una web que gestiona bien sus vulnerabilidades evita hackeos ruidosos (deface, inyecciones de spam) que arruinan el SEO en cuestión de horas. Además, muchas plataformas de rating de seguridad corporativa (como SecurityScorecard o BitSight) otorgan puntos extra a los dominios que implementan este estándar.',
|
|
162
|
+
},
|
|
163
|
+
{ type: 'title', text: 'Conclusión: Un paso sencillo para una web más segura', level: 2 },
|
|
164
|
+
{
|
|
165
|
+
type: 'paragraph',
|
|
166
|
+
html: 'En resumen, <strong>descargar security.txt</strong> y subirlo a tu servidor es una de las tareas de mantenimiento de seguridad más rápidas y efectivas que puedes realizar hoy mismo. Facilitas el trabajo a los "buenos", desincentivas a los curiosos y demuestras al mundo que te tomas en serio la privacidad y los datos de tus usuarios.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: 'paragraph',
|
|
170
|
+
html: 'No esperes a tener una brecha de seguridad para arrepentirte de no haber facilitado un canal de comunicación. Usa nuestro <strong>generador de security.txt online</strong> ahora y mantén tu ecosistema digital bajo control.',
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { GeneradorSecurityTxtUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'generateur-security-txt-rfc-9116';
|
|
6
|
+
const title = 'Générateur de Security.txt RFC 9116';
|
|
7
|
+
const description = 'Créez votre fichier security.txt professionnel pour faciliter la déclaration des vulnérabilités et respecter les normes de sécurité web internationales.';
|
|
8
|
+
|
|
9
|
+
const faqData = [
|
|
10
|
+
{
|
|
11
|
+
question: 'Qu\'est-ce que le fichier security.txt?',
|
|
12
|
+
answer: 'C\'est une norme (RFC 9116) qui permet aux sites web de définir comment les chercheurs en sécurité doivent les contacter pour signaler les vulnérabilités de manière responsable.',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
question: 'Où doit être placé le fichier security.txt?',
|
|
16
|
+
answer: 'L\'emplacement standard recommandé est dans le dossier /.well-known/ de votre domaine, ce qui donne l\'URL https://exemple.com/.well-known/security.txt.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
question: 'Pourquoi la date d\'expiration est-elle obligatoire?',
|
|
20
|
+
answer: 'Pour s\'assurer que les informations de contact ne deviennent pas obsolètes. Si le fichier ne dispose pas d\'une date d\'expiration valide, les chercheurs pourraient ne pas faire confiance aux canaux de communication.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
question: 'Quels champs sont obligatoires dans un security.txt?',
|
|
24
|
+
answer: 'Selon le RFC 9116, les champs obligatoires sont "Contact" (avec une adresse e-mail ou une URL) et "Expires" (avec une date future au format ISO 8601).',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const howToData = [
|
|
29
|
+
{ name: 'Remplissez les champs', text: 'Entrez votre adresse e-mail ou votre URL de contact et sélectionnez une date d\'expiration.' },
|
|
30
|
+
{ name: 'Ajoutez des champs optionnels', text: 'Incluez des informations supplémentaires telles que votre clé PGP, votre politique de sécurité ou votre forum d\'emploi.' },
|
|
31
|
+
{ name: 'Téléchargez ou copiez le fichier', text: 'Cliquez sur "Télécharger .txt" ou copiez le contenu et enregistrez-le sous security.txt.' },
|
|
32
|
+
{ name: 'Téléchargez sur le serveur', text: 'Placez le fichier dans le dossier /.well-known/ de votre domaine.' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
36
|
+
'@context': 'https://schema.org',
|
|
37
|
+
'@type': 'FAQPage',
|
|
38
|
+
mainEntity: faqData.map((item) => ({
|
|
39
|
+
'@type': 'Question',
|
|
40
|
+
name: item.question,
|
|
41
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
42
|
+
})),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
46
|
+
'@context': 'https://schema.org',
|
|
47
|
+
'@type': 'HowTo',
|
|
48
|
+
name: title,
|
|
49
|
+
description,
|
|
50
|
+
step: howToData.map((s, i) => ({ '@type': 'HowToStep', position: i + 1, name: s.name, text: s.text })),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
54
|
+
'@context': 'https://schema.org',
|
|
55
|
+
'@type': 'SoftwareApplication',
|
|
56
|
+
name: title,
|
|
57
|
+
description,
|
|
58
|
+
applicationCategory: 'UtilityApplication',
|
|
59
|
+
operatingSystem: 'All',
|
|
60
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
61
|
+
inLanguage: 'fr',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const ui: GeneradorSecurityTxtUI = {
|
|
65
|
+
titleBasicFields: 'Champs Obligatoires',
|
|
66
|
+
labelContact: 'Contact (E-mail ou URL)',
|
|
67
|
+
placeholderContact: 'mailto:securite@exemple.com ou https://exemple.com/contact',
|
|
68
|
+
contactTip: 'Adresse où envoyer les rapports de vulnérabilité.',
|
|
69
|
+
labelExpires: 'Date d\'Expiration',
|
|
70
|
+
expiresTip: 'Ne doit pas dépasser un an à l\'avenir.',
|
|
71
|
+
titleOptionalFields: 'Champs Optionnels',
|
|
72
|
+
labelEncryption: 'Clé Publique',
|
|
73
|
+
placeholderEncryption: 'https://exemple.com/pgp-key.txt',
|
|
74
|
+
encryptionTip: 'Lien vers votre clé PGP pour les rapports chiffrés.',
|
|
75
|
+
labelPolicy: 'Politique de Sécurité',
|
|
76
|
+
placeholderPolicy: 'https://exemple.com/securite/politique/',
|
|
77
|
+
policyTip: 'Page détaillant comment gérer les vulnérabilités.',
|
|
78
|
+
labelAcknowledgments: 'Remerciements',
|
|
79
|
+
placeholderAcknowledgments: 'https://exemple.com/securite/hall-of-fame/',
|
|
80
|
+
acknowledgmentsTip: 'Page remerciant les chercheurs en sécurité.',
|
|
81
|
+
labelHiring: 'Offres d\'Emploi',
|
|
82
|
+
placeholderHiring: 'https://exemple.com/emplois',
|
|
83
|
+
hiringTip: 'Lien vers vos offres d\'emploi en cybersécurité.',
|
|
84
|
+
resultTitle: 'Aperçu (security.txt)',
|
|
85
|
+
btnCopy: 'Copier le Code',
|
|
86
|
+
btnDownload: 'Télécharger .txt',
|
|
87
|
+
copiedMessage: 'Copié',
|
|
88
|
+
generatingMessage: 'Génération du fichier security.txt...',
|
|
89
|
+
comment: 'Généré',
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const content: ToolLocaleContent<GeneradorSecurityTxtUI> = {
|
|
93
|
+
slug,
|
|
94
|
+
title,
|
|
95
|
+
description,
|
|
96
|
+
ui,
|
|
97
|
+
faqTitle: 'Questions Fréquemment Posées',
|
|
98
|
+
faq: faqData,
|
|
99
|
+
bibliographyTitle: 'Ressources Techniques sur Security.txt',
|
|
100
|
+
bibliography: [
|
|
101
|
+
{ name: 'RFC 9116: A File Format to Aid in Security Vulnerability Disclosure', url: 'https://datatracker.ietf.org/doc/html/rfc9116' },
|
|
102
|
+
{ name: 'Site Officiel de Security.txt', url: 'https://securitytxt.org/' },
|
|
103
|
+
{ name: 'OWASP: Feuille de Triche sur la Divulgation de Vulnérabilité', url: 'https://cheatsheetseries.owasp.org/cheatsheets/Vulnerability_Disclosure_Cheat_Sheet.html' },
|
|
104
|
+
],
|
|
105
|
+
howTo: howToData,
|
|
106
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
107
|
+
seo: [
|
|
108
|
+
{ type: 'title', text: 'Qu\'est-ce qu\'un fichier Security.txt et pourquoi devez-vous en générer un?', level: 2 },
|
|
109
|
+
{
|
|
110
|
+
type: 'paragraph',
|
|
111
|
+
html: 'Dans le paysage actuel de la cybersécurité, la transparence et la communication sont essentielles. Si vous êtes administrateur système, développeur web ou propriétaire d\'une entreprise numérique, vous êtes probablement déjà familiarisé avec les fichiers texte qui aident les machines à comprendre votre site web, comme <code>robots.txt</code> ou <code>ads.txt</code>. Cependant, il existe une norme moins connue mais vitale pour l\'intégrité de votre plateforme: le <strong>Security.txt</strong>, défini par <strong>RFC 9116</strong>.',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'paragraph',
|
|
115
|
+
html: 'L\'objectif de <strong>générer un fichier security.txt</strong> est de fournir aux chercheurs en sécurité une méthode normalisée pour contacter les responsables de votre site web lorsqu\'ils découvrent une vulnérabilité. Sans ce fichier, un "pirate éthique" qui découvre un défaut dans votre système pourrait ne pas savoir à qui le signaler, ce qui entraîne souvent la perte de l\'information, sa publication sans préavis, ou son exploitation par des acteurs malveillants.',
|
|
116
|
+
},
|
|
117
|
+
{ type: 'title', text: 'Comment créer et installer le fichier Security.txt en suivant RFC 9116', level: 2 },
|
|
118
|
+
{
|
|
119
|
+
type: 'paragraph',
|
|
120
|
+
html: 'La <strong>norme de contact des chercheurs en sécurité</strong> stipule que ce fichier doit résider dans un endroit spécifique de votre serveur: le dossier <code>/.well-known/</code>. Par conséquent, le chemin final est généralement <code>https://votredomaine.com/.well-known/security.txt</code>. Bien qu\'il soit également autorisé de le placer à la racine (<code>/security.txt</code>), la première option est préférée par les outils de numérisation automatique.',
|
|
121
|
+
},
|
|
122
|
+
{ type: 'title', text: 'Les champs obligatoires que vous ne pouvez pas manquer', level: 3 },
|
|
123
|
+
{
|
|
124
|
+
type: 'paragraph',
|
|
125
|
+
html: 'Lorsque <strong>vous obtenez votre code security.txt</strong>, vous devez vous assurer qu\'il comprend au moins deux éléments critiques:',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: 'list',
|
|
129
|
+
items: [
|
|
130
|
+
'<strong>Contact:</strong> L\'adresse e-mail ou l\'URL du formulaire où les rapports doivent être envoyés. Doit commencer par <code>mailto:</code> ou <code>https://</code>.',
|
|
131
|
+
'<strong>Expires:</strong> Une date au format ISO 8601 qui indique quand les informations du fichier ne sont plus valides. Il est recommandé de ne pas fixer une date supérieure à un an.',
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
{ type: 'code', text: 'Contact: mailto:securite@votreentreprise.fr\nExpires: 2025-12-31T23:59:59.000Z' },
|
|
135
|
+
{ type: 'title', text: 'Champs optionnels pour une sécurité avancée', level: 3 },
|
|
136
|
+
{
|
|
137
|
+
type: 'paragraph',
|
|
138
|
+
html: 'Pour les sites recherchant une <strong>protection de site web</strong> plus robuste, la norme offre des champs supplémentaires:',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'list',
|
|
142
|
+
items: [
|
|
143
|
+
'<strong>Encryption:</strong> Un lien vers votre clé publique PGP pour que les chercheurs puissent vous envoyer des informations chiffrées et sécurisées.',
|
|
144
|
+
'<strong>Policy:</strong> Un lien vers votre page de politique de sécurité où vous expliquez le processus de divulgation responsable.',
|
|
145
|
+
'<strong>Acknowledgments:</strong> Un lien vers votre "Hall of Fame" ou mur d\'appréciation pour les chercheurs.',
|
|
146
|
+
'<strong>Hiring:</strong> Un lien vers vos offres d\'emploi en cybersécurité.',
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{ type: 'title', text: 'Avantages d\'utiliser notre générateur Security.txt gratuit', level: 2 },
|
|
150
|
+
{
|
|
151
|
+
type: 'paragraph',
|
|
152
|
+
html: 'Beaucoup de gens se demandent <strong>comment obtenir le contact de sécurité</strong> d\'un site web rapidement. En utilisant notre outil, vous vous assurez de respecter strictement le format RFC 9116 sans avoir à lire des documents techniques complexes.',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'paragraph',
|
|
156
|
+
html: 'L\'utilisation d\'un générateur vous épargne des erreurs de syntaxe courantes. Par exemple, oublier le préfixe <code>mailto:</code> ou mal formater le fuseau horaire dans la date d\'expiration peut amener les outils automatisés des chercheurs à ignorer votre fichier.',
|
|
157
|
+
},
|
|
158
|
+
{ type: 'title', text: 'Impact sur le positionnement et la réputation web', level: 3 },
|
|
159
|
+
{
|
|
160
|
+
type: 'paragraph',
|
|
161
|
+
html: 'Bien que le fichier <code>security.txt</code> ne soit pas un facteur de classement direct dans Google comme la vitesse de la page ou HTTPS, il a un impact indirect. Un site web qui gère bien ses vulnérabilités évite les piratages bruyants (défacement, injection de spam) qui ruinent le SEO en quelques heures. De plus, de nombreuses plateformes de notation de sécurité d\'entreprise (telles que SecurityScorecard ou BitSight) accordent des points supplémentaires aux domaines qui implémentent cette norme.',
|
|
162
|
+
},
|
|
163
|
+
{ type: 'title', text: 'Conclusion: Un pas simple pour un web plus sûr', level: 2 },
|
|
164
|
+
{
|
|
165
|
+
type: 'paragraph',
|
|
166
|
+
html: 'En résumé, <strong>télécharger security.txt</strong> et le télécharger sur votre serveur est l\'une des tâches de maintenance de sécurité les plus rapides et les plus efficaces que vous puissiez accomplir aujourd\'hui. Vous facilitez le travail des "bons gars", dissuadez les curieux et montrez au monde que vous prenez au sérieux la confidentialité et les données de vos utilisateurs.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: 'paragraph',
|
|
170
|
+
html: 'N\'attendez pas une violation de sécurité pour regretter de ne pas avoir fourni un canal de communication. Utilisez dès maintenant notre <strong>générateur de security.txt en ligne</strong> et maintenez votre écosystème numérique sous contrôle.',
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { DeveloperToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
|
|
2
|
+
import GeneradorSecurityTxtComponent from './component.astro';
|
|
3
|
+
import GeneradorSecurityTxtSEO from './seo.astro';
|
|
4
|
+
import GeneradorSecurityTxtBibliography from './bibliography.astro';
|
|
5
|
+
import type { GeneradorSecurityTxtUI } from './ui';
|
|
6
|
+
|
|
7
|
+
export type GeneradorSecurityTxtLocaleContent = ToolLocaleContent<GeneradorSecurityTxtUI>;
|
|
8
|
+
|
|
9
|
+
import { content as es } from './i18n/es';
|
|
10
|
+
import { content as en } from './i18n/en';
|
|
11
|
+
import { content as fr } from './i18n/fr';
|
|
12
|
+
|
|
13
|
+
export const generadorSecurityTxt: DeveloperToolEntry<GeneradorSecurityTxtUI> = {
|
|
14
|
+
id: 'generador-security-txt',
|
|
15
|
+
icons: {
|
|
16
|
+
bg: 'mdi:shield-alert',
|
|
17
|
+
fg: 'mdi:file-document',
|
|
18
|
+
},
|
|
19
|
+
i18n: {
|
|
20
|
+
es: async () => es,
|
|
21
|
+
en: async () => en,
|
|
22
|
+
fr: async () => fr,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { GeneradorSecurityTxtComponent, GeneradorSecurityTxtSEO, GeneradorSecurityTxtBibliography };
|
|
27
|
+
|
|
28
|
+
export const GENERADOR_SECURITY_TXT_TOOL: ToolDefinition = {
|
|
29
|
+
entry: generadorSecurityTxt,
|
|
30
|
+
Component: GeneradorSecurityTxtComponent,
|
|
31
|
+
SEOComponent: GeneradorSecurityTxtSEO,
|
|
32
|
+
BibliographyComponent: GeneradorSecurityTxtBibliography,
|
|
33
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { generadorSecurityTxt } 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 generadorSecurityTxt.i18n[locale]?.();
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{content && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface GeneradorSecurityTxtUI extends Record<string, string> {
|
|
2
|
+
titleBasicFields: string;
|
|
3
|
+
labelContact: string;
|
|
4
|
+
placeholderContact: string;
|
|
5
|
+
contactTip: string;
|
|
6
|
+
labelExpires: string;
|
|
7
|
+
expiresTip: string;
|
|
8
|
+
titleOptionalFields: string;
|
|
9
|
+
labelEncryption: string;
|
|
10
|
+
placeholderEncryption: string;
|
|
11
|
+
encryptionTip: string;
|
|
12
|
+
labelPolicy: string;
|
|
13
|
+
placeholderPolicy: string;
|
|
14
|
+
policyTip: string;
|
|
15
|
+
labelAcknowledgments: string;
|
|
16
|
+
placeholderAcknowledgments: string;
|
|
17
|
+
acknowledgmentsTip: string;
|
|
18
|
+
labelHiring: string;
|
|
19
|
+
placeholderHiring: string;
|
|
20
|
+
hiringTip: string;
|
|
21
|
+
resultTitle: string;
|
|
22
|
+
btnCopy: string;
|
|
23
|
+
btnDownload: string;
|
|
24
|
+
copiedMessage: string;
|
|
25
|
+
generatingMessage: string;
|
|
26
|
+
comment: string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { hashGenerator } 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 hashGenerator.i18n[locale]?.();
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{content && <SharedBibliography links={content.bibliography} />}
|