@jjlmoya/utils-streaming 1.19.0 → 1.21.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 (38) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +4 -1
  4. package/src/index.ts +2 -0
  5. package/src/tests/locale_completeness.test.ts +2 -3
  6. package/src/tests/seo_component_contract.test.ts +22 -0
  7. package/src/tests/tool_validation.test.ts +17 -17
  8. package/src/tool/videoBitratePlanner/bibliography.astro +6 -0
  9. package/src/tool/videoBitratePlanner/bibliography.ts +12 -0
  10. package/src/tool/videoBitratePlanner/component.astro +122 -0
  11. package/src/tool/videoBitratePlanner/controller.ts +134 -0
  12. package/src/tool/videoBitratePlanner/dom-views.ts +77 -0
  13. package/src/tool/videoBitratePlanner/entry.ts +29 -0
  14. package/src/tool/videoBitratePlanner/evaluator.ts +19 -0
  15. package/src/tool/videoBitratePlanner/i18n/de.ts +39 -0
  16. package/src/tool/videoBitratePlanner/i18n/en.ts +202 -0
  17. package/src/tool/videoBitratePlanner/i18n/es.ts +39 -0
  18. package/src/tool/videoBitratePlanner/i18n/fr.ts +39 -0
  19. package/src/tool/videoBitratePlanner/i18n/id.ts +37 -0
  20. package/src/tool/videoBitratePlanner/i18n/it.ts +37 -0
  21. package/src/tool/videoBitratePlanner/i18n/ja.ts +37 -0
  22. package/src/tool/videoBitratePlanner/i18n/ko.ts +37 -0
  23. package/src/tool/videoBitratePlanner/i18n/nl.ts +37 -0
  24. package/src/tool/videoBitratePlanner/i18n/pl.ts +37 -0
  25. package/src/tool/videoBitratePlanner/i18n/pt.ts +37 -0
  26. package/src/tool/videoBitratePlanner/i18n/ru.ts +37 -0
  27. package/src/tool/videoBitratePlanner/i18n/sv.ts +37 -0
  28. package/src/tool/videoBitratePlanner/i18n/tr.ts +37 -0
  29. package/src/tool/videoBitratePlanner/i18n/zh.ts +37 -0
  30. package/src/tool/videoBitratePlanner/index.ts +13 -0
  31. package/src/tool/videoBitratePlanner/locale-content.ts +72 -0
  32. package/src/tool/videoBitratePlanner/logic.test.ts +50 -0
  33. package/src/tool/videoBitratePlanner/logic.ts +158 -0
  34. package/src/tool/videoBitratePlanner/seo.astro +15 -0
  35. package/src/tool/videoBitratePlanner/storage.ts +31 -0
  36. package/src/tool/videoBitratePlanner/ui.ts +50 -0
  37. package/src/tool/videoBitratePlanner/video-bitrate-storage-planner.css +612 -0
  38. package/src/tools.ts +2 -1
