@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,381 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { KnownLocale } from '../../types';
|
|
3
|
+
import type { SvgToCssUI } from './ui';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
locale?: KnownLocale;
|
|
7
|
+
ui?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { ui } = Astro.props;
|
|
11
|
+
const t = (ui ?? {}) as SvgToCssUI;
|
|
12
|
+
|
|
13
|
+
const defaultSvg = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/><path d="M12 8v8M8 12h8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>`;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class="stc-container"
|
|
18
|
+
data-btn-copy={t.btnCopy}
|
|
19
|
+
data-btn-copied={t.btnCopied}
|
|
20
|
+
>
|
|
21
|
+
<div class="stc-grid">
|
|
22
|
+
<div class="stc-card">
|
|
23
|
+
<div class="stc-title-group">
|
|
24
|
+
<div class="stc-icon-box">
|
|
25
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
26
|
+
<path d="m5 16s1 1 4 1 4-1 4-1"></path>
|
|
27
|
+
<path d="m11 20s1 1 4 1 4-1 4-1"></path>
|
|
28
|
+
<path d="m17 4s1 1 4 1 4-1 4-1"></path>
|
|
29
|
+
<path d="m3 12s1 1 4 1 4-1 4-1"></path>
|
|
30
|
+
<path d="m9 8s1 1 4 1 4-1 4-1"></path>
|
|
31
|
+
<circle cx="5" cy="16" r="1"></circle>
|
|
32
|
+
<circle cx="11" cy="20" r="1"></circle>
|
|
33
|
+
<circle cx="17" cy="4" r="1"></circle>
|
|
34
|
+
<circle cx="3" cy="12" r="1"></circle>
|
|
35
|
+
<circle cx="9" cy="8" r="1"></circle>
|
|
36
|
+
</svg>
|
|
37
|
+
</div>
|
|
38
|
+
<h2 class="stc-card-title">{t.labelPasteTitle}</h2>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<span class="stc-area-label">{t.labelInputArea}</span>
|
|
42
|
+
<textarea id="stc-input" class="stc-textarea" placeholder={t.placeholder}>{defaultSvg}</textarea>
|
|
43
|
+
|
|
44
|
+
<span class="stc-area-label">{t.labelPreviewOriginal}</span>
|
|
45
|
+
<div class="stc-preview-container">
|
|
46
|
+
<div class="stc-preview-bg"></div>
|
|
47
|
+
<div id="stc-preview-original" class="stc-preview-img"></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="stc-card">
|
|
52
|
+
<div class="stc-title-group">
|
|
53
|
+
<div class="stc-icon-box">
|
|
54
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
55
|
+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
56
|
+
<polyline points="7 10 12 15 17 10"></polyline>
|
|
57
|
+
<line x1="12" x2="12" y1="3" y2="15"></line>
|
|
58
|
+
</svg>
|
|
59
|
+
</div>
|
|
60
|
+
<h2 class="stc-card-title">{t.labelResultTitle}</h2>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="stc-output-tabs">
|
|
64
|
+
<button class="stc-tab-btn active" data-type="background">{t.tabBackground}</button>
|
|
65
|
+
<button class="stc-tab-btn" data-type="mask">{t.tabMask}</button>
|
|
66
|
+
<button class="stc-tab-btn" data-type="uri">{t.tabUri}</button>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div class="stc-result-box">
|
|
70
|
+
<button id="stc-copy" class="stc-copy-btn">{t.btnCopy}</button>
|
|
71
|
+
<textarea id="stc-output" class="stc-textarea" readonly></textarea>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<span class="stc-area-label">{t.labelPreviewApplied}</span>
|
|
75
|
+
<div class="stc-preview-container">
|
|
76
|
+
<div class="stc-preview-bg"></div>
|
|
77
|
+
<div id="stc-preview-applied" class="stc-preview-applied"></div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<style>
|
|
84
|
+
.stc-container {
|
|
85
|
+
--stc-primary: #ec4899;
|
|
86
|
+
--stc-secondary: #8b5cf6;
|
|
87
|
+
--stc-card-bg: #fff;
|
|
88
|
+
--stc-text: #0f172a;
|
|
89
|
+
--stc-text-muted: #64748b;
|
|
90
|
+
--stc-border: #e2e8f0;
|
|
91
|
+
--stc-input-bg: #f1f5f9;
|
|
92
|
+
--stc-shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
93
|
+
|
|
94
|
+
max-width: 1000px;
|
|
95
|
+
margin: 4rem auto;
|
|
96
|
+
color: var(--stc-text);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
:global(.theme-dark) .stc-container {
|
|
100
|
+
--stc-card-bg: #1e293b;
|
|
101
|
+
--stc-text: #f8fafc;
|
|
102
|
+
--stc-text-muted: #94a3b8;
|
|
103
|
+
--stc-border: #334155;
|
|
104
|
+
--stc-input-bg: #0f172a;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.stc-grid {
|
|
108
|
+
display: grid;
|
|
109
|
+
grid-template-columns: 1fr;
|
|
110
|
+
gap: 2rem;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@media (min-width: 850px) {
|
|
114
|
+
.stc-grid {
|
|
115
|
+
grid-template-columns: 1fr 1fr;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.stc-card {
|
|
120
|
+
background: var(--stc-card-bg);
|
|
121
|
+
border: 1px solid var(--stc-border);
|
|
122
|
+
border-radius: 1.5rem;
|
|
123
|
+
padding: 2.5rem;
|
|
124
|
+
box-shadow: var(--stc-shadow-lg);
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-direction: column;
|
|
127
|
+
gap: 1.5rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.stc-title-group {
|
|
131
|
+
display: flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
gap: 0.75rem;
|
|
134
|
+
margin-bottom: 0.5rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.stc-icon-box {
|
|
138
|
+
width: 40px;
|
|
139
|
+
height: 40px;
|
|
140
|
+
background: linear-gradient(135deg, var(--stc-primary), var(--stc-secondary));
|
|
141
|
+
border-radius: 0.75rem;
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
justify-content: center;
|
|
145
|
+
color: white;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.stc-card-title {
|
|
149
|
+
font-size: 1.5rem;
|
|
150
|
+
font-weight: 800;
|
|
151
|
+
margin: 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.stc-area-label {
|
|
155
|
+
font-size: 0.875rem;
|
|
156
|
+
font-weight: 700;
|
|
157
|
+
color: var(--stc-primary);
|
|
158
|
+
text-transform: uppercase;
|
|
159
|
+
letter-spacing: 0.05em;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.stc-textarea {
|
|
163
|
+
width: 100%;
|
|
164
|
+
min-height: 250px;
|
|
165
|
+
background: var(--stc-input-bg);
|
|
166
|
+
border: 2px solid var(--stc-border);
|
|
167
|
+
border-radius: 1rem;
|
|
168
|
+
padding: 1.25rem;
|
|
169
|
+
font-size: 0.9rem;
|
|
170
|
+
color: var(--stc-text);
|
|
171
|
+
outline: none;
|
|
172
|
+
resize: vertical;
|
|
173
|
+
transition: all 0.2s;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.stc-textarea:focus {
|
|
177
|
+
border-color: var(--stc-primary);
|
|
178
|
+
box-shadow: 0 0 0 4px rgba(236, 72, 153, 0.1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.stc-result-box {
|
|
182
|
+
position: relative;
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-direction: column;
|
|
185
|
+
gap: 1rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.stc-copy-btn {
|
|
189
|
+
position: absolute;
|
|
190
|
+
top: 0.5rem;
|
|
191
|
+
right: 0.5rem;
|
|
192
|
+
background: var(--stc-primary);
|
|
193
|
+
color: white;
|
|
194
|
+
border: none;
|
|
195
|
+
padding: 0.5rem 1rem;
|
|
196
|
+
border-radius: 0.75rem;
|
|
197
|
+
font-size: 0.75rem;
|
|
198
|
+
font-weight: 700;
|
|
199
|
+
cursor: pointer;
|
|
200
|
+
transition: all 0.2s;
|
|
201
|
+
z-index: 1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.stc-copy-btn:hover {
|
|
205
|
+
transform: translateY(-2px);
|
|
206
|
+
box-shadow: 0 4px 12px rgba(236, 72, 153, 0.3);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.stc-preview-container {
|
|
210
|
+
background: var(--stc-input-bg);
|
|
211
|
+
border: 2px dashed var(--stc-border);
|
|
212
|
+
border-radius: 1rem;
|
|
213
|
+
height: 120px;
|
|
214
|
+
display: flex;
|
|
215
|
+
align-items: center;
|
|
216
|
+
justify-content: center;
|
|
217
|
+
margin-top: 1rem;
|
|
218
|
+
position: relative;
|
|
219
|
+
overflow: hidden;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.stc-preview-bg {
|
|
223
|
+
position: absolute;
|
|
224
|
+
inset: 0;
|
|
225
|
+
background-image:
|
|
226
|
+
linear-gradient(45deg, var(--stc-border) 25%, transparent 25%),
|
|
227
|
+
linear-gradient(-45deg, var(--stc-border) 25%, transparent 25%),
|
|
228
|
+
linear-gradient(45deg, transparent 75%, var(--stc-border) 75%),
|
|
229
|
+
linear-gradient(-45deg, transparent 75%, var(--stc-border) 75%);
|
|
230
|
+
background-size: 20px 20px;
|
|
231
|
+
background-position:
|
|
232
|
+
0 0,
|
|
233
|
+
0 10px,
|
|
234
|
+
10px -10px,
|
|
235
|
+
-10px 0;
|
|
236
|
+
opacity: 0.1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.stc-preview-img {
|
|
240
|
+
max-width: 80px;
|
|
241
|
+
max-height: 80px;
|
|
242
|
+
z-index: 1;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.stc-preview-applied {
|
|
246
|
+
width: 60px;
|
|
247
|
+
height: 60px;
|
|
248
|
+
z-index: 1;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.stc-output-tabs {
|
|
252
|
+
display: flex;
|
|
253
|
+
gap: 0.5rem;
|
|
254
|
+
background: var(--stc-input-bg);
|
|
255
|
+
padding: 0.3rem;
|
|
256
|
+
border-radius: 0.75rem;
|
|
257
|
+
margin-bottom: 0.5rem;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.stc-tab-btn {
|
|
261
|
+
flex: 1;
|
|
262
|
+
border: none;
|
|
263
|
+
background: transparent;
|
|
264
|
+
padding: 0.6rem;
|
|
265
|
+
border-radius: 0.5rem;
|
|
266
|
+
font-size: 0.8rem;
|
|
267
|
+
font-weight: 700;
|
|
268
|
+
color: var(--stc-text-muted);
|
|
269
|
+
cursor: pointer;
|
|
270
|
+
transition: all 0.2s;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
:global(.stc-tab-btn.active) {
|
|
274
|
+
background: var(--stc-card-bg);
|
|
275
|
+
color: var(--stc-primary);
|
|
276
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
277
|
+
}
|
|
278
|
+
</style>
|
|
279
|
+
|
|
280
|
+
<script>
|
|
281
|
+
const container = document.querySelector('.stc-container') as HTMLElement | null;
|
|
282
|
+
const input = document.getElementById('stc-input') as HTMLTextAreaElement | null;
|
|
283
|
+
const output = document.getElementById('stc-output') as HTMLTextAreaElement | null;
|
|
284
|
+
const copyBtn = document.getElementById('stc-copy');
|
|
285
|
+
const previewOriginal = document.getElementById('stc-preview-original');
|
|
286
|
+
const previewApplied = document.getElementById('stc-preview-applied');
|
|
287
|
+
const tabBtns = document.querySelectorAll<HTMLButtonElement>('.stc-tab-btn');
|
|
288
|
+
|
|
289
|
+
const btnCopy = container?.dataset.btnCopy ?? 'Copy';
|
|
290
|
+
const btnCopied = container?.dataset.btnCopied ?? 'Copied!';
|
|
291
|
+
|
|
292
|
+
let currentType = 'background';
|
|
293
|
+
|
|
294
|
+
function cleanSvg(svg: string): string {
|
|
295
|
+
return svg
|
|
296
|
+
.trim()
|
|
297
|
+
.replace(/\r?\n|\r/g, '')
|
|
298
|
+
.replace(/>\s+</g, '><')
|
|
299
|
+
.replace(/\s{2,}/g, ' ');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function encodeSvg(svg: string): string {
|
|
303
|
+
return svg
|
|
304
|
+
.replace(/"/g, "'")
|
|
305
|
+
.replace(/%/g, '%25')
|
|
306
|
+
.replace(/#/g, '%23')
|
|
307
|
+
.replace(/{/g, '%7B')
|
|
308
|
+
.replace(/}/g, '%7D')
|
|
309
|
+
.replace(/</g, '%3C')
|
|
310
|
+
.replace(/>/g, '%3E');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function applyBackground(dataUri: string): void {
|
|
314
|
+
if (!previewApplied) return;
|
|
315
|
+
previewApplied.style.backgroundImage = `url("${dataUri}")`;
|
|
316
|
+
previewApplied.style.maskImage = 'none';
|
|
317
|
+
(previewApplied.style as CSSStyleDeclaration & { webkitMaskImage: string }).webkitMaskImage = 'none';
|
|
318
|
+
previewApplied.style.backgroundColor = 'transparent';
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function applyMask(dataUri: string): void {
|
|
322
|
+
if (!previewApplied) return;
|
|
323
|
+
const style = previewApplied.style as CSSStyleDeclaration & {
|
|
324
|
+
webkitMaskImage: string;
|
|
325
|
+
webkitMaskRepeat: string;
|
|
326
|
+
webkitMaskSize: string;
|
|
327
|
+
};
|
|
328
|
+
previewApplied.style.backgroundImage = 'none';
|
|
329
|
+
previewApplied.style.maskImage = `url("${dataUri}")`;
|
|
330
|
+
style.webkitMaskImage = `url("${dataUri}")`;
|
|
331
|
+
previewApplied.style.maskRepeat = 'no-repeat';
|
|
332
|
+
previewApplied.style.maskSize = 'contain';
|
|
333
|
+
style.webkitMaskRepeat = 'no-repeat';
|
|
334
|
+
style.webkitMaskSize = 'contain';
|
|
335
|
+
previewApplied.style.backgroundColor = '#ec4899';
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function generateOutput(): void {
|
|
339
|
+
if (!input || !output || !previewOriginal || !previewApplied) return;
|
|
340
|
+
|
|
341
|
+
const raw = input.value;
|
|
342
|
+
const cleaned = cleanSvg(raw);
|
|
343
|
+
const encoded = encodeSvg(cleaned);
|
|
344
|
+
const dataUri = `data:image/svg+xml,${encoded}`;
|
|
345
|
+
|
|
346
|
+
previewOriginal.innerHTML = cleaned;
|
|
347
|
+
|
|
348
|
+
if (currentType === 'background') {
|
|
349
|
+
output.value = `background-image: url("${dataUri}");`;
|
|
350
|
+
applyBackground(dataUri);
|
|
351
|
+
} else if (currentType === 'mask') {
|
|
352
|
+
output.value = `mask-image: url("${dataUri}");\n-webkit-mask-image: url("${dataUri}");\nmask-repeat: no-repeat;\nmask-size: contain;\nbackground-color: currentColor;`;
|
|
353
|
+
applyMask(dataUri);
|
|
354
|
+
} else {
|
|
355
|
+
output.value = dataUri;
|
|
356
|
+
applyBackground(dataUri);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
input?.addEventListener('input', generateOutput);
|
|
361
|
+
|
|
362
|
+
tabBtns.forEach((btn) => {
|
|
363
|
+
btn.addEventListener('click', () => {
|
|
364
|
+
tabBtns.forEach((b) => b.classList.remove('active'));
|
|
365
|
+
btn.classList.add('active');
|
|
366
|
+
currentType = btn.dataset.type ?? 'background';
|
|
367
|
+
generateOutput();
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
copyBtn?.addEventListener('click', async () => {
|
|
372
|
+
if (!output) return;
|
|
373
|
+
await navigator.clipboard.writeText(output.value);
|
|
374
|
+
copyBtn.textContent = btnCopied;
|
|
375
|
+
setTimeout(() => {
|
|
376
|
+
copyBtn.textContent = btnCopy;
|
|
377
|
+
}, 2000);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
generateOutput();
|
|
381
|
+
</script>
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { SvgToCssUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'svg-to-css-converter';
|
|
6
|
+
const title = 'Free Online SVG to CSS and Data URI Converter';
|
|
7
|
+
const description =
|
|
8
|
+
'Transform your SVG icons and vectors into CSS code (Background or Mask) or compressed Data URI. Optimise your website performance by eliminating external HTTP requests.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Is it better to use a Data URI or an external .svg file?',
|
|
13
|
+
answer:
|
|
14
|
+
'It depends on the use case. Data URIs eliminate HTTP requests (ideal for small icons), but increase CSS file size. For large or detail-rich illustrations, an external file is preferable.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'How do I change the colour of an SVG embedded in CSS?',
|
|
18
|
+
answer:
|
|
19
|
+
"The best way is via 'mask-image'. By defining the SVG as a mask, you can use 'background-color' to change its colour dynamically, even in :hover states.",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Which browsers support CSS Masks?',
|
|
23
|
+
answer:
|
|
24
|
+
'All modern browsers (Chrome, Firefox, Safari, Edge) have full support. For older browsers, -webkit- prefixes are commonly used.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'Does using Data URIs affect SEO?',
|
|
28
|
+
answer:
|
|
29
|
+
'Yes, positively. By reducing the number of requests needed to render the page, it improves load time (LCP) and Core Web Vitals scores.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
question: 'Can I use it in frameworks like React or Tailwind?',
|
|
33
|
+
answer:
|
|
34
|
+
'Absolutely! You can copy the generated code and use it in your .css files or even as arbitrary values in Tailwind CSS.',
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const howToData = [
|
|
39
|
+
{
|
|
40
|
+
name: 'Paste the SVG',
|
|
41
|
+
text: 'Copy the source code of your SVG file and paste it into the text area on the left.',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'Choose the output type',
|
|
45
|
+
text: 'Select between Background Image (for static backgrounds), CSS Mask (for icons with dynamic colour) or Data URI Only (for direct use).',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'Copy the result',
|
|
49
|
+
text: 'Click "Copy" to bring the generated CSS code to your clipboard.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Apply in your project',
|
|
53
|
+
text: 'Paste the code into your stylesheet or CSS component. For Masks, also add background-color to define the icon colour.',
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
58
|
+
'@context': 'https://schema.org',
|
|
59
|
+
'@type': 'FAQPage',
|
|
60
|
+
mainEntity: faqData.map((item) => ({
|
|
61
|
+
'@type': 'Question',
|
|
62
|
+
name: item.question,
|
|
63
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
64
|
+
})),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const howToSchema: WithContext<HowToThing> = {
|
|
68
|
+
'@context': 'https://schema.org',
|
|
69
|
+
'@type': 'HowTo',
|
|
70
|
+
name: title,
|
|
71
|
+
description,
|
|
72
|
+
step: howToData.map((step, i) => ({
|
|
73
|
+
'@type': 'HowToStep',
|
|
74
|
+
position: i + 1,
|
|
75
|
+
name: step.name,
|
|
76
|
+
text: step.text,
|
|
77
|
+
})),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
81
|
+
'@context': 'https://schema.org',
|
|
82
|
+
'@type': 'SoftwareApplication',
|
|
83
|
+
name: title,
|
|
84
|
+
description,
|
|
85
|
+
applicationCategory: 'UtilityApplication',
|
|
86
|
+
operatingSystem: 'All',
|
|
87
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
88
|
+
inLanguage: 'en',
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const ui: SvgToCssUI = {
|
|
92
|
+
labelPasteTitle: 'Paste SVG',
|
|
93
|
+
labelInputArea: 'SVG Source Code',
|
|
94
|
+
labelPreviewOriginal: 'Original Preview',
|
|
95
|
+
labelResultTitle: 'CSS Result',
|
|
96
|
+
labelPreviewApplied: 'Applied Result',
|
|
97
|
+
tabBackground: 'Background Image',
|
|
98
|
+
tabMask: 'CSS Mask / Webkit',
|
|
99
|
+
tabUri: 'Data URI Only',
|
|
100
|
+
btnCopy: 'Copy',
|
|
101
|
+
btnCopied: 'Copied!',
|
|
102
|
+
placeholder: '<svg xmlns="http://www.w3.org/2000/svg" ...',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const content: ToolLocaleContent<SvgToCssUI> = {
|
|
106
|
+
slug,
|
|
107
|
+
title,
|
|
108
|
+
description,
|
|
109
|
+
ui,
|
|
110
|
+
faqTitle: 'Frequently Asked Questions',
|
|
111
|
+
faq: faqData,
|
|
112
|
+
bibliographyTitle: 'References and Documentation',
|
|
113
|
+
bibliography: [
|
|
114
|
+
{
|
|
115
|
+
name: 'CSS-Tricks: Using SVG as Background',
|
|
116
|
+
url: 'https://css-tricks.com/using-svg/',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'MDN Web Docs: mask-image',
|
|
120
|
+
url: 'https://developer.mozilla.org/en-US/docs/Web/CSS/mask-image',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'MDN Web Docs: background-image',
|
|
124
|
+
url: 'https://developer.mozilla.org/en-US/docs/Web/CSS/background-image',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'W3C: CSS Masking Module Level 1',
|
|
128
|
+
url: 'https://www.w3.org/TR/css-masking-1/',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
howTo: howToData,
|
|
132
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
133
|
+
seo: [
|
|
134
|
+
{
|
|
135
|
+
type: 'title',
|
|
136
|
+
text: 'Why Convert SVG to CSS Data URI?',
|
|
137
|
+
level: 2,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: 'paragraph',
|
|
141
|
+
html: 'In modern web development, optimising performance and resource loading is essential. Embedding icons directly in CSS via <strong>Data URIs</strong> eliminates unnecessary HTTP requests, reducing latency and improving Time to Interactive (TTI).',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: 'paragraph',
|
|
145
|
+
html: 'This tool transforms <code><svg></code> vector code into an encoded text string that the browser can interpret as a background image or a clipping mask, maintaining infinite scalability and the sharpness characteristic of vectors.',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: 'title',
|
|
149
|
+
text: 'Key Technical Benefits',
|
|
150
|
+
level: 3,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
type: 'list',
|
|
154
|
+
items: [
|
|
155
|
+
'<strong>Zero HTTP Requests:</strong> By embedding the graphic in your <code>.css</code> files, the browser does not need to download additional external files.',
|
|
156
|
+
'<strong>Customisation via CSS Mask:</strong> Using the <code>mask-image</code> technique, you can change the colour of a complex vector icon simply by using <code>background-color</code>.',
|
|
157
|
+
'<strong>Immediate Rendering:</strong> You avoid content flicker (FOUC) since critical visual resources are available as soon as the stylesheet is downloaded.',
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'title',
|
|
162
|
+
text: 'CSS Masks vs Backgrounds',
|
|
163
|
+
level: 3,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
type: 'paragraph',
|
|
167
|
+
html: 'Many developers simply use <code>background-image</code> to embed vectors, but this has a limitation: you cannot change the SVG colour dynamically from CSS.',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'paragraph',
|
|
171
|
+
html: 'Our utility supports code generation for <strong>CSS Masks</strong>. By applying a <code>mask-image</code> with the generated Data URI, the icon acts as a stencil, allowing the <code>background-color</code> of the element to define the final icon colour. It is the most professional and flexible way to manage icons in Astro, Next.js or any modern framework.',
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|