@jjlmoya/utils-developer 1.30.0 → 1.32.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.
Files changed (187) hide show
  1. package/package.json +70 -70
  2. package/src/category/i18n/en.ts +1 -1
  3. package/src/category/i18n/es.ts +1 -1
  4. package/src/category/index.ts +2 -1
  5. package/src/category/seo.astro +1 -1
  6. package/src/components/PreviewNavSidebar.astro +1 -1
  7. package/src/components/PreviewToolbar.astro +1 -1
  8. package/src/data.ts +1 -1
  9. package/src/entries.ts +2 -0
  10. package/src/env.d.ts +1 -1
  11. package/src/index.ts +1 -0
  12. package/src/layouts/PreviewLayout.astro +1 -1
  13. package/src/pages/[locale]/[slug].astro +161 -161
  14. package/src/pages/index.astro +1 -1
  15. package/src/tests/bibliography_wellformed_export.test.ts +46 -0
  16. package/src/tests/category_seo_quality.test.ts +76 -0
  17. package/src/tests/entry_contract.test.ts +8 -2
  18. package/src/tests/faq_count.test.ts +1 -1
  19. package/src/tests/i18n_coverage.test.ts +2 -6
  20. package/src/tests/inverted_punctuation.test.ts +113 -113
  21. package/src/tests/locale_completeness.test.ts +1 -1
  22. package/src/tests/mocks/astro_mock.js +1 -1
  23. package/src/tests/no_h1_in_components.test.ts +1 -1
  24. package/src/tests/promote_this_website_i18n.test.ts +33 -0
  25. package/src/tests/seo_translation_completeness.test.ts +69 -0
  26. package/src/tests/seo_wellformed_export.test.ts +65 -0
  27. package/src/tests/slug_language_code_format.test.ts +25 -25
  28. package/src/tests/slug_uniqueness.test.ts +86 -86
  29. package/src/tests/tool_validation.test.ts +16 -16
  30. package/src/tool/aspectRatio/i18n/de.ts +164 -164
  31. package/src/tool/aspectRatio/i18n/ja.ts +1 -1
  32. package/src/tool/aspectRatio/i18n/ko.ts +1 -1
  33. package/src/tool/aspectRatio/i18n/pl.ts +164 -164
  34. package/src/tool/aspectRatio/i18n/ru.ts +164 -164
  35. package/src/tool/aspectRatio/i18n/zh.ts +165 -165
  36. package/src/tool/aspectRatio/seo.astro +15 -15
  37. package/src/tool/calculadoraTiempoDatos/i18n/de.ts +143 -143
  38. package/src/tool/calculadoraTiempoDatos/i18n/ja.ts +1 -1
  39. package/src/tool/calculadoraTiempoDatos/i18n/ko.ts +1 -1
  40. package/src/tool/calculadoraTiempoDatos/i18n/pl.ts +143 -143
  41. package/src/tool/calculadoraTiempoDatos/i18n/ru.ts +144 -144
  42. package/src/tool/calculadoraTiempoDatos/i18n/sv.ts +143 -143
  43. package/src/tool/calculadoraTiempoDatos/i18n/zh.ts +144 -144
  44. package/src/tool/calculadoraTiempoDatos/seo.astro +15 -15
  45. package/src/tool/colorConverter/i18n/de.ts +120 -120
  46. package/src/tool/colorConverter/i18n/ja.ts +1 -1
  47. package/src/tool/colorConverter/i18n/ko.ts +1 -1
  48. package/src/tool/colorConverter/i18n/ru.ts +120 -120
  49. package/src/tool/colorConverter/i18n/zh.ts +1 -1
  50. package/src/tool/colorConverter/seo.astro +15 -15
  51. package/src/tool/conversorExcelCsvHtml/i18n/ja.ts +1 -1
  52. package/src/tool/conversorExcelCsvHtml/i18n/ko.ts +1 -1
  53. package/src/tool/conversorExcelCsvHtml/i18n/pl.ts +124 -124
  54. package/src/tool/conversorExcelCsvHtml/i18n/ru.ts +124 -124
  55. package/src/tool/conversorExcelCsvHtml/i18n/zh.ts +125 -125
  56. package/src/tool/conversorExcelCsvHtml/seo.astro +15 -15
  57. package/src/tool/cronGenerator/i18n/ja.ts +1 -1
  58. package/src/tool/cronGenerator/i18n/ko.ts +1 -1
  59. package/src/tool/cronGenerator/i18n/zh.ts +183 -183
  60. package/src/tool/cronGenerator/seo.astro +15 -15
  61. package/src/tool/cssSpecificityCalculator/i18n/ja.ts +1 -1
  62. package/src/tool/cssSpecificityCalculator/i18n/ko.ts +1 -1
  63. package/src/tool/cssSpecificityCalculator/i18n/zh.ts +1 -1
  64. package/src/tool/cssSpecificityCalculator/seo.astro +15 -15
  65. package/src/tool/cssToInlineConverter/i18n/ja.ts +1 -1
  66. package/src/tool/cssToInlineConverter/i18n/ko.ts +1 -1
  67. package/src/tool/cssToInlineConverter/i18n/zh.ts +1 -1
  68. package/src/tool/cssToInlineConverter/seo.astro +15 -15
  69. package/src/tool/dualOsIconPreview/assets/day-check.webp +0 -0
  70. package/src/tool/dualOsIconPreview/assets/fast-task.webp +0 -0
  71. package/src/tool/dualOsIconPreview/assets/fortune-cookie.webp +0 -0
  72. package/src/tool/dualOsIconPreview/assets/lexi-crash.webp +0 -0
  73. package/src/tool/dualOsIconPreview/assets/pizzametrics.webp +0 -0
  74. package/src/tool/dualOsIconPreview/assets/sauce-lab.webp +0 -0
  75. package/src/tool/dualOsIconPreview/assets/vesp.webp +0 -0
  76. package/src/tool/dualOsIconPreview/bibliography.astro +6 -0
  77. package/src/tool/dualOsIconPreview/bibliography.ts +7 -0
  78. package/src/tool/dualOsIconPreview/component.astro +117 -0
  79. package/src/tool/dualOsIconPreview/controller.ts +157 -0
  80. package/src/tool/dualOsIconPreview/dom-views.ts +82 -0
  81. package/src/tool/dualOsIconPreview/dual-ios-android-app-icon-preview.css +861 -0
  82. package/src/tool/dualOsIconPreview/entry.ts +31 -0
  83. package/src/tool/dualOsIconPreview/evaluator.ts +20 -0
  84. package/src/tool/dualOsIconPreview/i18n/de.ts +56 -0
  85. package/src/tool/dualOsIconPreview/i18n/en.ts +46 -0
  86. package/src/tool/dualOsIconPreview/i18n/es.ts +56 -0
  87. package/src/tool/dualOsIconPreview/i18n/fr.ts +56 -0
  88. package/src/tool/dualOsIconPreview/i18n/id.ts +56 -0
  89. package/src/tool/dualOsIconPreview/i18n/it.ts +56 -0
  90. package/src/tool/dualOsIconPreview/i18n/ja.ts +56 -0
  91. package/src/tool/dualOsIconPreview/i18n/ko.ts +56 -0
  92. package/src/tool/dualOsIconPreview/i18n/nl.ts +56 -0
  93. package/src/tool/dualOsIconPreview/i18n/pl.ts +56 -0
  94. package/src/tool/dualOsIconPreview/i18n/pt.ts +56 -0
  95. package/src/tool/dualOsIconPreview/i18n/ru.ts +56 -0
  96. package/src/tool/dualOsIconPreview/i18n/sv.ts +56 -0
  97. package/src/tool/dualOsIconPreview/i18n/tr.ts +43 -0
  98. package/src/tool/dualOsIconPreview/i18n/zh.ts +43 -0
  99. package/src/tool/dualOsIconPreview/index.ts +11 -0
  100. package/src/tool/dualOsIconPreview/logic.test.ts +63 -0
  101. package/src/tool/dualOsIconPreview/logic.ts +135 -0
  102. package/src/tool/dualOsIconPreview/seo.astro +15 -0
  103. package/src/tool/dualOsIconPreview/storage.ts +18 -0
  104. package/src/tool/dualOsIconPreview/ui.ts +52 -0
  105. package/src/tool/duplicateCssRemover/i18n/ja.ts +1 -1
  106. package/src/tool/duplicateCssRemover/i18n/ko.ts +1 -1
  107. package/src/tool/duplicateCssRemover/i18n/zh.ts +1 -1
  108. package/src/tool/duplicateCssRemover/seo.astro +15 -15
  109. package/src/tool/generadorSecurityTxt/i18n/ja.ts +1 -1
  110. package/src/tool/generadorSecurityTxt/i18n/ko.ts +1 -1
  111. package/src/tool/generadorSecurityTxt/i18n/zh.ts +1 -1
  112. package/src/tool/generadorSecurityTxt/seo.astro +15 -15
  113. package/src/tool/hashGenerator/i18n/ja.ts +1 -1
  114. package/src/tool/hashGenerator/i18n/ko.ts +1 -1
  115. package/src/tool/hashGenerator/seo.astro +15 -15
  116. package/src/tool/inspectorCertificadosSsl/i18n/ja.ts +1 -1
  117. package/src/tool/inspectorCertificadosSsl/i18n/ko.ts +1 -1
  118. package/src/tool/inspectorCertificadosSsl/i18n/zh.ts +1 -1
  119. package/src/tool/inspectorCertificadosSsl/seo.astro +15 -15
  120. package/src/tool/jsonFormatter/seo.astro +15 -15
  121. package/src/tool/jwtDecoder/i18n/es.ts +248 -248
  122. package/src/tool/jwtDecoder/i18n/fr.ts +248 -248
  123. package/src/tool/jwtDecoder/i18n/tr.ts +248 -248
  124. package/src/tool/keycode/seo.astro +15 -15
  125. package/src/tool/llmCostCalculator/i18n/fr.ts +149 -149
  126. package/src/tool/llmCostCalculator/i18n/ja.ts +1 -1
  127. package/src/tool/llmCostCalculator/i18n/ko.ts +1 -1
  128. package/src/tool/llmCostCalculator/seo.astro +15 -15
  129. package/src/tool/mobileMockupGenerator/i18n/ja.ts +1 -1
  130. package/src/tool/mobileMockupGenerator/i18n/ko.ts +1 -1
  131. package/src/tool/mobileMockupGenerator/i18n/zh.ts +1 -1
  132. package/src/tool/mobileMockupGenerator/seo.astro +15 -15
  133. package/src/tool/musicalTypography/i18n/ja.ts +1 -1
  134. package/src/tool/musicalTypography/i18n/ko.ts +1 -1
  135. package/src/tool/musicalTypography/i18n/zh.ts +1 -1
  136. package/src/tool/musicalTypography/seo.astro +15 -15
  137. package/src/tool/placeholderGenerator/i18n/ja.ts +1 -1
  138. package/src/tool/placeholderGenerator/i18n/ko.ts +1 -1
  139. package/src/tool/placeholderGenerator/i18n/zh.ts +1 -1
  140. package/src/tool/placeholderGenerator/seo.astro +15 -15
  141. package/src/tool/promoteThisWebsite/entry.ts +13 -0
  142. package/src/tool/promoteThisWebsite/i18n/de.ts +95 -0
  143. package/src/tool/promoteThisWebsite/i18n/fr.ts +95 -0
  144. package/src/tool/promoteThisWebsite/i18n/id.ts +95 -0
  145. package/src/tool/promoteThisWebsite/i18n/it.ts +95 -0
  146. package/src/tool/promoteThisWebsite/i18n/ja.ts +95 -0
  147. package/src/tool/promoteThisWebsite/i18n/ko.ts +95 -0
  148. package/src/tool/promoteThisWebsite/i18n/nl.ts +95 -0
  149. package/src/tool/promoteThisWebsite/i18n/pl.ts +95 -0
  150. package/src/tool/promoteThisWebsite/i18n/pt.ts +95 -0
  151. package/src/tool/promoteThisWebsite/i18n/ru.ts +95 -0
  152. package/src/tool/promoteThisWebsite/i18n/sv.ts +95 -0
  153. package/src/tool/promoteThisWebsite/i18n/tr.ts +95 -0
  154. package/src/tool/promoteThisWebsite/i18n/zh.ts +95 -0
  155. package/src/tool/promptLibrary/i18n/ja.ts +1 -1
  156. package/src/tool/promptLibrary/i18n/ko.ts +1 -1
  157. package/src/tool/promptLibrary/i18n/zh.ts +1 -1
  158. package/src/tool/promptLibrary/seo.astro +15 -15
  159. package/src/tool/readabilityCalculator/i18n/ja.ts +1 -1
  160. package/src/tool/readabilityCalculator/i18n/ko.ts +1 -1
  161. package/src/tool/readabilityCalculator/i18n/zh.ts +1 -1
  162. package/src/tool/readabilityCalculator/seo.astro +15 -15
  163. package/src/tool/serpPixelSimulator/entry.ts +30 -30
  164. package/src/tool/serpPixelSimulator/i18n/en.ts +211 -211
  165. package/src/tool/serpPixelSimulator/i18n/fr.ts +214 -214
  166. package/src/tool/serpPixelSimulator/i18n/ru.ts +214 -214
  167. package/src/tool/serpPixelSimulator/logic.ts +18 -18
  168. package/src/tool/serpPixelSimulator/serp-pixel-simulator.css +195 -195
  169. package/src/tool/svgSanitizer/i18n/ja.ts +1 -1
  170. package/src/tool/svgSanitizer/i18n/ko.ts +1 -1
  171. package/src/tool/svgSanitizer/seo.astro +15 -15
  172. package/src/tool/svgToCss/i18n/ja.ts +1 -1
  173. package/src/tool/svgToCss/i18n/ko.ts +1 -1
  174. package/src/tool/svgToCss/seo.astro +15 -15
  175. package/src/tool/urlCleaner/i18n/ja.ts +1 -1
  176. package/src/tool/urlCleaner/i18n/ko.ts +1 -1
  177. package/src/tool/urlCleaner/i18n/zh.ts +1 -1
  178. package/src/tool/urlCleaner/seo.astro +15 -15
  179. package/src/tool/urlEncoderDecoder/i18n/es.ts +146 -146
  180. package/src/tool/urlEncoderDecoder/i18n/ko.ts +1 -1
  181. package/src/tool/urlEncoderDecoder/seo.astro +15 -15
  182. package/src/tool/utmGenerator/i18n/ja.ts +1 -1
  183. package/src/tool/utmGenerator/i18n/ko.ts +1 -1
  184. package/src/tool/utmGenerator/i18n/zh.ts +1 -1
  185. package/src/tool/utmGenerator/seo.astro +15 -15
  186. package/src/tools.ts +2 -1
  187. package/src/types.ts +1 -1
