@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,167 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { DuplicateCssRemoverUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'duplicate-css-remover';
|
|
6
|
+
const title = 'Duplicate CSS Remover Online. Unify and Clean Stylesheets';
|
|
7
|
+
const description =
|
|
8
|
+
'Free tool to clean and purge duplicate CSS code. Unifies redundant selectors, respects the cascade, and reduces your file size instantly in the browser.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'What happens when CSS selectors are duplicated?',
|
|
13
|
+
answer:
|
|
14
|
+
'When the same selector appears multiple times, the browser applies all the rules but the last declaration of each property overrides the earlier ones. This generates heavier files than necessary with no real benefit to the visual result.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'Will any properties be lost when removing duplicates?',
|
|
18
|
+
answer:
|
|
19
|
+
'No. The algorithm strictly respects the CSS cascade: for conflicting properties under the same selector, it always preserves the last declared one. Unique properties from each block are combined under a single unified selector.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Does it work with minified CSS or CSS with comments?',
|
|
23
|
+
answer:
|
|
24
|
+
'The tool automatically strips CSS comments before processing and works correctly with single-line code. For CSS with advanced nesting or complex at-rules, it is recommended to separate the blocks first.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'Is my CSS sent to any server?',
|
|
28
|
+
answer:
|
|
29
|
+
'No. All processing happens directly in your browser via local JavaScript. No part of your CSS is transmitted to any external server, guaranteeing complete privacy of your code.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howToData = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Paste your dirty CSS',
|
|
36
|
+
text: 'Copy the content of your CSS file with repeated selectors and paste it into the left field labeled "Dirty / Duplicate CSS".',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Run the cleanup',
|
|
40
|
+
text: 'Click the "Clean and Unify CSS" button. The tool will scan all selectors, merge properties, and remove redundant blocks.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Review stats and copy',
|
|
44
|
+
text: 'Check the byte savings achieved and copy the optimized CSS with the "Copy Code" button to use it directly in your project.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
49
|
+
'@context': 'https://schema.org',
|
|
50
|
+
'@type': 'FAQPage',
|
|
51
|
+
mainEntity: faqData.map((item) => ({
|
|
52
|
+
'@type': 'Question',
|
|
53
|
+
name: item.question,
|
|
54
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
55
|
+
})),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
59
|
+
'@context': 'https://schema.org',
|
|
60
|
+
'@type': 'HowTo',
|
|
61
|
+
name: title,
|
|
62
|
+
description,
|
|
63
|
+
step: howToData.map((step, i) => ({
|
|
64
|
+
'@type': 'HowToStep',
|
|
65
|
+
position: i + 1,
|
|
66
|
+
name: step.name,
|
|
67
|
+
text: step.text,
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
72
|
+
'@context': 'https://schema.org',
|
|
73
|
+
'@type': 'SoftwareApplication',
|
|
74
|
+
name: title,
|
|
75
|
+
description,
|
|
76
|
+
applicationCategory: 'UtilityApplication',
|
|
77
|
+
operatingSystem: 'All',
|
|
78
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
79
|
+
inLanguage: 'en',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const ui: DuplicateCssRemoverUI = {
|
|
83
|
+
labelInput: 'Dirty / Duplicate CSS',
|
|
84
|
+
labelOutput: 'Clean CSS',
|
|
85
|
+
placeholderInput: '.btn { padding: 10px; color: red; }\n.btn { margin: 5px; color: blue; }',
|
|
86
|
+
placeholderOutput: 'Optimized and unified CSS will appear here...',
|
|
87
|
+
btnClean: 'Clean and Unify CSS',
|
|
88
|
+
btnCopy: 'Copy Code',
|
|
89
|
+
btnCopied: 'Copied!',
|
|
90
|
+
statBytesOriginal: 'Original Bytes',
|
|
91
|
+
statBytesClean: 'Clean Bytes',
|
|
92
|
+
statSaving: 'Savings',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const content: ToolLocaleContent<DuplicateCssRemoverUI> = {
|
|
96
|
+
slug,
|
|
97
|
+
title,
|
|
98
|
+
description,
|
|
99
|
+
ui,
|
|
100
|
+
faqTitle: 'Frequently Asked Questions',
|
|
101
|
+
faq: faqData,
|
|
102
|
+
bibliographyTitle: 'References and Documentation',
|
|
103
|
+
bibliography: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Web Vitals: CSS Impact on Render-Blocking and FCP',
|
|
106
|
+
url: 'https://web.dev/articles/render-blocking-resources',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'W3C Specification: CSS Cascade and Inheritance',
|
|
110
|
+
url: 'https://www.w3.org/TR/css-cascade-4/',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Clean CSS: Library and Methodologies for CSS Minification',
|
|
114
|
+
url: 'https://github.com/clean-css/clean-css',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
howTo: howToData,
|
|
118
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
119
|
+
seo: [
|
|
120
|
+
{
|
|
121
|
+
type: 'title',
|
|
122
|
+
text: 'Why Does CSS Code Get Duplicated?',
|
|
123
|
+
level: 2,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'paragraph',
|
|
127
|
+
html: 'When maintaining long-term web projects or working with legacy code, it is extremely common for multiple developers to write overlapping CSS rules. Often, out of fear of breaking an existing design, a developer prefers to add a new redundant rule at the end of the document rather than editing or refactoring the original.',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'paragraph',
|
|
131
|
+
html: 'The result is an inefficient file with dozens of selectors declared repeatedly, killing readability and significantly increasing the download weight of your web page.',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: 'title',
|
|
135
|
+
text: 'The Hidden Impact on Web Performance (Web Vitals)',
|
|
136
|
+
level: 3,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'paragraph',
|
|
140
|
+
html: 'Stylesheet files block the natural rendering of the browser (a <strong>Render-Blocking</strong> resource). Until your browser downloads and builds the complete CSSOM, your screen remains blank.',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'tip',
|
|
144
|
+
html: 'Purging redundant styles is not just about code cleanliness; it is a measurable and immediate improvement in vital metrics such as <strong>First Contentful Paint (FCP)</strong>.',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'title',
|
|
148
|
+
text: 'How We Unify Duplicate Rules',
|
|
149
|
+
level: 3,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: 'paragraph',
|
|
153
|
+
html: 'This utility acts as an intelligent assembler. Rather than just compressing whitespace (as a traditional minifier would), it recursively scans the text for identical selector patterns.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'list',
|
|
157
|
+
items: [
|
|
158
|
+
'Imagine having the rule <code>.box { color: red; }</code> and a hundred lines later a <code>.box { padding: 10px; color: blue; }</code>. The tool will unify both blocks under the same selector <code>.box</code>, merging the padding.',
|
|
159
|
+
'<strong>CSS Cascade Preservation:</strong> For direct conflicts, the algorithm strictly preserves the last declared property. This ensures your original layout does not break when purging the document.',
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'paragraph',
|
|
164
|
+
html: 'Stop sending kilobytes of dead text to your users\' mobile phones. Unify your code in milliseconds entirely offline from your browser.',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { DuplicateCssRemoverUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'eliminador-css-duplicado';
|
|
6
|
+
const title = 'Eliminador de CSS Duplicado Online. Unifica y Limpia Estilos';
|
|
7
|
+
const description =
|
|
8
|
+
'Herramienta gratuita para limpiar y purgar código CSS duplicado. Unifica selectores redundantes, respeta la cascada y reduce el tamaño de tus archivos al instante.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: '¿Qué ocurre cuando hay selectores CSS duplicados?',
|
|
13
|
+
answer:
|
|
14
|
+
'Cuando el mismo selector aparece varias veces, el navegador aplica todas las reglas pero la última declaración de cada propiedad sobreescribe a las anteriores. Esto genera archivos más pesados de lo necesario sin ningún beneficio real en el resultado visual.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: '¿Se perderá alguna propiedad al eliminar duplicados?',
|
|
18
|
+
answer:
|
|
19
|
+
'No. El algoritmo respeta estrictamente la cascada CSS: ante propiedades en conflicto bajo el mismo selector, preserva siempre la última declarada. Las propiedades únicas de cada bloque se combinan bajo un único selector unificado.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: '¿Funciona con CSS minificado o con comentarios?',
|
|
23
|
+
answer:
|
|
24
|
+
'La herramienta elimina automáticamente los comentarios CSS antes de procesar y trabaja correctamente con código en una sola línea. Para CSS con anidamiento avanzado (nesting, at-rules complejos) se recomienda separar primero los bloques.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: '¿Mis datos se envían a algún servidor?',
|
|
28
|
+
answer:
|
|
29
|
+
'No. Todo el procesamiento ocurre directamente en tu navegador mediante JavaScript local. Ningún fragmento de tu CSS es transmitido a ningún servidor externo, garantizando la privacidad total de tu código.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howToData = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Pega tu CSS sucio',
|
|
36
|
+
text: 'Copia el contenido de tu archivo CSS con selectores repetidos y pégalo en el campo de la izquierda "CSS Sucio / Duplicado".',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Ejecuta la limpieza',
|
|
40
|
+
text: 'Haz clic en el botón "Limpiar y Unificar CSS". La herramienta escaneará todos los selectores, combinará propiedades y eliminará bloques redundantes.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Revisa las estadísticas y copia',
|
|
44
|
+
text: 'Observa el ahorro en bytes obtenido y copia el CSS optimizado con el botón "Copiar Código" para usarlo directamente en tu proyecto.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
49
|
+
'@context': 'https://schema.org',
|
|
50
|
+
'@type': 'FAQPage',
|
|
51
|
+
mainEntity: faqData.map((item) => ({
|
|
52
|
+
'@type': 'Question',
|
|
53
|
+
name: item.question,
|
|
54
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
55
|
+
})),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
59
|
+
'@context': 'https://schema.org',
|
|
60
|
+
'@type': 'HowTo',
|
|
61
|
+
name: title,
|
|
62
|
+
description,
|
|
63
|
+
step: howToData.map((step, i) => ({
|
|
64
|
+
'@type': 'HowToStep',
|
|
65
|
+
position: i + 1,
|
|
66
|
+
name: step.name,
|
|
67
|
+
text: step.text,
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
72
|
+
'@context': 'https://schema.org',
|
|
73
|
+
'@type': 'SoftwareApplication',
|
|
74
|
+
name: title,
|
|
75
|
+
description,
|
|
76
|
+
applicationCategory: 'UtilityApplication',
|
|
77
|
+
operatingSystem: 'All',
|
|
78
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
79
|
+
inLanguage: 'es',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const ui: DuplicateCssRemoverUI = {
|
|
83
|
+
labelInput: 'CSS Sucio / Duplicado',
|
|
84
|
+
labelOutput: 'CSS Limpio',
|
|
85
|
+
placeholderInput: '.btn { padding: 10px; color: red; }\n.btn { margin: 5px; color: blue; }',
|
|
86
|
+
placeholderOutput: 'Aquí aparecerá el CSS optimizado y unificado...',
|
|
87
|
+
btnClean: 'Limpiar y Unificar CSS',
|
|
88
|
+
btnCopy: 'Copiar Código',
|
|
89
|
+
btnCopied: '¡Copiado!',
|
|
90
|
+
statBytesOriginal: 'Bytes Originales',
|
|
91
|
+
statBytesClean: 'Bytes Limpios',
|
|
92
|
+
statSaving: 'De Ahorro',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const content: ToolLocaleContent<DuplicateCssRemoverUI> = {
|
|
96
|
+
slug,
|
|
97
|
+
title,
|
|
98
|
+
description,
|
|
99
|
+
ui,
|
|
100
|
+
faqTitle: 'Preguntas Frecuentes',
|
|
101
|
+
faq: faqData,
|
|
102
|
+
bibliographyTitle: 'Referencias y Documentación',
|
|
103
|
+
bibliography: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Web Vitals: Impacto del CSS en Render-Blocking y FCP',
|
|
106
|
+
url: 'https://web.dev/articles/render-blocking-resources',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Especificación W3C: Cascada CSS y Herencia',
|
|
110
|
+
url: 'https://www.w3.org/TR/css-cascade-4/',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Clean CSS: Librería y metodologías para CSS minifier',
|
|
114
|
+
url: 'https://github.com/clean-css/clean-css',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
howTo: howToData,
|
|
118
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
119
|
+
seo: [
|
|
120
|
+
{
|
|
121
|
+
type: 'title',
|
|
122
|
+
text: '¿Por qué se duplica el código CSS?',
|
|
123
|
+
level: 2,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'paragraph',
|
|
127
|
+
html: 'Al mantener proyectos web a largo plazo o trabajar con código heredado (<em>legacy code</em>), es extremadamente común que varios desarrolladores escriban reglas CSS superpuestas. A menudo, por miedo a romper un diseño existente, un programador prefiere añadir una nueva regla redundante al final del documento en lugar de editar o refactorizar la original.',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'paragraph',
|
|
131
|
+
html: 'El resultado es un archivo ineficiente con docenas de selectores declarados de forma repetida que ahogan la legibilidad y aumentan considerablemente el peso de descarga de tu página web.',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: 'title',
|
|
135
|
+
text: 'El impacto oculto en el Rendimiento Web (Web Vitals)',
|
|
136
|
+
level: 3,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'paragraph',
|
|
140
|
+
html: 'Los archivos de estilo bloquean el renderizado natural del navegador (recurso <strong>Render-Blocking</strong>). Hasta que tu navegador no descarga y construye el CSSOM completo, tu pantalla permanece en blanco.',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'tip',
|
|
144
|
+
html: 'Purgar los estilos redundantes no es una mera cuestión de pulcritud en el código; es una mejora medible e inmediata en métricas vitales como el <strong>First Contentful Paint (FCP)</strong>.',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'title',
|
|
148
|
+
text: 'Cómo unificamos las reglas duplicadas',
|
|
149
|
+
level: 3,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: 'paragraph',
|
|
153
|
+
html: 'Esta utilidad actúa como un ensamblador inteligente. En lugar de limitarse a comprimir espacios (como haría un minificador tradicional), escanea recursivamente el texto buscando patrones de selectores idénticos.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'list',
|
|
157
|
+
items: [
|
|
158
|
+
'Imagina tener la regla <code>.box { color: red; }</code> y cien líneas más abajo un <code>.box { padding: 10px; color: blue; }</code>. La herramienta unificará ambos bloques bajo el mismo selector <code>.box</code> combinando el padding.',
|
|
159
|
+
'<strong>Preservación de la Cascada CSS:</strong> Ante conflictos directos, el algoritmo preserva estrictamente la última propiedad declarada. Así garantizamos que tu maquetado original no se rompa al purgar el documento.',
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'paragraph',
|
|
164
|
+
html: 'Se acabó enviar kilobytes de texto muerto a los teléfonos móviles de tus usuarios. Unifica tu código en milésimas de segundo totalmente offline desde tu navegador.',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { DuplicateCssRemoverUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'suppression-css-duplique';
|
|
6
|
+
const title = 'Suppression de CSS Dupliqué en Ligne. Unifier et Nettoyer les Styles';
|
|
7
|
+
const description =
|
|
8
|
+
'Outil gratuit pour nettoyer et purger le code CSS dupliqué. Unifie les sélecteurs redondants, respecte la cascade et réduit la taille de vos fichiers instantanément.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Que se passe-t-il lorsque des sélecteurs CSS sont dupliqués ?',
|
|
13
|
+
answer:
|
|
14
|
+
'Lorsque le même sélecteur apparaît plusieurs fois, le navigateur applique toutes les règles mais la dernière déclaration de chaque propriété écrase les précédentes. Cela génère des fichiers plus lourds que nécessaire sans aucun bénéfice réel sur le rendu visuel.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'Des propriétés seront-elles perdues lors de la suppression des doublons ?',
|
|
18
|
+
answer:
|
|
19
|
+
'Non. L\'algorithme respecte strictement la cascade CSS : pour les propriétés en conflit sous le même sélecteur, il préserve toujours la dernière déclarée. Les propriétés uniques de chaque bloc sont combinées sous un sélecteur unifié.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Fonctionne-t-il avec du CSS minifié ou des commentaires ?',
|
|
23
|
+
answer:
|
|
24
|
+
'L\'outil supprime automatiquement les commentaires CSS avant le traitement et fonctionne correctement avec du code sur une seule ligne. Pour du CSS avec des imbrications avancées ou des at-rules complexes, il est recommandé de séparer d\'abord les blocs.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'Mon CSS est-il envoyé à un serveur ?',
|
|
28
|
+
answer:
|
|
29
|
+
'Non. Tout le traitement se fait directement dans votre navigateur via JavaScript local. Aucune partie de votre CSS n\'est transmise à un serveur externe, garantissant la confidentialité totale de votre code.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howToData = [
|
|
34
|
+
{
|
|
35
|
+
name: 'Collez votre CSS brut',
|
|
36
|
+
text: 'Copiez le contenu de votre fichier CSS avec des sélecteurs répétés et collez-le dans le champ gauche "CSS Brut / Dupliqué".',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Lancez le nettoyage',
|
|
40
|
+
text: 'Cliquez sur le bouton "Nettoyer et Unifier le CSS". L\'outil analysera tous les sélecteurs, fusionnera les propriétés et supprimera les blocs redondants.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Vérifiez les statistiques et copiez',
|
|
44
|
+
text: 'Consultez les économies en octets obtenues et copiez le CSS optimisé avec le bouton "Copier le Code" pour l\'utiliser directement dans votre projet.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
49
|
+
'@context': 'https://schema.org',
|
|
50
|
+
'@type': 'FAQPage',
|
|
51
|
+
mainEntity: faqData.map((item) => ({
|
|
52
|
+
'@type': 'Question',
|
|
53
|
+
name: item.question,
|
|
54
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
55
|
+
})),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
59
|
+
'@context': 'https://schema.org',
|
|
60
|
+
'@type': 'HowTo',
|
|
61
|
+
name: title,
|
|
62
|
+
description,
|
|
63
|
+
step: howToData.map((step, i) => ({
|
|
64
|
+
'@type': 'HowToStep',
|
|
65
|
+
position: i + 1,
|
|
66
|
+
name: step.name,
|
|
67
|
+
text: step.text,
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
72
|
+
'@context': 'https://schema.org',
|
|
73
|
+
'@type': 'SoftwareApplication',
|
|
74
|
+
name: title,
|
|
75
|
+
description,
|
|
76
|
+
applicationCategory: 'UtilityApplication',
|
|
77
|
+
operatingSystem: 'All',
|
|
78
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
79
|
+
inLanguage: 'fr',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const ui: DuplicateCssRemoverUI = {
|
|
83
|
+
labelInput: 'CSS Brut / Dupliqué',
|
|
84
|
+
labelOutput: 'CSS Propre',
|
|
85
|
+
placeholderInput: '.btn { padding: 10px; color: red; }\n.btn { margin: 5px; color: blue; }',
|
|
86
|
+
placeholderOutput: 'Le CSS optimisé et unifié apparaîtra ici...',
|
|
87
|
+
btnClean: 'Nettoyer et Unifier le CSS',
|
|
88
|
+
btnCopy: 'Copier le Code',
|
|
89
|
+
btnCopied: 'Copié !',
|
|
90
|
+
statBytesOriginal: 'Octets Originaux',
|
|
91
|
+
statBytesClean: 'Octets Propres',
|
|
92
|
+
statSaving: 'Économie',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const content: ToolLocaleContent<DuplicateCssRemoverUI> = {
|
|
96
|
+
slug,
|
|
97
|
+
title,
|
|
98
|
+
description,
|
|
99
|
+
ui,
|
|
100
|
+
faqTitle: 'Questions Fréquentes',
|
|
101
|
+
faq: faqData,
|
|
102
|
+
bibliographyTitle: 'Références et Documentation',
|
|
103
|
+
bibliography: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Web Vitals: Impact du CSS sur le Render-Blocking et FCP',
|
|
106
|
+
url: 'https://web.dev/articles/render-blocking-resources',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Spécification W3C: Cascade CSS et Héritage',
|
|
110
|
+
url: 'https://www.w3.org/TR/css-cascade-4/',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Clean CSS: Bibliothèque et méthodologies pour la minification CSS',
|
|
114
|
+
url: 'https://github.com/clean-css/clean-css',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
howTo: howToData,
|
|
118
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
119
|
+
seo: [
|
|
120
|
+
{
|
|
121
|
+
type: 'title',
|
|
122
|
+
text: 'Pourquoi le code CSS se duplique-t-il ?',
|
|
123
|
+
level: 2,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'paragraph',
|
|
127
|
+
html: 'Lors de la maintenance de projets web à long terme ou lors du travail avec du code hérité (<em>legacy code</em>), il est extrêmement courant que plusieurs développeurs écrivent des règles CSS qui se chevauchent. Souvent, par peur de casser un design existant, un développeur préfère ajouter une nouvelle règle redondante à la fin du document plutôt que de modifier ou refactoriser l\'originale.',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'paragraph',
|
|
131
|
+
html: 'Le résultat est un fichier inefficace avec des dizaines de sélecteurs déclarés de manière répétée, nuisant à la lisibilité et augmentant considérablement le poids de téléchargement de votre page web.',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: 'title',
|
|
135
|
+
text: 'L\'impact caché sur les performances web (Web Vitals)',
|
|
136
|
+
level: 3,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'paragraph',
|
|
140
|
+
html: 'Les fichiers de style bloquent le rendu naturel du navigateur (ressource <strong>Render-Blocking</strong>). Tant que votre navigateur n\'a pas téléchargé et construit le CSSOM complet, votre écran reste blanc.',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'tip',
|
|
144
|
+
html: 'Purger les styles redondants n\'est pas une simple question d\'ordre dans le code ; c\'est une amélioration mesurable et immédiate des métriques vitales comme le <strong>First Contentful Paint (FCP)</strong>.',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'title',
|
|
148
|
+
text: 'Comment nous unifions les règles dupliquées',
|
|
149
|
+
level: 3,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: 'paragraph',
|
|
153
|
+
html: 'Cet utilitaire agit comme un assembleur intelligent. Au lieu de se limiter à compresser les espaces (comme le ferait un minificateur traditionnel), il analyse récursivement le texte à la recherche de motifs de sélecteurs identiques.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'list',
|
|
157
|
+
items: [
|
|
158
|
+
'Imaginez avoir la règle <code>.box { color: red; }</code> et cent lignes plus bas un <code>.box { padding: 10px; color: blue; }</code>. L\'outil unifiera les deux blocs sous le même sélecteur <code>.box</code> en combinant le padding.',
|
|
159
|
+
'<strong>Préservation de la Cascade CSS :</strong> En cas de conflits directs, l\'algorithme préserve strictement la dernière propriété déclarée. Cela garantit que votre mise en page originale ne se casse pas lors de la purge du document.',
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'paragraph',
|
|
164
|
+
html: 'Fini d\'envoyer des kilooctets de texte mort aux téléphones mobiles de vos utilisateurs. Unifiez votre code en millisecondes entièrement hors ligne depuis votre navigateur.',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DeveloperToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
|
|
2
|
+
import DuplicateCssRemoverComponent from './component.astro';
|
|
3
|
+
import DuplicateCssRemoverSEO from './seo.astro';
|
|
4
|
+
import DuplicateCssRemoverBibliography from './bibliography.astro';
|
|
5
|
+
|
|
6
|
+
import type { DuplicateCssRemoverUI } from './ui';
|
|
7
|
+
|
|
8
|
+
export type DuplicateCssRemoverLocaleContent = ToolLocaleContent<DuplicateCssRemoverUI>;
|
|
9
|
+
|
|
10
|
+
import { content as es } from './i18n/es';
|
|
11
|
+
import { content as en } from './i18n/en';
|
|
12
|
+
import { content as fr } from './i18n/fr';
|
|
13
|
+
|
|
14
|
+
export const duplicateCssRemover: DeveloperToolEntry<DuplicateCssRemoverUI> = {
|
|
15
|
+
id: 'duplicate-css-remover',
|
|
16
|
+
icons: {
|
|
17
|
+
bg: 'mdi:broom',
|
|
18
|
+
fg: 'mdi:language-css3',
|
|
19
|
+
},
|
|
20
|
+
i18n: {
|
|
21
|
+
es: async () => es,
|
|
22
|
+
en: async () => en,
|
|
23
|
+
fr: async () => fr,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { DuplicateCssRemoverComponent, DuplicateCssRemoverSEO, DuplicateCssRemoverBibliography };
|
|
28
|
+
|
|
29
|
+
export const DUPLICATE_CSS_REMOVER_TOOL: ToolDefinition = {
|
|
30
|
+
entry: duplicateCssRemover,
|
|
31
|
+
Component: DuplicateCssRemoverComponent,
|
|
32
|
+
SEOComponent: DuplicateCssRemoverSEO,
|
|
33
|
+
BibliographyComponent: DuplicateCssRemoverBibliography,
|
|
34
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { duplicateCssRemover } 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 duplicateCssRemover.i18n[locale]?.();
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{content && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface DuplicateCssRemoverUI extends Record<string, string> {
|
|
2
|
+
labelInput: string;
|
|
3
|
+
labelOutput: string;
|
|
4
|
+
placeholderInput: string;
|
|
5
|
+
placeholderOutput: string;
|
|
6
|
+
btnClean: string;
|
|
7
|
+
btnCopy: string;
|
|
8
|
+
btnCopied: string;
|
|
9
|
+
statBytesOriginal: string;
|
|
10
|
+
statBytesClean: string;
|
|
11
|
+
statSaving: string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Bibliography as SharedBibliography } 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 && <SharedBibliography links={content.bibliography} />}
|