create-openclass-uniminuto 1.6.1 → 1.6.2

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.
@@ -15,8 +15,21 @@ const positional = args.filter((arg) => !arg.startsWith("--"));
15
15
  const targetArg = positional[0] || "openclass-uniminuto";
16
16
  const targetDir = path.resolve(process.cwd(), targetArg);
17
17
  const isCurrentDirectoryTarget = targetArg === "." || targetArg === "./";
18
- const forceOverwrite = flags.has("--force");
19
- const updateTheme = flags.has("--update-theme") || flags.has("--sync-theme");
18
+ function envFlag(name) {
19
+ const value = process.env[name];
20
+ if (value === undefined) return false;
21
+ return ["1", "true", "yes", "on"].includes(String(value).toLowerCase());
22
+ }
23
+
24
+ const forceOverwrite =
25
+ flags.has("--force") ||
26
+ envFlag("npm_config_force");
27
+
28
+ const updateTheme =
29
+ flags.has("--update-theme") ||
30
+ flags.has("--sync-theme") ||
31
+ envFlag("npm_config_update_theme") ||
32
+ envFlag("npm_config_sync_theme");
20
33
 
21
34
  function log(message = "") {
22
35
  console.log(message);
@@ -100,13 +113,23 @@ function updateThemeOnly() {
100
113
  log("Modo: solo theme/components/styles/layouts y recursos base seguros\n");
101
114
 
102
115
  const pathsToUpdate = [
103
- "theme/uniminuto/components",
116
+ "README.md",
117
+ "theme/uniminuto/components",
104
118
  "theme/uniminuto/layouts",
105
119
  "theme/uniminuto/styles",
106
120
  "theme/uniminuto/package.json",
107
121
  "theme/uniminuto/README-AutoFit.md",
108
122
  "setup",
109
- "snippets"
123
+ "snippets",
124
+ "scripts/build-site.mjs",
125
+ "scripts/build-incremental.mjs",
126
+ "scripts/decks.mjs",
127
+ "scripts/dev-all.mjs",
128
+ "scripts/export-downloads.mjs",
129
+ "scripts/export-incremental.mjs",
130
+ "scripts/preparar-github-pages.mjs",
131
+ "scripts/semana.mjs",
132
+ ".github/workflows/deploy.yml"
110
133
  ];
111
134
 
112
135
  for (const relativePath of pathsToUpdate) {
@@ -117,6 +140,37 @@ function updateThemeOnly() {
117
140
  ensureFileFromTemplate("public/imagenes/favicon.png", { onlyIfMissing: true });
118
141
  ensureFileFromTemplate("public/imagenes/avion.png", { onlyIfMissing: false });
119
142
 
143
+ patchJson(path.join(targetDir, "package.json"), (pkg) => {
144
+ pkg.scripts = pkg.scripts || {};
145
+ pkg.scripts["dev"] = pkg.scripts["dev"] || "slidev slides.md --open --port 3000";
146
+ pkg.scripts["dev:all"] = "node scripts/dev-all.mjs";
147
+ pkg.scripts["dev:todo"] = "node scripts/dev-all.mjs";
148
+ pkg.scripts["build:all"] = "node scripts/build-site.mjs";
149
+ pkg.scripts["build:incremental"] = "node scripts/build-incremental.mjs";
150
+ pkg.scripts["export:downloads"] = "node scripts/export-downloads.mjs";
151
+ pkg.scripts["export:incremental"] = "node scripts/export-incremental.mjs";
152
+ pkg.scripts["pages:check"] = "node scripts/preparar-github-pages.mjs";
153
+ pkg.scripts["pages:build"] = "npm run export:downloads && npm run build:all";
154
+ pkg.scripts["pages:preview"] = "npm run preview:pages";
155
+ pkg.scripts["semana"] = "node scripts/semana.mjs";
156
+ pkg.scripts["actualizar:tema"] = "npm create openclass-uniminuto@latest . -- --update-theme";
157
+ });
158
+
159
+ patchJson(path.join(targetDir, "package.json"), (pkg) => {
160
+ pkg.scripts = pkg.scripts || {};
161
+ pkg.scripts["dev"] = pkg.scripts["dev"] || "slidev slides.md --open --port 3000";
162
+ pkg.scripts["dev:all"] = "node scripts/dev-all.mjs";
163
+ pkg.scripts["dev:todo"] = "node scripts/dev-all.mjs";
164
+ pkg.scripts["build:all"] = "node scripts/build-site.mjs";
165
+ pkg.scripts["build:incremental"] = "node scripts/build-incremental.mjs";
166
+ pkg.scripts["export:downloads"] = "node scripts/export-downloads.mjs";
167
+ pkg.scripts["export:incremental"] = "node scripts/export-incremental.mjs";
168
+ pkg.scripts["pages:check"] = "node scripts/preparar-github-pages.mjs";
169
+ pkg.scripts["pages:build"] = "npm run export:downloads && npm run build:all";
170
+ pkg.scripts["pages:preview"] = "npm run preview:pages";
171
+ pkg.scripts["semana"] = "node scripts/semana.mjs";
172
+ pkg.scripts["actualizar:tema"] = "npm create openclass-uniminuto@latest . -- --update-theme";
173
+ });
120
174
  log("\n✅ Tema actualizado sin tocar semanas, slides.md ni openclass.config.json.");
121
175
  log(" Recomendado ahora:");
122
176
  log(" npm run dev");
@@ -220,3 +274,5 @@ log(" npm create openclass-uniminuto@latest . -- --update-theme");
220
274
  log("\nPara revisar la publicación en GitHub Pages:");
221
275
  log(" npm run pages:check");
222
276
  log("");
277
+
278
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclass-uniminuto",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "description": "Creador de proyectos Open Class UNIMINUTO basados en Slidev, con generación incremental por semanas, actualización de tema y GitHub Pages.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,7 +6,6 @@ Este curso está diseñado para organizar una Open Class de **8 semanas**, con g
6
6
 
7
7
  ---
8
8
 
9
-
10
9
  ## Crear el curso dentro de un repositorio ya creado en GitHub
11
10
 
12
11
  Si primero creaste el repositorio en GitHub, clónalo y aplica la plantilla desde npm dentro de la carpeta del repositorio:
@@ -34,6 +33,7 @@ git commit -m "Configura Open Class"
34
33
  git push
35
34
  ```
36
35
 
36
+ ---
37
37
 
38
38
  ## 1. Primer uso
39
39
 
@@ -69,6 +69,12 @@ npm run dev:s2
69
69
  npm run dev:s3
70
70
  ```
71
71
 
72
+ También puedes abrir todas las semanas activas en varios puertos:
73
+
74
+ ```bash
75
+ npm run dev:all
76
+ ```
77
+
72
78
  ---
73
79
 
74
80
  ## 2. Tres formas de crear este curso
@@ -173,7 +179,7 @@ El contenido ya editado dentro de `semanas/*.md` se conserva. Solo se sobrescrib
173
179
  npm run semana -- 4 --force-content
174
180
  ```
175
181
 
176
- Para activar únicamente una semana:
182
+ Para activar únicamente una semana ya existente:
177
183
 
178
184
  ```bash
179
185
  npm run semana -- 4 --only
@@ -199,6 +205,22 @@ semanas/iot_semana3.md
199
205
 
200
206
  Los archivos de la raíz como `iot_semana1.md` funcionan como lanzadores. Normalmente no debes editarlos manualmente.
201
207
 
208
+ Un lanzador raíz tiene una estructura como esta:
209
+
210
+ ```md
211
+ ---
212
+ theme: ./theme/uniminuto
213
+ title: Curso — Semana 1
214
+ favicon: /favicon.png
215
+ codeCopy: true
216
+ transition: fade
217
+ routerMode: hash
218
+ drawings:
219
+ persist: false
220
+ src: ./semanas/curso_semana1.md
221
+ ---
222
+ ```
223
+
202
224
  ---
203
225
 
204
226
  ## 5. Recursos del curso
@@ -212,9 +234,65 @@ public/descargas/ PDF, PPTX u otros descargables
212
234
  public/fondos/ fondos institucionales
213
235
  ```
214
236
 
237
+ Recomendaciones:
238
+
239
+ * Guarda imágenes propias del curso en `public/imagenes/`.
240
+ * Usa nombres cortos, claros y sin espacios.
241
+ * En las diapositivas, referencia imágenes con rutas absolutas desde `public`.
242
+
243
+ Ejemplo:
244
+
245
+ ```html
246
+ <img src="/imagenes/iot-semana1-arquitectura.png" alt="Arquitectura IoT" />
247
+ ```
248
+
249
+ Evita rutas demasiado largas o generadas a partir de prompts completos.
250
+
251
+ ---
252
+
253
+ ## 6. Detección automática de semanas
254
+
255
+ El proyecto detecta automáticamente las presentaciones semanales disponibles a partir de los lanzadores ubicados en la raíz.
256
+
257
+ Ejemplo:
258
+
259
+ ```text
260
+ iot_semana1.md
261
+ iot_semana2.md
262
+ gestionseguridad_semana7.md
263
+ bigdata_semana4.md
264
+ ```
265
+
266
+ Cada archivo raíz debe apuntar al contenido real ubicado en `semanas/`.
267
+
268
+ El archivo `scripts/decks.mjs` detecta estos lanzadores y construye automáticamente el portal principal y todas las semanas activas.
269
+
270
+ Ya no es necesario editar manualmente `scripts/decks.mjs` para activar cada semana, siempre que el lanzador raíz exista y tenga un nombre con este patrón:
271
+
272
+ ```text
273
+ curso_semanaN.md
274
+ ```
275
+
276
+ Ejemplos válidos:
277
+
278
+ ```text
279
+ bigdata_semana1.md
280
+ iot_semana5.md
281
+ gestionseguridad_semana7.md
282
+ percepcioncomputacional_semana8.md
283
+ ```
284
+
285
+ Ejemplos que no se incluyen automáticamente:
286
+
287
+ ```text
288
+ demo_semana1.md
289
+ semana1.md
290
+ presentacion.md
291
+ ```
292
+
215
293
  ---
216
294
 
217
- ## 6. Construcción local
295
+ ## 7. Construcción local
218
296
 
219
297
  Construir el portal y las semanas activas:
220
298
 
@@ -222,6 +300,23 @@ Construir el portal y las semanas activas:
222
300
  npm run pages:build
223
301
  ```
224
302
 
303
+ Este comando ejecuta:
304
+
305
+ ```text
306
+ npm run export:downloads
307
+ npm run build:all
308
+ ```
309
+
310
+ Por tanto, genera:
311
+
312
+ ```text
313
+ dist/ sitio estático final
314
+ dist/semanas/ semanas publicadas
315
+ public/descargas/*.pdf descargas PDF
316
+ public/descargas/*.pptx descargas PPTX
317
+ dist/.nojekyll archivo requerido para GitHub Pages
318
+ ```
319
+
225
320
  Previsualizar la versión estática:
226
321
 
227
322
  ```bash
@@ -234,9 +329,15 @@ Revisar configuración para GitHub Pages:
234
329
  npm run pages:check
235
330
  ```
236
331
 
332
+ También puedes probar directamente la carpeta `dist` con:
333
+
334
+ ```bash
335
+ npx serve dist
336
+ ```
337
+
237
338
  ---
238
339
 
239
- ## 7. Publicar en GitHub Pages
340
+ ## 8. Publicar en GitHub Pages
240
341
 
241
342
  Este proyecto ya incluye:
242
343
 
@@ -274,9 +375,67 @@ Ejemplo:
274
375
  https://herrerawilliamh.github.io/openclass-iot/
275
376
  ```
276
377
 
378
+ Las semanas quedarán disponibles en rutas como:
379
+
380
+ ```text
381
+ https://herrerawilliamh.github.io/openclass-iot/semanas/iot_semana1/
382
+ https://herrerawilliamh.github.io/openclass-iot/semanas/iot_semana2/
383
+ ```
384
+
385
+ ---
386
+
387
+ ## 9. Actualizar tema, layouts y scripts en un curso existente
388
+
389
+ Si el curso ya existe y solo quieres actualizar tema, layouts, scripts de build, workflow y documentación base sin tocar el contenido académico de `semanas/`, usa:
390
+
391
+ ```bash
392
+ npm create openclass-uniminuto@latest . -- --update-theme
393
+ ```
394
+
395
+ Este comando actualiza recursos seguros como:
396
+
397
+ ```text
398
+ README.md
399
+ theme/uniminuto/
400
+ scripts/decks.mjs
401
+ scripts/dev-all.mjs
402
+ scripts/build-site.mjs
403
+ scripts/build-incremental.mjs
404
+ scripts/export-downloads.mjs
405
+ scripts/export-incremental.mjs
406
+ scripts/preparar-github-pages.mjs
407
+ scripts/semana.mjs
408
+ .github/workflows/deploy.yml
409
+ public/imagenes/avion.png
410
+ ```
411
+
412
+ No debería sobrescribir:
413
+
414
+ ```text
415
+ slides.md
416
+ openclass.config.json
417
+ semanas/*.md
418
+ public/imagenes propias del curso
419
+ ```
420
+
421
+ Después de actualizar, revisa:
422
+
423
+ ```bash
424
+ git status
425
+ npm run pages:build
426
+ ```
427
+
428
+ Si todo funciona:
429
+
430
+ ```bash
431
+ git add -A
432
+ git commit -m "Actualizar tema institucional Open Class"
433
+ git push
434
+ ```
435
+
277
436
  ---
278
437
 
279
- ## 8. Flujo semanal sugerido
438
+ ## 10. Flujo semanal sugerido
280
439
 
281
440
  Semana 1:
282
441
 
@@ -300,27 +459,154 @@ Repite el proceso hasta la semana 8.
300
459
 
301
460
  ---
302
461
 
303
- ## 9. Comandos útiles
462
+ ## 11. Comandos útiles
463
+
464
+ | Comando | Uso |
465
+ | ------------------------- | ----------------------------------------------- |
466
+ | `npm run nuevo` | Configura un curso desde consola |
467
+ | `npm run semana -- 1` | Genera o activa la semana 1 |
468
+ | `npm run dev` | Abre el portal principal |
469
+ | `npm run dev:s1` | Abre la semana 1 |
470
+ | `npm run dev:all` | Abre portal y semanas activas en varios puertos |
471
+ | `npm run pages:check` | Revisa configuración para GitHub Pages |
472
+ | `npm run pages:build` | Construye el sitio estático y exporta descargas |
473
+ | `npm run pages:preview` | Previsualiza la versión publicada |
474
+ | `npm run publicar` | Ejecuta exportaciones y construcción local |
475
+ | `npm run actualizar:tema` | Actualiza tema/layouts/scripts desde npm |
304
476
 
305
- | Comando | Uso |
306
- |---|---|
307
- | `npm run nuevo` | Configura un curso desde consola |
308
- | `npm run semana -- 1` | Genera o activa la semana 1 |
309
- | `npm run dev` | Abre el portal principal |
310
- | `npm run dev:s1` | Abre la semana 1 |
311
- | `npm run pages:check` | Revisa configuración para GitHub Pages |
312
- | `npm run pages:build` | Construye el sitio estático y exporta descargas |
313
- | `npm run pages:preview` | Previsualiza la versión publicada |
314
- | `npm run publicar` | Ejecuta exportaciones y construcción local |
477
+ ---
478
+
479
+ ## 12. Archivos clave
480
+
481
+ ```text
482
+ openclass.config.json configuración general del curso
483
+ slides.md portal principal
484
+ semanas/ contenido académico real
485
+ curso_semanaN.md lanzadores raíz de cada semana
486
+ scripts/decks.mjs detección automática de semanas activas
487
+ scripts/build-site.mjs construcción de portal y semanas
488
+ scripts/export-downloads.mjs exportación de PDF/PPTX
489
+ .github/workflows/deploy.yml despliegue automático en GitHub Pages
490
+ theme/uniminuto/ tema institucional UNIMINUTO
491
+ public/imagenes/ imágenes del curso
492
+ public/descargas/ archivos PDF/PPTX exportados
493
+ ```
315
494
 
316
495
  ---
317
496
 
318
- ## 10. Archivos clave
497
+ ## 13. Recomendaciones antes de publicar
498
+
499
+ Antes de hacer `git push`, revisa:
500
+
501
+ ```bash
502
+ git status
503
+ npm run pages:build
504
+ ```
505
+
506
+ Confirma que existan las semanas generadas:
507
+
508
+ ```bash
509
+ ls dist/semanas
510
+ ```
511
+
512
+ En Windows PowerShell:
513
+
514
+ ```powershell
515
+ Get-ChildItem .\dist\semanas | Select-Object Name
516
+ ```
517
+
518
+ Confirma que una semana específica exista:
519
+
520
+ ```powershell
521
+ Test-Path .\dist\semanas\curso_semana1\index.html
522
+ ```
523
+
524
+ Si responde `True`, esa semana fue generada correctamente.
525
+
526
+ ---
527
+
528
+ ## 14. Problemas comunes
529
+
530
+ ### La semana abre localmente, pero no aparece en GitHub Pages
531
+
532
+ Verifica que exista el lanzador raíz:
533
+
534
+ ```text
535
+ curso_semanaN.md
536
+ ```
537
+
538
+ y que apunte al archivo real:
539
+
540
+ ```text
541
+ semanas/curso_semanaN.md
542
+ ```
543
+
544
+ Luego ejecuta:
545
+
546
+ ```bash
547
+ npm run pages:build
548
+ ```
549
+
550
+ ### Error con imágenes
551
+
552
+ Si aparece un error como:
553
+
554
+ ```text
555
+ Failed to resolve import "/imagenes/..."
556
+ ```
557
+
558
+ revisa que el archivo exista en:
319
559
 
320
560
  ```text
321
- openclass.config.json configuración general del curso
322
- slides.md portal principal
323
- semanas/ contenido académico real
324
- scripts/decks.mjs listado de presentaciones activas
325
- .github/workflows/deploy.yml despliegue automático en GitHub Pages
561
+ public/imagenes/
326
562
  ```
563
+
564
+ y que la ruta usada en la diapositiva tenga extensión correcta.
565
+
566
+ Ejemplo válido:
567
+
568
+ ```html
569
+ <img src="/imagenes/semana701.png" alt="Imagen de apoyo" />
570
+ ```
571
+
572
+ ### GitHub Pages no publica
573
+
574
+ Revisa:
575
+
576
+ ```text
577
+ Settings → Pages → Source → GitHub Actions
578
+ Actions → Deploy Open Class to GitHub Pages
579
+ ```
580
+
581
+ También puedes ejecutar:
582
+
583
+ ```bash
584
+ npm run pages:check
585
+ ```
586
+
587
+ ### Warnings de build
588
+
589
+ Algunos mensajes informativos no bloquean la publicación si el build termina con:
590
+
591
+ ```text
592
+ ✓ built
593
+ ✓ dist/.nojekyll creado para GitHub Pages.
594
+ ```
595
+
596
+ ---
597
+
598
+ ## 15. Actualizar este proyecto desde el generador local
599
+
600
+ Durante desarrollo del generador, también puedes aplicar la actualización de tema desde una copia local:
601
+
602
+ ```bash
603
+ node ../create-openclass-uniminuto/bin/create-openclass-uniminuto.mjs . --update-theme
604
+ ```
605
+
606
+ En Windows, desde una carpeta de curso ubicada dentro de `D:\OpenClass`:
607
+
608
+ ```powershell
609
+ node ..\create-openclass-uniminuto\bin\create-openclass-uniminuto.mjs . --update-theme
610
+ ```
611
+
612
+ Esto es útil para probar cambios antes de publicar una nueva versión npm.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclass-demo",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "description": "Presentaciones Open Class del curso Curso Open Class de ejemplo.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -43,7 +43,8 @@
43
43
  "pages:build": "npm run export:downloads && npm run build:all",
44
44
  "pages:preview": "npm run preview:pages",
45
45
  "actualizar:tema": "npm create openclass-uniminuto@latest . -- --update-theme",
46
- "actualizar:tema:preview": "npm run actualizar:tema && npm run dev"
46
+ "actualizar:tema:preview": "npm run actualizar:tema && npm run dev",
47
+ "dev:all": "node scripts/dev-all.mjs"
47
48
  },
48
49
  "dependencies": {
49
50
  "@fontsource/atkinson-hyperlegible": "^5.2.8",
@@ -1,7 +1,16 @@
1
+ import { readdirSync } from "node:fs";
2
+
1
3
  function normalizeBase(value) {
2
4
  let base = value || "/";
3
- if (!base.startsWith("/")) base = `/${base}`;
4
- if (!base.endsWith("/")) base = `${base}/`;
5
+
6
+ if (!base.startsWith("/")) {
7
+ base = `/${base}`;
8
+ }
9
+
10
+ if (!base.endsWith("/")) {
11
+ base = `${base}/`;
12
+ }
13
+
5
14
  return base;
6
15
  }
7
16
 
@@ -11,19 +20,48 @@ function withBase(path = "") {
11
20
  return `${SITE_BASE}${path.replace(/^\/+/, "")}`;
12
21
  }
13
22
 
23
+ function getWeekNumber(filename) {
24
+ const match = filename.match(/_semana(\d+)\.md$/i);
25
+ return match ? Number(match[1]) : 999;
26
+ }
27
+
28
+ function getDeckName(filename) {
29
+ return filename.replace(/\.md$/i, "");
30
+ }
31
+
32
+ const rootFiles = readdirSync(process.cwd(), { withFileTypes: true })
33
+ .filter((item) => item.isFile())
34
+ .map((item) => item.name);
35
+
36
+ const weeklyEntries = rootFiles
37
+ .filter((name) => /^[a-z0-9_-]+_semana\d+\.md$/i.test(name))
38
+ .filter((name) => !name.startsWith("demo_"))
39
+ .sort((a, b) => {
40
+ const weekDiff = getWeekNumber(a) - getWeekNumber(b);
41
+ return weekDiff !== 0 ? weekDiff : a.localeCompare(b);
42
+ });
43
+
44
+ const weeklyDecks = weeklyEntries.map((entry) => {
45
+ const name = getDeckName(entry);
46
+
47
+ return {
48
+ name,
49
+ entry,
50
+ out: `dist/semanas/${name}`,
51
+ base: withBase(`semanas/${name}/`),
52
+ exportable: true,
53
+ };
54
+ });
55
+
14
56
  export const decks = [
15
57
  {
16
- name: "openclass-demo",
58
+ name: "openclass-main",
17
59
  entry: "slides.md",
18
60
  out: "dist",
19
61
  base: SITE_BASE,
20
62
  exportable: false,
21
63
  },
22
- {
23
- name: "demo_semana1",
24
- entry: "demo_semana1.md",
25
- out: "dist/semanas/demo_semana1",
26
- base: withBase("semanas/demo_semana1/"),
27
- exportable: true,
28
- },
64
+ ...weeklyDecks,
29
65
  ];
66
+
67
+ export default decks;
@@ -1,5 +1,5 @@
1
- import { decks } from "./decks.mjs";
2
1
  import { spawn } from "node:child_process";
2
+ import { decks } from "./decks.mjs";
3
3
 
4
4
  const COLORS = [
5
5
  "bgBlue.bold",
@@ -11,27 +11,40 @@ const COLORS = [
11
11
  "blue.bold",
12
12
  "green.bold",
13
13
  "yellow.bold",
14
+ "magenta.bold",
15
+ "cyan.bold",
16
+ "red.bold",
14
17
  ];
15
18
 
16
- const semanas = decks.filter((deck) => deck.entry !== "slides.md");
17
19
  const BASE_PORT = 3000;
18
20
 
21
+ const weeklyDecks = decks.filter((deck) => deck.entry !== "slides.md");
22
+
19
23
  const commands = [
20
24
  `slidev slides.md --open --port ${BASE_PORT}`,
21
- ...semanas.map((deck, index) => `slidev ${deck.entry} --port ${BASE_PORT + index + 1}`),
25
+ ...weeklyDecks.map((deck, index) => {
26
+ return `slidev ${deck.entry} --port ${BASE_PORT + index + 1}`;
27
+ }),
22
28
  ];
23
29
 
24
- const names = ["portal", ...semanas.map((deck) => deck.name)].join(",");
30
+ const names = ["portal", ...weeklyDecks.map((deck) => deck.name)].join(",");
25
31
  const colors = COLORS.slice(0, commands.length).join(",");
26
32
 
27
- console.log("\n🚀 Iniciando servidores de desarrollo...");
33
+ console.log("");
34
+ console.log("🚀 Iniciando servidores de desarrollo...");
28
35
  console.log(` portal → http://localhost:${BASE_PORT}`);
29
- semanas.forEach((deck, index) => {
36
+
37
+ weeklyDecks.forEach((deck, index) => {
30
38
  console.log(` ${deck.name} → http://localhost:${BASE_PORT + index + 1}`);
31
39
  });
40
+
32
41
  console.log("");
33
42
 
34
- spawn("concurrently", ["-n", names, "-c", colors, ...commands], {
43
+ const child = spawn("concurrently", ["-n", names, "-c", colors, ...commands], {
35
44
  stdio: "inherit",
36
45
  shell: true,
37
46
  });
47
+
48
+ child.on("exit", (code) => {
49
+ process.exit(code ?? 0);
50
+ });
@@ -92,9 +92,9 @@
92
92
  overflow: hidden;
93
93
  }
94
94
 
95
- .uni-stack-slot :deep(p),
96
- .uni-image-slot :deep(p),
97
- .uni-media-slot :deep(p) {
95
+ .uni-stack-slot p,
96
+ .uni-image-slot p,
97
+ .uni-media-slot p {
98
98
  margin: 0;
99
99
  width: 100%;
100
100
  max-width: 100%;
@@ -105,8 +105,8 @@
105
105
  gap: 0.55rem;
106
106
  }
107
107
 
108
- .uni-stack-slot :deep(img),
109
- .uni-image-slot :deep(img) {
108
+ .uni-stack-slot img,
109
+ .uni-image-slot img {
110
110
  display: block;
111
111
  width: auto;
112
112
  height: auto;
@@ -116,9 +116,9 @@
116
116
  object-position: center;
117
117
  }
118
118
 
119
- .uni-media-slot :deep(img),
120
- .uni-media-slot :deep(video),
121
- .uni-media-slot :deep(iframe) {
119
+ .uni-media-slot img,
120
+ .uni-media-slot video,
121
+ .uni-media-slot iframe {
122
122
  display: block;
123
123
  width: 100%;
124
124
  height: 100%;
@@ -212,3 +212,4 @@
212
212
  background: rgba(242, 181, 27, 0.8);
213
213
  border-radius: 999px;
214
214
  }
215
+