@jjlmoya/utils-developer 1.15.0 → 1.17.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 (63) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -1
  3. package/src/entries.ts +7 -1
  4. package/src/index.ts +4 -0
  5. package/src/tests/locale_completeness.test.ts +2 -3
  6. package/src/tests/pagespeed_best_practices.test.ts +198 -0
  7. package/src/tests/tool_validation.test.ts +2 -2
  8. package/src/tool/aspectRatio/component.astro +3 -1
  9. package/src/tool/colorConverter/component.astro +3 -3
  10. package/src/tool/jwtDecoder/bibliography.astro +14 -0
  11. package/src/tool/jwtDecoder/bibliography.ts +12 -0
  12. package/src/tool/jwtDecoder/component.astro +209 -0
  13. package/src/tool/jwtDecoder/entry.ts +30 -0
  14. package/src/tool/jwtDecoder/i18n/de.ts +248 -0
  15. package/src/tool/jwtDecoder/i18n/en.ts +247 -0
  16. package/src/tool/jwtDecoder/i18n/es.ts +248 -0
  17. package/src/tool/jwtDecoder/i18n/fr.ts +248 -0
  18. package/src/tool/jwtDecoder/i18n/id.ts +248 -0
  19. package/src/tool/jwtDecoder/i18n/it.ts +248 -0
  20. package/src/tool/jwtDecoder/i18n/ja.ts +248 -0
  21. package/src/tool/jwtDecoder/i18n/ko.ts +248 -0
  22. package/src/tool/jwtDecoder/i18n/nl.ts +247 -0
  23. package/src/tool/jwtDecoder/i18n/pl.ts +247 -0
  24. package/src/tool/jwtDecoder/i18n/pt.ts +247 -0
  25. package/src/tool/jwtDecoder/i18n/ru.ts +248 -0
  26. package/src/tool/jwtDecoder/i18n/sv.ts +248 -0
  27. package/src/tool/jwtDecoder/i18n/tr.ts +248 -0
  28. package/src/tool/jwtDecoder/i18n/zh.ts +248 -0
  29. package/src/tool/jwtDecoder/index.ts +11 -0
  30. package/src/tool/jwtDecoder/jwt-decoder-parser-and-claims-inspector.css +358 -0
  31. package/src/tool/jwtDecoder/logic.ts +96 -0
  32. package/src/tool/jwtDecoder/seo.astro +15 -0
  33. package/src/tool/jwtDecoder/ui.ts +38 -0
  34. package/src/tool/llmCostCalculator/component.astro +1 -2
  35. package/src/tool/mobileMockupGenerator/component.astro +4 -5
  36. package/src/tool/placeholderGenerator/component.astro +2 -2
  37. package/src/tool/readabilityCalculator/component.astro +4 -4
  38. package/src/tool/serpPixelSimulator/bibliography.astro +14 -0
  39. package/src/tool/serpPixelSimulator/bibliography.ts +16 -0
  40. package/src/tool/serpPixelSimulator/component.astro +84 -0
  41. package/src/tool/serpPixelSimulator/controller.ts +323 -0
  42. package/src/tool/serpPixelSimulator/entry.ts +30 -0
  43. package/src/tool/serpPixelSimulator/i18n/de.ts +214 -0
  44. package/src/tool/serpPixelSimulator/i18n/en.ts +213 -0
  45. package/src/tool/serpPixelSimulator/i18n/es.ts +214 -0
  46. package/src/tool/serpPixelSimulator/i18n/fr.ts +214 -0
  47. package/src/tool/serpPixelSimulator/i18n/id.ts +214 -0
  48. package/src/tool/serpPixelSimulator/i18n/it.ts +214 -0
  49. package/src/tool/serpPixelSimulator/i18n/ja.ts +214 -0
  50. package/src/tool/serpPixelSimulator/i18n/ko.ts +214 -0
  51. package/src/tool/serpPixelSimulator/i18n/nl.ts +214 -0
  52. package/src/tool/serpPixelSimulator/i18n/pl.ts +214 -0
  53. package/src/tool/serpPixelSimulator/i18n/pt.ts +214 -0
  54. package/src/tool/serpPixelSimulator/i18n/ru.ts +214 -0
  55. package/src/tool/serpPixelSimulator/i18n/sv.ts +214 -0
  56. package/src/tool/serpPixelSimulator/i18n/tr.ts +214 -0
  57. package/src/tool/serpPixelSimulator/i18n/zh.ts +214 -0
  58. package/src/tool/serpPixelSimulator/index.ts +8 -0
  59. package/src/tool/serpPixelSimulator/logic.ts +18 -0
  60. package/src/tool/serpPixelSimulator/seo.astro +15 -0
  61. package/src/tool/serpPixelSimulator/serp-pixel-simulator.css +335 -0
  62. package/src/tool/serpPixelSimulator/ui.ts +33 -0
  63. package/src/tools.ts +3 -2