@@ -0,0 +1,135 @@
1
+ export type IosAppearance = 'default' | 'dark' | 'clear' | 'tinted';
2
+ export type AndroidShape = 'circle' | 'squircle' | 'rounded' | 'teardrop';
3
+
4
+ export interface IconPreviewSettings {
5
+ appName: string;
6
+ brandColor: string;
7
+ iosAppearance: IosAppearance;
8
+ androidShape: AndroidShape;
9
+ androidThemed: boolean;
10
+ }
11
+
12
+ export interface IconPreviewState extends IconPreviewSettings {
13
+ hasLogo: boolean;
14
+ audit: LogoAudit | null;
15
+ }
16
+
17
+ export interface LogoAuditMetrics {
18
+ width: number;
19
+ height: number;
20
+ leftMargin: number;
21
+ rightMargin: number;
22
+ topMargin: number;
23
+ bottomMargin: number;
24
+ visiblePixels: number;
25
+ }
26
+
27
+ export interface LogoAudit {
28
+ score: number;
29
+ dimensions: string;
30
+ aspect: string;
31
+ resolution: 'pass' | 'review';
32
+ iosMask: 'pass' | 'review';
33
+ androidSafeZone: 'pass' | 'review';
34
+ transparency: 'transparent' | 'full-bleed';
35
+ minimumMargin: number;
36
+ }
37
+
38
+ export const DEFAULT_SETTINGS: IconPreviewSettings = {
39
+ appName: 'Northstar',
40
+ brandColor: '#f4b942',
41
+ iosAppearance: 'default',
42
+ androidShape: 'squircle',
43
+ androidThemed: false,
44
+ };
45
+
46
+ const APPEARANCES: IosAppearance[] = ['default', 'dark', 'clear', 'tinted'];
47
+ const SHAPES: AndroidShape[] = ['circle', 'squircle', 'rounded', 'teardrop'];
48
+
49
+ export function isIosAppearance(value: string): value is IosAppearance {
50
+ return APPEARANCES.includes(value as IosAppearance);
51
+ }
52
+
53
+ export function isAndroidShape(value: string): value is AndroidShape {
54
+ return SHAPES.includes(value as AndroidShape);
55
+ }
56
+
57
+ export function normaliseAppName(value: string): string {
58
+ const clean = value.trim().replace(/\s+/g, ' ');
59
+ return clean.slice(0, 24);
60
+ }
61
+
62
+ export function isHexColor(value: string): boolean {
63
+ return /^#[0-9a-f]{6}$/i.test(value);
64
+ }
65
+
66
+ function resolveAppName(value: string | undefined): string {
67
+ return normaliseAppName(value ?? DEFAULT_SETTINGS.appName) || DEFAULT_SETTINGS.appName;
68
+ }
69
+
70
+ function resolveBrandColor(value: string | undefined): string {
71
+ return isHexColor(value ?? '') ? value! : DEFAULT_SETTINGS.brandColor;
72
+ }
73
+
74
+ function resolveAppearance(value: string | undefined): IosAppearance {
75
+ return isIosAppearance(value ?? '') ? value as IosAppearance : DEFAULT_SETTINGS.iosAppearance;
76
+ }
77
+
78
+ function resolveShape(value: string | undefined): AndroidShape {
79
+ return isAndroidShape(value ?? '') ? value as AndroidShape : DEFAULT_SETTINGS.androidShape;
80
+ }
81
+
82
+ export function sanitiseSettings(input: Partial<IconPreviewSettings>): IconPreviewSettings {
83
+ return {
84
+ appName: resolveAppName(input.appName),
85
+ brandColor: resolveBrandColor(input.brandColor),
86
+ iosAppearance: resolveAppearance(input.iosAppearance),
87
+ androidShape: resolveShape(input.androidShape),
88
+ androidThemed: input.androidThemed === true,
89
+ };
90
+ }
91
+
92
+ export function buildPreviewState(settings: Partial<IconPreviewSettings>, hasLogo: boolean, audit: LogoAudit | null = null): IconPreviewState {
93
+ return { ...sanitiseSettings(settings), hasLogo, audit };
94
+ }
95
+
96
+ export function getIosSurface(appearance: IosAppearance): string {
97
+ if (appearance === 'dark') return 'dark';
98
+ if (appearance === 'clear') return 'clear';
99
+ if (appearance === 'tinted') return 'tinted';
100
+ return 'light';
101
+ }
102
+
103
+ function isSquare(metrics: LogoAuditMetrics): boolean {
104
+ return metrics.width === metrics.height;
105
+ }
106
+
107
+ function hasGoodResolution(metrics: LogoAuditMetrics): boolean {
108
+ return Math.min(metrics.width, metrics.height) >= 512;
109
+ }
110
+
111
+ function getMinimumMargin(metrics: LogoAuditMetrics): number {
112
+ return Math.min(metrics.leftMargin, metrics.rightMargin, metrics.topMargin, metrics.bottomMargin) / Math.max(metrics.width, metrics.height);
113
+ }
114
+
115
+ function getScore(metrics: LogoAuditMetrics, minimumMargin: number): number {
116
+ const squarePoints = isSquare(metrics) ? 25 : 0;
117
+ const resolutionPoints = hasGoodResolution(metrics) ? 25 : 0;
118
+ const iosPoints = minimumMargin >= 0.1 ? 25 : 0;
119
+ const androidPoints = minimumMargin >= 0.195 ? 25 : 0;
120
+ return squarePoints + resolutionPoints + iosPoints + androidPoints;
121
+ }
122
+
123
+ export function auditLogo(metrics: LogoAuditMetrics): LogoAudit {
124
+ const minimumMargin = getMinimumMargin(metrics);
125
+ return {
126
+ score: getScore(metrics, minimumMargin),
127
+ dimensions: `${metrics.width} x ${metrics.height}`,
128
+ aspect: isSquare(metrics) ? '1:1' : `${metrics.width}:${metrics.height}`,
129
+ resolution: hasGoodResolution(metrics) ? 'pass' : 'review',
130
+ iosMask: minimumMargin >= 0.1 && isSquare(metrics) ? 'pass' : 'review',
131
+ androidSafeZone: minimumMargin >= 0.195 && isSquare(metrics) ? 'pass' : 'review',
132
+ transparency: metrics.visiblePixels < metrics.width * metrics.height ? 'transparent' : 'full-bleed',
133
+ minimumMargin,
134
+ };
135
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { dualOsIconPreview } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'en' } = Astro.props;
11
+ const content = await dualOsIconPreview.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,18 @@
1
+ import type { IconPreviewSettings } from './logic';
2
+
3
+ const STORAGE_KEY = 'jjlmoya:dual-os-icon-preview';
4
+
5
+ export function loadStoredSettings(): Partial<IconPreviewSettings> {
6
+ try {
7
+ const raw = window.localStorage.getItem(STORAGE_KEY);
8
+ return raw ? JSON.parse(raw) as Partial<IconPreviewSettings> : {};
9
+ } catch {
10
+ return {};
11
+ }
12
+ }
13
+
14
+ export function saveStoredSettings(settings: IconPreviewSettings): void {
15
+ try {
16
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
17
+ } catch {}
18
+ }
@@ -0,0 +1,52 @@
1
+ export interface DualOsIconPreviewUI extends Record<string, string> {
2
+ labelUpload: string;
3
+ uploadAction: string;
4
+ uploadHint: string;
5
+ dropHint: string;
6
+ labelAppName: string;
7
+ appNamePlaceholder: string;
8
+ labelBrandColor: string;
9
+ labelIosAppearance: string;
10
+ iosAppearanceHint: string;
11
+ iosDefault: string;
12
+ iosDark: string;
13
+ iosClear: string;
14
+ iosTinted: string;
15
+ labelAndroidShape: string;
16
+ androidShapeHint: string;
17
+ androidCircle: string;
18
+ androidSquircle: string;
19
+ androidRounded: string;
20
+ androidTeardrop: string;
21
+ labelAndroidTheme: string;
22
+ androidThemeHint: string;
23
+ iosDeviceLabel: string;
24
+ androidDeviceLabel: string;
25
+ iosHomeLabel: string;
26
+ androidHomeLabel: string;
27
+ safeZoneLabel: string;
28
+ adaptiveLayerLabel: string;
29
+ monochromeLabel: string;
30
+ nameFallback: string;
31
+ emptyLogo: string;
32
+ fileError: string;
33
+ statusReady: string;
34
+ statusNeedsReview: string;
35
+ stageKicker: string;
36
+ stageNote: string;
37
+ auditTitle: string;
38
+ auditHint: string;
39
+ auditWaiting: string;
40
+ auditNotChecked: string;
41
+ auditFile: string;
42
+ auditAspect: string;
43
+ auditResolution: string;
44
+ auditIosMask: string;
45
+ auditAndroidZone: string;
46
+ auditMargin: string;
47
+ auditTransparency: string;
48
+ auditTransparent: string;
49
+ auditFullBleed: string;
50
+ statusPass: string;
51
+ statusReview: string;
52
+ }
@@ -153,4 +153,4 @@ export const content: ToolLocaleContent<DuplicateCssRemoverUI> = {
153
153
  },