@@ -0,0 +1,612 @@
1
+ :root {
2
+ --n-paper: #f6f0e6;
3
+ --n-card: #fffaf2;
4
+ --n-ink: #1d2630;
5
+ --n-muted: #69737d;
6
+ --n-line: #d9cec0;
7
+ --n-coral: #e35f4d;
8
+ --n-coral-soft: #f7d8d1;
9
+ --n-blue: #28699a;
10
+ --n-blue-soft: #d7e9f2;
11
+ --n-yellow: #d6a536;
12
+ --n-green: #398269;
13
+ --n-shadow: rgba(29, 38, 48, .12);
14
+ }
15
+
16
+ .theme-dark {
17
+ --n-paper: #1b2025;
18
+ --n-card: #252c32;
19
+ --n-ink: #f4eee3;
20
+ --n-muted: #aab4bc;
21
+ --n-line: #49545d;
22
+ --n-coral: #f17a63;
23
+ --n-coral-soft: #57332f;
24
+ --n-blue: #78b8d8;
25
+ --n-blue-soft: #244452;
26
+ --n-yellow: #e5bf5c;
27
+ --n-green: #70bb9b;
28
+ --n-shadow: rgba(0, 0, 0, .32);
29
+ }
30
+
31
+ .bitrate-planner {
32
+ --n-surface: var(--n-card);
33
+ --n-surface-strong: var(--n-paper);
34
+ --n-text: var(--n-ink);
35
+ --n-secondary: var(--n-muted);
36
+ --n-border: var(--n-line);
37
+ --n-accent: var(--n-coral);
38
+ --n-accent-soft: var(--n-coral-soft);
39
+ --n-cool: var(--n-blue);
40
+ --n-cool-soft: var(--n-blue-soft);
41
+
42
+ color: var(--n-text);
43
+ background: var(--n-surface);
44
+ border: 1px solid var(--n-border);
45
+ border-radius: 1.2rem;
46
+ box-shadow: 0 .7rem 2rem var(--n-shadow);
47
+ overflow: hidden;
48
+ }
49
+
50
+ .planner-layout {
51
+ display: grid;
52
+ grid-template-columns: minmax(18rem, .92fr) minmax(20rem, 1.08fr);
53
+ gap: 0;
54
+ }
55
+
56
+ .planner-controls {
57
+ display: grid;
58
+ align-content: start;
59
+ gap: 1.25rem;
60
+ padding: 1.5rem;
61
+ background: var(--n-surface-strong);
62
+ border-right: 1px solid var(--n-border);
63
+ }
64
+
65
+ .preset-line,
66
+ .choice-row,
67
+ .control-footer,
68
+ .scene-heading,
69
+ .scene-caption,
70
+ .badge-line,
71
+ .comparison-heading {
72
+ display: flex;
73
+ align-items: center;
74
+ gap: .5rem;
75
+ flex-wrap: wrap;
76
+ }
77
+
78
+ .control-caption,
79
+ .scene-label,
80
+ .number-control > span:first-child,
81
+ .stat-strip span,
82
+ .comparison-heading,
83
+ .world-label,
84
+ .scene-caption,
85
+ .quality-note,
86
+ .local-note,
87
+ .control-note,
88
+ .assumption-panel,
89
+ .main-result span,
90
+ .main-result small {
91
+ color: var(--n-secondary);
92
+ font-size: .72rem;
93
+ letter-spacing: .04em;
94
+ line-height: 1.45;
95
+ }
96
+
97
+ .control-caption,
98
+ .scene-label,
99
+ .comparison-heading,
100
+ .world-label {
101
+ text-transform: uppercase;
102
+ font-weight: 750;
103
+ }
104
+
105
+ button,
106
+ input {
107
+ font: inherit;
108
+ }
109
+
110
+ button {
111
+ cursor: pointer;
112
+ }
113
+
114
+ .preset-button,
115
+ .choice-button,
116
+ .reset-button {
117
+ color: var(--n-text);
118
+ background: var(--n-surface);
119
+ border: 1px solid var(--n-border);
120
+ border-radius: .65rem;
121
+ min-height: 2.25rem;
122
+ padding: .45rem .7rem;
123
+ transition: background .16s ease, border-color .16s ease, transform .16s ease;
124
+ }
125
+
126
+ .preset-button:hover,
127
+ .choice-button:hover,
128
+ .reset-button:hover {
129
+ border-color: var(--n-accent);
130
+ transform: translateY(-1px);
131
+ }
132
+
133
+ .preset-button.is-active,
134
+ .choice-button.is-active {
135
+ color: var(--n-surface);
136
+ background: var(--n-text);
137
+ border-color: var(--n-text);
138
+ }
139
+
140
+ .control-fieldset {
141
+ display: grid;
142
+ gap: .55rem;
143
+ min-width: 0;
144
+ margin: 0;
145
+ padding: 0;
146
+ border: 0;
147
+ }
148
+
149
+ .control-fieldset legend {
150
+ margin-bottom: .1rem;
151
+ color: var(--n-text);
152
+ font-size: .82rem;
153
+ font-weight: 750;
154
+ }
155
+
156
+ .control-note,
157
+ .local-note,
158
+ .quality-note {
159
+ margin: 0;
160
+ }
161
+
162
+ .number-grid {
163
+ display: grid;
164
+ gap: .75rem;
165
+ }
166
+
167
+ .number-control {
168
+ display: grid;
169
+ gap: .35rem;
170
+ }
171
+
172
+ .number-input-wrap {
173
+ display: flex;
174
+ align-items: center;
175
+ min-height: 2.8rem;
176
+ padding: 0 .75rem;
177
+ background: var(--n-surface);
178
+ border: 1px solid var(--n-border);
179
+ border-radius: .65rem;
180
+ }
181
+
182
+ .number-input-wrap:focus-within {
183
+ border-color: var(--n-accent);
184
+ outline: 2px solid var(--n-accent-soft);
185
+ }
186
+
187
+ .number-input-wrap input {
188
+ width: 100%;
189
+ min-width: 0;
190
+ color: var(--n-text);
191
+ background: transparent;
192
+ border: 0;
193
+ outline: 0;
194
+ }
195
+
196
+ .number-input-wrap b {
197
+ color: var(--n-secondary);
198
+ font-size: .72rem;
199
+ white-space: nowrap;
200
+ }
201
+
202
+ .control-footer {
203
+ align-items: flex-start;
204
+ justify-content: space-between;
205
+ padding-top: .2rem;
206
+ }
207
+
208
+ .reset-button {
209
+ flex: 0 0 auto;
210
+ min-height: 1.9rem;
211
+ padding: .3rem .55rem;
212
+ font-size: .72rem;
213
+ }
214
+
215
+ .planner-scene {
216
+ display: grid;
217
+ align-content: start;
218
+ gap: 1rem;
219
+ min-width: 0;
220
+ padding: 1.5rem;
221
+ background: var(--n-surface);
222
+ }
223
+
224
+ .scene-heading {
225
+ justify-content: space-between;
226
+ }
227
+
228
+ .quality-badge,
229
+ .capacity-badge {
230
+ display: inline-flex;
231
+ align-items: center;
232
+ min-height: 1.7rem;
233
+ padding: .25rem .55rem;
234
+ color: var(--n-text);
235
+ background: var(--n-accent-soft);
236
+ border-radius: 999px;
237
+ font-size: .7rem;
238
+ font-weight: 750;
239
+ }
240
+
241
+ .quality-badge[data-tone="excellent"],
242
+ .quality-badge[data-tone="strong"] {
243
+ background: var(--n-blue-soft);
244
+ }
245
+
246
+ .quality-badge[data-tone="aggressive"] {
247
+ background: var(--n-coral-soft);
248
+ }
249
+
250
+ .capacity-badge[data-tone="medium"] {
251
+ background: #f1e5be;
252
+ }
253
+
254
+ .capacity-badge[data-tone="heavy"] {
255
+ color: var(--n-surface);
256
+ background: var(--n-coral);
257
+ }
258
+
259
+ .signal-world {
260
+ position: relative;
261
+ display: grid;
262
+ grid-template-columns: 1fr auto 1fr;
263
+ align-items: center;
264
+ min-height: 15rem;
265
+ padding: 1.25rem .75rem;
266
+ background: var(--n-surface-strong);
267
+ border: 1px solid var(--n-border);
268
+ border-radius: .9rem;
269
+ overflow: hidden;
270
+ }
271
+
272
+ .signal-source,
273
+ .signal-reel {
274
+ display: grid;
275
+ justify-items: center;
276
+ gap: .65rem;
277
+ z-index: 1;
278
+ }
279
+
280
+ .source-screen {
281
+ display: grid;
282
+ place-items: center;
283
+ width: 7.2rem;
284
+ height: 5.3rem;
285
+ color: var(--n-surface);
286
+ background: var(--n-blue);
287
+ border: .35rem solid var(--n-text);
288
+ border-radius: .7rem;
289
+ font-size: 1.25rem;
290
+ font-weight: 800;
291
+ box-shadow: .35rem .35rem 0 var(--n-coral);
292
+ }
293
+
294
+ .screen-grid {
295
+ position: absolute;
296
+ display: grid;
297
+ grid-template-columns: repeat(2, .65rem);
298
+ gap: .35rem;
299
+ opacity: .5;
300
+ }
301
+
302
+ .screen-grid i {
303
+ display: block;
304
+ width: .65rem;
305
+ height: .65rem;
306
+ background: var(--n-surface);
307
+ border-radius: 50%;
308
+ }
309
+
310
+ .source-screen > span {
311
+ position: relative;
312
+ z-index: 1;
313
+ }
314
+
315
+ .signal-bridge {
316
+ display: grid;
317
+ justify-items: center;
318
+ gap: .45rem;
319
+ min-width: 3.5rem;
320
+ }
321
+
322
+ .bridge-line {
323
+ width: 2rem;
324
+ height: .15rem;
325
+ background: var(--n-coral);
326
+ }
327
+
328
+ .codec-gate {
329
+ display: grid;
330
+ place-items: center;
331
+ width: 3rem;
332
+ height: 3rem;
333
+ color: var(--n-surface);
334
+ background: var(--n-text);
335
+ border: .25rem solid var(--n-coral);
336
+ border-radius: 50%;
337
+ font-size: .65rem;
338
+ font-weight: 800;
339
+ }
340
+
341
+ .reel-disc {
342
+ position: relative;
343
+ display: grid;
344
+ place-items: center;
345
+ width: 7rem;
346
+ height: 7rem;
347
+ background: var(--n-coral);
348
+ border: .55rem solid var(--n-text);
349
+ border-radius: 50%;
350
+ box-shadow: .35rem .35rem 0 var(--n-blue);
351
+ }
352
+
353
+ .reel-hole,
354
+ .reel-groove {
355
+ position: absolute;
356
+ display: block;
357
+ width: 1.4rem;
358
+ height: 1.4rem;
359
+ border: .25rem solid var(--n-surface);
360
+ border-radius: 50%;
361
+ }
362
+
363
+ .reel-groove {
364
+ width: 4.1rem;
365
+ height: 4.1rem;
366
+ border-width: .12rem;
367
+ opacity: .65;
368
+ }
369
+
370
+ .reel-groove-inner {
371
+ width: 2.7rem;
372
+ height: 2.7rem;
373
+ border-width: .18rem;
374
+ opacity: .8;
375
+ }
376
+
377
+ .signal-frames {
378
+ position: absolute;
379
+ right: 4.8rem;
380
+ left: 4.8rem;
381
+ bottom: 1.05rem;
382
+ display: flex;
383
+ align-items: flex-end;
384
+ gap: .22rem;
385
+ height: 2rem;
386
+ overflow: hidden;
387
+ opacity: .9;
388
+ }
389
+
390
+ .signal-frame {
391
+ flex: 1 0 .5rem;
392
+ max-width: 1rem;
393
+ height: 38%;
394
+ background: var(--n-blue);
395
+ border-radius: .15rem .15rem 0 0;
396
+ animation: pulse-frame 1.7s ease-in-out infinite;
397
+ animation-delay: var(--frame-delay);
398
+ }
399
+
400
+ .signal-frame:nth-child(3n) {
401
+ height: 72%;
402
+ }
403
+
404
+ .signal-frame:nth-child(4n) {
405
+ height: 52%;
406
+ }
407
+
408
+ .signal-frame-accent {
409
+ background: var(--n-coral);
410
+ }
411
+
412
+ @keyframes pulse-frame {
413
+ 0%, 100% { transform: scaleY(.8); }
414
+ 50% { transform: scaleY(1); }
415
+ }
416
+
417
+ .scene-caption {
418
+ justify-content: space-between;
419
+ padding-bottom: .65rem;
420
+ border-bottom: 1px solid var(--n-border);
421
+ }
422
+
423
+ .scene-caption strong {
424
+ color: var(--n-text);
425
+ font-size: .82rem;
426
+ }
427
+
428
+ .main-result {
429
+ display: grid;
430
+ gap: .15rem;
431
+ padding: .2rem 0;
432
+ }
433
+
434
+ .main-result strong {
435
+ max-width: 100%;
436
+ color: var(--n-text);
437
+ font-size: clamp(2.5rem, 7vw, 4.8rem);
438
+ line-height: 1;
439
+ letter-spacing: -.07em;
440
+ overflow-wrap: anywhere;
441
+ }
442
+
443
+ .main-result small {
444
+ letter-spacing: 0;
445
+ }
446
+
447
+ .badge-line {
448
+ align-items: flex-start;
449
+ }
450
+
451
+ .capacity-note {
452
+ color: var(--n-secondary);
453
+ font-size: .72rem;
454
+ line-height: 1.45;
455
+ }
456
+
457
+ .planner-lower {
458
+ grid-column: 1 / -1;
459
+ display: grid;
460
+ gap: 1rem;
461
+ padding: 0 1.5rem 1.5rem;
462
+ background: var(--n-surface);
463
+ }
464
+
465
+ .stat-strip {
466
+ display: grid;
467
+ grid-template-columns: repeat(4, 1fr);
468
+ border-top: 1px solid var(--n-border);
469
+ border-bottom: 1px solid var(--n-border);
470
+ }
471
+
472
+ .stat-strip > div {
473
+ display: grid;
474
+ gap: .25rem;
475
+ padding: .9rem .75rem;
476
+ border-right: 1px solid var(--n-border);
477
+ }
478
+
479
+ .stat-strip > div:last-child {
480
+ border-right: 0;
481
+ }
482
+
483
+ .stat-strip strong {
484
+ color: var(--n-text);
485
+ font-size: 1rem;
486
+ }
487
+
488
+ .comparison-panel {
489
+ display: grid;
490
+ gap: .65rem;
491
+ }
492
+
493
+ .comparison-heading {
494
+ justify-content: space-between;
495
+ color: var(--n-text);
496
+ font-size: .8rem;
497
+ }
498
+
499
+ .comparison-row {
500
+ display: grid;
501
+ grid-template-columns: .55rem 1fr auto auto auto;
502
+ align-items: center;
503
+ gap: .7rem;
504
+ min-height: 2.25rem;
505
+ border-bottom: 1px solid var(--n-border);
506
+ font-size: .78rem;
507
+ }
508
+
509
+ .comparison-mark {
510
+ width: .5rem;
511
+ height: .5rem;
512
+ background: var(--n-yellow);
513
+ border-radius: 50%;
514
+ }
515
+
516
+ .comparison-row[data-tone="strong"] .comparison-mark,
517
+ .comparison-row[data-tone="excellent"] .comparison-mark {
518
+ background: var(--n-blue);
519
+ }
520
+
521
+ .comparison-row[data-tone="aggressive"] .comparison-mark {
522
+ background: var(--n-coral);
523
+ }
524
+
525
+ .comparison-name,
526
+ .comparison-quality {
527
+ color: var(--n-secondary);
528
+ }
529
+
530
+ .assumption-panel {
531
+ border-top: 1px solid var(--n-border);
532
+ padding-top: .85rem;
533
+ }
534
+
535
+ .assumption-panel summary {
536
+ color: var(--n-text);
537
+ cursor: pointer;
538
+ font-size: .78rem;
539
+ font-weight: 750;
540
+ }
541
+
542
+ .assumption-panel p {
543
+ max-width: 60rem;
544
+ margin: .65rem 0 0;
545
+ line-height: 1.6;
546
+ }
547
+
548
+ @media (max-width: 760px) {
549
+ .planner-layout {
550
+ grid-template-columns: 1fr;
551
+ }
552
+
553
+ .planner-controls {
554
+ border-right: 0;
555
+ border-bottom: 1px solid var(--n-border);
556
+ }
557
+
558
+ .planner-lower {
559
+ grid-column: auto;
560
+ }
561
+ }
562
+
563
+ @media (max-width: 520px) {
564
+ .planner-controls,
565
+ .planner-scene,
566
+ .planner-lower {
567
+ padding-right: 1rem;
568
+ padding-left: 1rem;
569
+ }
570
+
571
+ .signal-world {
572
+ min-height: 13rem;
573
+ padding-right: .25rem;
574
+ padding-left: .25rem;
575
+ }
576
+
577
+ .source-screen {
578
+ width: 5.8rem;
579
+ height: 4.3rem;
580
+ font-size: 1rem;
581
+ }
582
+
583
+ .reel-disc {
584
+ width: 5.7rem;
585
+ height: 5.7rem;
586
+ }
587
+
588
+ .signal-frames {
589
+ right: 3.6rem;
590
+ left: 3.6rem;
591
+ }
592
+
593
+ .stat-strip {
594
+ grid-template-columns: repeat(2, 1fr);
595
+ }
596
+
597
+ .stat-strip > div:nth-child(2) {
598
+ border-right: 0;
599
+ }
600
+
601
+ .stat-strip > div:nth-child(-n + 2) {
602
+ border-bottom: 1px solid var(--n-border);
603
+ }
604
+
605
+ .comparison-row {
606
+ grid-template-columns: .55rem 1fr auto;
607
+ }
608
+
609
+ .comparison-row > span:nth-last-child(-n + 2) {
610
+ display: none;
611
+ }
612
+ }
package/src/tools.ts CHANGED
@@ -2,9 +2,10 @@ export { ALL_ENTRIES } from './entries';
2
2
  import type { ToolDefinition } from './types';
3
3
  import { SORTEO_TOOL } from './tool/sorteo/index';
4
4
  import { TEBAS_CHECK_TOOL } from './tool/tebasCheck/index';
5
+ import { VIDEO_BITRATE_PLANNER_TOOL } from './tool/videoBitratePlanner/index';
5
6
 
6
7
  export const ALL_TOOLS: ToolDefinition[] = [
7
8
  SORTEO_TOOL,
8
9
  TEBAS_CHECK_TOOL,
10
+ VIDEO_BITRATE_PLANNER_TOOL,
9
11
  ];
10
-