@@ -0,0 +1,15 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { serpPixelSimulator } 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 serpPixelSimulator.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,335 @@
1
+ .sps-root {
2
+ --sps-ink: #1f2937;
3
+ --sps-muted: #64748b;
4
+ --sps-line: #d9e2ec;
5
+ --sps-panel: #fff;
6
+ --sps-soft: #f6f8fb;
7
+ --sps-ok: #16875d;
8
+ --sps-warn: #d93025;
9
+
10
+ color: var(--sps-ink);
11
+ }
12
+
13
+ .theme-dark .sps-root {
14
+ --sps-ink: #e5edf7;
15
+ --sps-muted: #a8b5c6;
16
+ --sps-line: #2c3a4e;
17
+ --sps-panel: #111827;
18
+ --sps-soft: #0b1120;
19
+ }
20
+
21
+ .sps-shell {
22
+ display: grid;
23
+ grid-template-columns: minmax(280px, 0.95fr) minmax(320px, 1.05fr);
24
+ gap: 24px;
25
+ align-items: start;
26
+ }
27
+
28
+ .sps-card {
29
+ border: 1px solid var(--sps-line);
30
+ border-radius: 8px;
31
+ background: var(--sps-panel);
32
+ padding: 24px;
33
+ }
34
+
35
+ .sps-panel,
36
+ .sps-preview-wrap {
37
+ min-width: 0;
38
+ }
39
+
40
+ .sps-field {
41
+ display: grid;
42
+ gap: 8px;
43
+ margin-bottom: 18px;
44
+ }
45
+
46
+ .sps-label,
47
+ .sps-device-label,
48
+ .sps-meter-top {
49
+ font-size: 0.86rem;
50
+ font-weight: 700;
51
+ color: #334155;
52
+ }
53
+
54
+ .sps-input,
55
+ .sps-textarea {
56
+ width: 100%;
57
+ box-sizing: border-box;
58
+ border: 1px solid #cbd5e1;
59
+ border-radius: 6px;
60
+ padding: 10px 12px;
61
+ font-size: 15px;
62
+ line-height: 1.45;
63
+ color: #172033;
64
+ background: #fff;
65
+ }
66
+
67
+ .sps-url-control {
68
+ display: flex;
69
+ align-items: stretch;
70
+ width: 100%;
71
+ }
72
+
73
+ .sps-url-input {
74
+ min-width: 0;
75
+ border-top-right-radius: 0;
76
+ border-bottom-right-radius: 0;
77
+ }
78
+
79
+ .sps-fetch-button {
80
+ flex: 0 0 auto;
81
+ border: 1px solid #cbd5e1;
82
+ border-left: 0;
83
+ border-radius: 0 6px 6px 0;
84
+ padding: 0 14px;
85
+ background: #174ea6;
86
+ color: #fff;
87
+ font-size: 0.88rem;
88
+ font-weight: 700;
89
+ line-height: 1;
90
+ cursor: pointer;
91
+ }
92
+
93
+ .sps-fetch-button:disabled {
94
+ cursor: progress;
95
+ opacity: 0.72;
96
+ }
97
+
98
+ .sps-fetch-message {
99
+ min-height: 1.2em;
100
+ margin: 0;
101
+ color: var(--sps-muted);
102
+ font-size: 0.82rem;
103
+ line-height: 1.4;
104
+ }
105
+
106
+ .sps-fetch-message[data-tone='success'] {
107
+ color: var(--sps-ok);
108
+ font-weight: 700;
109
+ }
110
+
111
+ .sps-fetch-message[data-tone='error'] {
112
+ color: var(--sps-warn);
113
+ font-weight: 700;
114
+ }
115
+
116
+ .theme-dark .sps-input,
117
+ .theme-dark .sps-textarea,
118
+ .theme-dark .sps-segment button {
119
+ border-color: #334155;
120
+ background: #0f172a;
121
+ color: #e5edf7;
122
+ }
123
+
124
+ .theme-dark .sps-fetch-button {
125
+ border-color: #334155;
126
+ background: #2563eb;
127
+ }
128
+
129
+ .theme-dark .sps-label,
130
+ .theme-dark .sps-device-label,
131
+ .theme-dark .sps-meter-top,
132
+ .theme-dark .sps-preview-title {
133
+ color: #d6e1f0;
134
+ }
135
+
136
+ .sps-textarea {
137
+ min-height: 108px;
138
+ resize: vertical;
139
+ }
140
+
141
+ .sps-device {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: space-between;
145
+ gap: 12px;
146
+ margin-bottom: 18px;
147
+ }
148
+
149
+ .sps-segment {
150
+ display: inline-grid;
151
+ grid-template-columns: 1fr 1fr;
152
+ border: 1px solid #cbd5e1;
153
+ border-radius: 7px;
154
+ overflow: hidden;
155
+ }
156
+
157
+ .sps-segment button {
158
+ border: 0;
159
+ border-right: 1px solid #cbd5e1;
160
+ background: #fff;
161
+ color: #334155;
162
+ padding: 8px 12px;
163
+ font-weight: 700;
164
+ cursor: pointer;
165
+ }
166
+
167
+ .sps-segment button:last-child {
168
+ border-right: 0;
169
+ }
170
+
171
+ .sps-segment button[aria-pressed='true'] {
172
+ background: #e8f0fe;
173
+ color: #174ea6;
174
+ }
175
+
176
+ .theme-dark .sps-segment button[aria-pressed='true'] {
177
+ background: #1e3a5f;
178
+ color: #bfdbfe;
179
+ }
180
+
181
+ .sps-meter {
182
+ display: grid;
183
+ gap: 7px;
184
+ margin-top: 14px;
185
+ }
186
+
187
+ .sps-meter-top {
188
+ display: flex;
189
+ justify-content: space-between;
190
+ gap: 12px;
191
+ }
192
+
193
+ .sps-track {
194
+ height: 10px;
195
+ border-radius: 999px;
196
+ background: #e5eaf1;
197
+ overflow: hidden;
198
+ }
199
+
200
+ .sps-fill {
201
+ display: block;
202
+ width: 0%;
203
+ height: 100%;
204
+ border-radius: inherit;
205
+ background: var(--sps-ok);
206
+ transition: width 120ms ease, background-color 120ms ease;
207
+ }
208
+
209
+ .sps-meter.sps-over .sps-fill {
210
+ background: var(--sps-warn);
211
+ }
212
+
213
+ .sps-meter-status {
214
+ font-size: 0.82rem;
215
+ color: var(--sps-muted);
216
+ }
217
+
218
+ .sps-meter.sps-over .sps-meter-status {
219
+ color: var(--sps-warn);
220
+ font-weight: 700;
221
+ }
222
+
223
+ .sps-preview-wrap {
224
+ border-left: 1px solid var(--sps-line);
225
+ background: var(--sps-soft);
226
+ border-radius: 8px;
227
+ padding: 24px;
228
+ }
229
+
230
+ .sps-preview-title {
231
+ margin: 0 0 14px;
232
+ color: #334155;
233
+ font-size: 0.92rem;
234
+ }
235
+
236
+ .sps-serp {
237
+ width: min(100%, 652px);
238
+ border-radius: 8px;
239
+ background: #fff;
240
+ padding: 18px;
241
+ font-family: Arial, Helvetica, sans-serif;
242
+ box-shadow: 0 1px 2px rgb(60, 64, 67, 0.14), 0 1px 3px 1px rgb(60, 64, 67, 0.08);
243
+ }
244
+
245
+ .theme-dark .sps-serp {
246
+ background: #f8fafc;
247
+ }
248
+
249
+ .sps-serp.sps-mobile {
250
+ max-width: 390px;
251
+ }
252
+
253
+ .sps-url-line {
254
+ display: flex;
255
+ align-items: center;
256
+ gap: 10px;
257
+ min-width: 0;
258
+ margin-bottom: 6px;
259
+ }
260
+
261
+ .sps-favicon {
262
+ display: grid;
263
+ place-items: center;
264
+ width: 28px;
265
+ height: 28px;
266
+ flex: 0 0 auto;
267
+ border-radius: 50%;
268
+ background: #edf2f7;
269
+ color: #5f6368;
270
+ font-size: 14px;
271
+ font-weight: 700;
272
+ }
273
+
274
+ .sps-favicon-image {
275
+ width: 28px;
276
+ height: 28px;
277
+ flex: 0 0 auto;
278
+ border-radius: 50%;
279
+ background: #edf2f7;
280
+ object-fit: contain;
281
+ }
282
+
283
+ .sps-hidden {
284
+ display: none;
285
+ }
286
+
287
+ .sps-url-text {
288
+ min-width: 0;
289
+ color: #202124;
290
+ font-size: 14px;
291
+ line-height: 1.3;
292
+ overflow: hidden;
293
+ text-overflow: ellipsis;
294
+ white-space: nowrap;
295
+ }
296
+
297
+ .sps-serp-title {
298
+ margin: 0 0 4px;
299
+ color: #1a0dab;
300
+ font-size: 20px;
301
+ line-height: 1.3;
302
+ font-weight: 400;
303
+ }
304
+
305
+ .sps-description {
306
+ margin: 0;
307
+ color: #4d5156;
308
+ font-size: 14px;
309
+ line-height: 1.58;
310
+ }
311
+
312
+ .sps-measure {
313
+ position: fixed;
314
+ inset: auto auto -9999px -9999px;
315
+ visibility: hidden;
316
+ white-space: nowrap;
317
+ pointer-events: none;
318
+ }
319
+
320
+ @media (max-width: 780px) {
321
+ .sps-shell {
322
+ grid-template-columns: 1fr;
323
+ }
324
+
325
+ .sps-card {
326
+ padding: 16px;
327
+ }
328
+
329
+ .sps-preview-wrap {
330
+ border-left: 0;
331
+ border-top: 1px solid var(--sps-line);
332
+ padding: 18px 0 0;
333
+ background: transparent;
334
+ }
335
+ }
@@ -0,0 +1,33 @@
1
+ export interface SerpPixelSimulatorUI extends Record<string, string> {
2
+ titleLabel: string;
3
+ titlePlaceholder: string;
4
+ urlLabel: string;
5
+ urlPlaceholder: string;
6
+ descriptionLabel: string;
7
+ descriptionPlaceholder: string;
8
+ deviceLabel: string;
9
+ desktopLabel: string;
10
+ mobileLabel: string;
11
+ titlePixelsLabel: string;
12
+ descriptionPixelsLabel: string;
13
+ charactersLabel: string;
14
+ previewLabel: string;
15
+ tooLongLabel: string;
16
+ goodLabel: string;
17
+ emptyTitle: string;
18
+ emptyDescription: string;
19
+ defaultTitle: string;
20
+ defaultUrl: string;
21
+ defaultDescription: string;
22
+ fallbackUrl: string;
23
+ fallbackFaviconText: string;
24
+ pixelUnit: string;
25
+ ellipsis: string;
26
+ fetchButtonLabel: string;
27
+ fetchLoadingLabel: string;
28
+ fetchSuccessLabel: string;
29
+ fetchCorsError: string;
30
+ fetchInvalidUrlError: string;
31
+ fetchNoMetadataError: string;
32
+ fetchGenericError: string;
33
+ }
package/src/tools.ts CHANGED
@@ -24,6 +24,7 @@ import { INSPECTOR_CERTIFICADOS_SSL_TOOL } from './tool/inspectorCertificadosSsl
24
24
  import { GENERADOR_SECURITY_TXT_TOOL } from './tool/generadorSecurityTxt/index';