154
154
  ],
155
155
  };
156
-
156
+
@@ -153,4 +153,4 @@ export const content: ToolLocaleContent<DuplicateCssRemoverUI> = {
153
153
  },
154
154
  ],
155
155
  };
156
-
156
+
@@ -153,4 +153,4 @@ export const content: ToolLocaleContent<DuplicateCssRemoverUI> = {
153
153
  },
154
154
  ],
155
155
  };
156
-
156
+
@@ -1,15 +1,15 @@
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
- if (!content) return null;
13
- ---
14
-
15
- {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
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
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -168,4 +168,4 @@ export const content: ToolLocaleContent<GeneradorSecurityTxtUI> = {
168
168
  },
169
169
  ],
170
170
  };
171
-
171
+
@@ -168,4 +168,4 @@ export const content: ToolLocaleContent<GeneradorSecurityTxtUI> = {
168
168
  },
169
169
  ],
170
170
  };
171
-
171
+
@@ -168,4 +168,4 @@ export const content: ToolLocaleContent<GeneradorSecurityTxtUI> = {
168
168
  },
169
169
  ],
170
170
  };
171
-
171
+
@@ -1,15 +1,15 @@
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
- if (!content) return null;
13
- ---
14
-
15
- {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
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
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -113,4 +113,4 @@ export const content: ToolLocaleContent<HashGeneratorUI> = {
113
113
  },
114
114
  ],