25
25
  import { CALCULADORA_TIEMPO_DATOS_TOOL } from './tool/calculadoraTiempoDatos/index';
26
26
  import { CONVERSOR_EXCEL_CSV_HTML_TOOL } from './tool/conversorExcelCsvHtml/index';
27
+ import { SERP_PIXEL_SIMULATOR_TOOL } from './tool/serpPixelSimulator/index';
28
+ import { JWT_DECODER_TOOL } from './tool/jwtDecoder/index';
27
29
 
28
- export const ALL_TOOLS: ToolDefinition[] = [JSON_FORMATTER_TOOL, SVG_TO_CSS_TOOL, ASPECT_RATIO_TOOL, PLACEHOLDER_GENERATOR_TOOL, URL_ENCODER_DECODER_TOOL, DUPLICATE_CSS_REMOVER_TOOL, CSS_TO_INLINE_CONVERTER_TOOL, CSS_SPECIFICITY_CALCULATOR_TOOL, CRON_GENERATOR_TOOL, KEYCODE_TOOL, LLM_COST_CALCULATOR_TOOL, MUSICAL_TYPOGRAPHY_TOOL, MOBILE_MOCKUP_GENERATOR_TOOL, HASH_GENERATOR_TOOL, PROMPT_LIBRARY_TOOL, COLOR_CONVERTER_TOOL, READABILITY_CALCULATOR_TOOL, SVG_SANITIZER_TOOL, UTM_GENERATOR_TOOL, URL_CLEANER_TOOL, INSPECTOR_CERTIFICADOS_SSL_TOOL, GENERADOR_SECURITY_TXT_TOOL, CALCULADORA_TIEMPO_DATOS_TOOL, CONVERSOR_EXCEL_CSV_HTML_TOOL];
29
-
30
+ export const ALL_TOOLS: ToolDefinition[] = [JSON_FORMATTER_TOOL, SVG_TO_CSS_TOOL, ASPECT_RATIO_TOOL, PLACEHOLDER_GENERATOR_TOOL, URL_ENCODER_DECODER_TOOL, DUPLICATE_CSS_REMOVER_TOOL, CSS_TO_INLINE_CONVERTER_TOOL, CSS_SPECIFICITY_CALCULATOR_TOOL, CRON_GENERATOR_TOOL, KEYCODE_TOOL, LLM_COST_CALCULATOR_TOOL, MUSICAL_TYPOGRAPHY_TOOL, MOBILE_MOCKUP_GENERATOR_TOOL, HASH_GENERATOR_TOOL, PROMPT_LIBRARY_TOOL, COLOR_CONVERTER_TOOL, READABILITY_CALCULATOR_TOOL, SVG_SANITIZER_TOOL, UTM_GENERATOR_TOOL, URL_CLEANER_TOOL, INSPECTOR_CERTIFICADOS_SSL_TOOL, GENERADOR_SECURITY_TXT_TOOL, CALCULADORA_TIEMPO_DATOS_TOOL, CONVERSOR_EXCEL_CSV_HTML_TOOL, SERP_PIXEL_SIMULATOR_TOOL, JWT_DECODER_TOOL];