115
115
  };
116
-
116
+
@@ -113,4 +113,4 @@ export const content: ToolLocaleContent<HashGeneratorUI> = {
113
113
  },
114
114
  ],
115
115
  };
116
-
116
+
@@ -1,15 +1,15 @@
1
- ---
2
- import { SEORenderer } 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
- if (!content) return null;
13
- ---
14
-
15
- {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
1
+ ---
2
+ import { SEORenderer } 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
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -208,4 +208,4 @@ export const content: ToolLocaleContent<InspectorCertificadosSslUI> = {
208
208
  },
209
209
  ],
210
210
  };
211
-
211
+
@@ -208,4 +208,4 @@ export const content: ToolLocaleContent<InspectorCertificadosSslUI> = {
208
208
  },
209
209
  ],
210
210
  };
211
-
211
+
@@ -208,4 +208,4 @@ export const content: ToolLocaleContent<InspectorCertificadosSslUI> = {
208
208
  },
209
209
  ],
210
210
  };
211
-
211
+
@@ -1,15 +1,15 @@
1
- ---
2
- import { SEORenderer } from '@jjlmoya/utils-shared';
3
- import { inspectorCertificadosSsl } 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 inspectorCertificadosSsl.i18n[locale]?.();
12
- if (!content) return null;
13
- ---
14
-
15
- {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { inspectorCertificadosSsl } 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 inspectorCertificadosSsl.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -1,15 +1,15 @@
1
- ---
2
- import { SEORenderer } from '@jjlmoya/utils-shared';
3
- import { jsonFormatter } 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 jsonFormatter.i18n[locale]?.();
12
- if (!content) return null;
13
- ---
14
-
15
- {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { jsonFormatter } 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 jsonFormatter.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}