create-openclass-uniminuto 1.4.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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +480 -0
  3. package/bin/create-openclass-uniminuto.mjs +142 -0
  4. package/package.json +39 -0
  5. package/template/.github/workflows/deploy.yml +64 -0
  6. package/template/README.md +326 -0
  7. package/template/config/openclass.config.iot-desde-openclass-iot.json +77 -0
  8. package/template/config/openclass.config.iot-ejemplo.json +81 -0
  9. package/template/demo_semana1.md +11 -0
  10. package/template/demo_semana2.md +11 -0
  11. package/template/demo_semana3.md +11 -0
  12. package/template/demo_semana4.md +11 -0
  13. package/template/demo_semana5.md +11 -0
  14. package/template/demo_semana6.md +11 -0
  15. package/template/demo_semana7.md +11 -0
  16. package/template/demo_semana8.md +11 -0
  17. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana1.md +12 -0
  18. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana2.md +12 -0
  19. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana3.md +12 -0
  20. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana4.md +12 -0
  21. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana5.md +12 -0
  22. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana6.md +12 -0
  23. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana7.md +12 -0
  24. package/template/ejemplos/iot-semanas-1-a-3/raiz/iot_semana8.md +12 -0
  25. package/template/ejemplos/iot-semanas-1-a-3/raiz/slides.md +154 -0
  26. package/template/ejemplos/iot-semanas-1-a-3/semanas/iot_semana1.md +846 -0
  27. package/template/ejemplos/iot-semanas-1-a-3/semanas/iot_semana2.md +1040 -0
  28. package/template/ejemplos/iot-semanas-1-a-3/semanas/iot_semana3.md +1071 -0
  29. package/template/openclass.config.json +79 -0
  30. package/template/package-lock.json +11568 -0
  31. package/template/package.json +61 -0
  32. package/template/plantillas/launcher.md +11 -0
  33. package/template/plantillas/semana.md +177 -0
  34. package/template/public/descargas/.gitkeep +0 -0
  35. package/template/public/favicon.png +0 -0
  36. package/template/public/fondos/slide-01-portada.png +0 -0
  37. package/template/public/fondos/slide-02-titulo.png +0 -0
  38. package/template/public/fondos/slide-03-imagen-izquierda.png +0 -0
  39. package/template/public/fondos/slide-04-imagen-derecha.png +0 -0
  40. package/template/public/fondos/slide-05-template.png +0 -0
  41. package/template/public/fondos/slide-06-cierre.png +0 -0
  42. package/template/public/imagenes/.gitkeep +0 -0
  43. package/template/public/videos/.gitkeep +0 -0
  44. package/template/scripts/build-incremental.mjs +33 -0
  45. package/template/scripts/build-site.mjs +33 -0
  46. package/template/scripts/decks.mjs +29 -0
  47. package/template/scripts/dev-all.mjs +37 -0
  48. package/template/scripts/export-downloads.mjs +53 -0
  49. package/template/scripts/export-incremental.mjs +49 -0
  50. package/template/scripts/generar-desde-config.mjs +279 -0
  51. package/template/scripts/nuevo-curso.mjs +104 -0
  52. package/template/scripts/preparar-github-pages.mjs +52 -0
  53. package/template/scripts/publicar.mjs +36 -0
  54. package/template/scripts/semana.mjs +122 -0
  55. package/template/scripts/zip-template.mjs +70 -0
  56. package/template/semanas/demo_semana1.md +177 -0
  57. package/template/semanas/demo_semana2.md +177 -0
  58. package/template/semanas/demo_semana3.md +177 -0
  59. package/template/semanas/demo_semana4.md +177 -0
  60. package/template/semanas/demo_semana5.md +177 -0
  61. package/template/semanas/demo_semana6.md +177 -0
  62. package/template/semanas/demo_semana7.md +177 -0
  63. package/template/semanas/demo_semana8.md +177 -0
  64. package/template/setup/shiki.ts +10 -0
  65. package/template/slides.md +65 -0
  66. package/template/snippets/external.ts +12 -0
  67. package/template/theme/uniminuto/README-AutoFit.md +28 -0
  68. package/template/theme/uniminuto/components/AutoFitText.vue +159 -0
  69. package/template/theme/uniminuto/components/Counter.vue +37 -0
  70. package/template/theme/uniminuto/components/FontToggle.vue +42 -0
  71. package/template/theme/uniminuto/layouts/slide-01-portada.vue +119 -0
  72. package/template/theme/uniminuto/layouts/slide-02-titulo.vue +63 -0
  73. package/template/theme/uniminuto/layouts/slide-03-imagen-izquierda.vue +110 -0
  74. package/template/theme/uniminuto/layouts/slide-04-imagen-derecha.vue +110 -0
  75. package/template/theme/uniminuto/layouts/slide-05-titulo-superior-texto-derecha.vue +104 -0
  76. package/template/theme/uniminuto/layouts/slide-06-titulo-superior-texto-izquierda.vue +109 -0
  77. package/template/theme/uniminuto/layouts/slide-07-multimedia-con-titulo.vue +87 -0
  78. package/template/theme/uniminuto/layouts/slide-08-titulo-texto.vue +78 -0
  79. package/template/theme/uniminuto/layouts/slide-09-objetivos.vue +77 -0
  80. package/template/theme/uniminuto/layouts/slide-10-titulo-dos-columnas.vue +89 -0
  81. package/template/theme/uniminuto/layouts/slide-11-dos-titulos-dos-columnas.vue +98 -0
  82. package/template/theme/uniminuto/layouts/slide-12-cierre.vue +27 -0
  83. package/template/theme/uniminuto/layouts/slide-codigo.vue +133 -0
  84. package/template/theme/uniminuto/package.json +13 -0
  85. package/template/theme/uniminuto/styles/base.css +109 -0
  86. package/template/theme/uniminuto/styles/index.ts +11 -0
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "openclass-demo",
3
+ "version": "1.0.0",
4
+ "description": "Presentaciones Open Class del curso Curso Open Class de ejemplo.",
5
+ "type": "module",
6
+ "private": true,
7
+ "scripts": {
8
+ "dev": "slidev slides.md --open --port 3000",
9
+ "config": "node scripts/generar-desde-config.mjs",
10
+ "dev:s1": "slidev demo_semana1.md --open --port 3001",
11
+ "dev:s2": "slidev demo_semana2.md --open --port 3002",
12
+ "dev:s3": "slidev demo_semana3.md --open --port 3003",
13
+ "dev:s4": "slidev demo_semana4.md --open --port 3004",
14
+ "dev:s5": "slidev demo_semana5.md --open --port 3005",
15
+ "dev:s6": "slidev demo_semana6.md --open --port 3006",
16
+ "dev:s7": "slidev demo_semana7.md --open --port 3007",
17
+ "dev:s8": "slidev demo_semana8.md --open --port 3008",
18
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
19
+ "clean:downloads": "node -e \"require('fs').rmSync('public/descargas',{recursive:true,force:true})\"",
20
+ "clean:cache": "node -e \"require('fs').rmSync('.slidev',{recursive:true,force:true}); require('fs').rmSync('node_modules/.vite',{recursive:true,force:true})\"",
21
+ "build:index": "slidev build slides.md --out dist --base / --without-notes",
22
+ "build:s1": "slidev build demo_semana1.md --out dist/semanas/demo_semana1 --base /semanas/demo_semana1/ --without-notes",
23
+ "build:s2": "slidev build demo_semana2.md --out dist/semanas/demo_semana2 --base /semanas/demo_semana2/ --without-notes",
24
+ "build:s3": "slidev build demo_semana3.md --out dist/semanas/demo_semana3 --base /semanas/demo_semana3/ --without-notes",
25
+ "build:s4": "slidev build demo_semana4.md --out dist/semanas/demo_semana4 --base /semanas/demo_semana4/ --without-notes",
26
+ "build:s5": "slidev build demo_semana5.md --out dist/semanas/demo_semana5 --base /semanas/demo_semana5/ --without-notes",
27
+ "build:s6": "slidev build demo_semana6.md --out dist/semanas/demo_semana6 --base /semanas/demo_semana6/ --without-notes",
28
+ "build:s7": "slidev build demo_semana7.md --out dist/semanas/demo_semana7 --base /semanas/demo_semana7/ --without-notes",
29
+ "build:s8": "slidev build demo_semana8.md --out dist/semanas/demo_semana8 --base /semanas/demo_semana8/ --without-notes",
30
+ "build:all": "node scripts/build-site.mjs",
31
+ "build:incremental": "node scripts/build-incremental.mjs",
32
+ "export:downloads": "node scripts/export-downloads.mjs",
33
+ "export:incremental": "node scripts/export-incremental.mjs",
34
+ "vista": "npm run clean && npm run export:downloads && npm run build:all && http-server dist -p 4173 -c-1 -o",
35
+ "publicar": "node scripts/publicar.mjs",
36
+ "dev:todo": "node scripts/dev-all.mjs",
37
+ "nuevo": "node scripts/nuevo-curso.mjs",
38
+ "zip:template": "node scripts/zip-template.mjs",
39
+ "preview:static": "npm run build:all && http-server dist -p 4173 -c-1",
40
+ "preview:pages": "npm run export:downloads && npm run build:all && http-server dist -p 4173 -c-1",
41
+ "semana": "node scripts/semana.mjs",
42
+ "pages:check": "node scripts/preparar-github-pages.mjs",
43
+ "pages:build": "npm run export:downloads && npm run build:all",
44
+ "pages:preview": "npm run preview:pages"
45
+ },
46
+ "dependencies": {
47
+ "@fontsource/atkinson-hyperlegible": "^5.2.8",
48
+ "@fontsource/merriweather-sans": "^5.2.7",
49
+ "@fontsource/opendyslexic": "^5.2.5",
50
+ "@slidev/theme-seriph": "latest",
51
+ "vue": "^3.5.33"
52
+ },
53
+ "devDependencies": {
54
+ "@slidev/cli": "^52.15.0",
55
+ "@slidev/theme-default": "^0.25.0",
56
+ "concurrently": "^9.2.1",
57
+ "http-server": "^14.1.1",
58
+ "playwright-chromium": "^1.59.1",
59
+ "vite": "^7.1.12"
60
+ }
61
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ theme: ./theme/uniminuto
3
+ title: {{COURSE_NAME}} — Semana {{WEEK_NUMBER}} — {{WEEK_TITLE}}
4
+ favicon: /favicon.png
5
+ codeCopy: true
6
+ transition: fade
7
+ routerMode: hash
8
+ drawings:
9
+ persist: false
10
+ src: ./semanas/{{COURSE_SHORT}}_semana{{WEEK_NUMBER}}.md
11
+ ---
@@ -0,0 +1,177 @@
1
+ ---
2
+ layout: slide-01-portada
3
+ ---
4
+
5
+ ::title::
6
+ {{COURSE_NAME}}
7
+
8
+ ::week::
9
+ Semana {{WEEK_NUMBER}} — {{WEEK_TITLE}}
10
+
11
+ ::date::
12
+ {{WEEK_DATE}}
13
+
14
+ ---
15
+ layout: slide-09-objetivos
16
+ ---
17
+
18
+ ::title::
19
+ Objetivos de la sesiĂłn
20
+
21
+ ::content::
22
+ Al terminar esta sesión, el estudiante estará en capacidad de:
23
+
24
+ - Reconocer los conceptos centrales asociados con **{{WEEK_TITLE}}**.
25
+ - Relacionar la temática de la semana con situaciones académicas, profesionales o institucionales.
26
+ - Desarrollar una actividad breve que evidencie comprensión, análisis y aplicación.
27
+
28
+ <!--
29
+ Notas del presentador:
30
+ Presentar los objetivos como una ruta de trabajo. Conectar cada objetivo con la actividad o evaluaciĂłn de la semana para que el estudiante comprenda el sentido formativo de la sesiĂłn.
31
+ -->
32
+
33
+ ---
34
+ layout: slide-08-titulo-texto
35
+ ---
36
+
37
+ ::title::
38
+ Agenda de la Open Class
39
+
40
+ ::content::
41
+ La sesión se desarrollará en **90 minutos**:
42
+
43
+ - Bienvenida y encuadre inicial.
44
+ - Contextualización de la temática de la semana.
45
+ - Desarrollo conceptual con ejemplos.
46
+ - Actividad didáctica breve.
47
+ - SocializaciĂłn de hallazgos.
48
+ - ResoluciĂłn de dudas.
49
+ - Cierre académico y recordatorio de la Encuesta de Percepción Estudiantil.
50
+
51
+ <!--
52
+ Notas del presentador:
53
+ Recordar la tolerancia máxima de cinco minutos para iniciar. Mantener la actividad didáctica en un tiempo máximo aproximado de veinte minutos y reservar un bloque final para preguntas.
54
+ -->
55
+
56
+ ---
57
+ layout: slide-08-titulo-texto
58
+ ---
59
+
60
+ ::title::
61
+ ContextualizaciĂłn de la semana
62
+
63
+ ::content::
64
+ Esta semana se aborda **{{WEEK_TITLE}}** como eje para comprender problemas, decisiones y aplicaciones propias del curso.
65
+
66
+ **Tema central:** {{WEEK_THEME}}
67
+
68
+ La intención es conectar el contenido con casos reales, experiencias profesionales y criterios de análisis que permitan pasar de la comprensión conceptual a la aplicación práctica.
69
+
70
+ <!--
71
+ Notas del presentador:
72
+ Iniciar con una pregunta detonante o un ejemplo cercano al contexto del grupo. Evitar una exposiciĂłn Ăşnicamente teĂłrica: llevar el tema hacia decisiones, consecuencias, riesgos, oportunidades o productos concretos.
73
+ -->
74
+
75
+ ---
76
+ layout: slide-10-titulo-dos-columnas
77
+ ---
78
+
79
+ ::title::
80
+ Desarrollo conceptual
81
+
82
+ ::left::
83
+ **Ideas clave**
84
+
85
+ - Concepto principal de la semana.
86
+ - Elementos, componentes o criterios asociados.
87
+ - RelaciĂłn con el propĂłsito del curso.
88
+ - Aplicaciones en contextos reales.
89
+
90
+ ::right::
91
+ **Preguntas orientadoras**
92
+
93
+ - ¿Qué problema permite comprender o resolver este tema?
94
+ - ¿Qué decisiones se pueden tomar a partir de este conocimiento?
95
+ - ¿Qué evidencias muestran que el estudiante comprendió el tema?
96
+
97
+ <!--
98
+ Notas del presentador:
99
+ Usar esta diapositiva para organizar la explicaciĂłn central. Reemplazar los puntos por los conceptos especĂ­ficos del curso y de la semana.
100
+ -->
101
+
102
+ ---
103
+ layout: slide-10-titulo-dos-columnas
104
+ ---
105
+
106
+ ::title::
107
+ Actividad didáctica breve
108
+
109
+ ::left::
110
+ **Instrucciones**
111
+
112
+ - Organizar el trabajo de forma individual, en parejas o en pequeños grupos.
113
+ - Analizar el caso, pregunta o reto propuesto por el docente.
114
+ - Construir una respuesta breve y justificable.
115
+ - Socializar una conclusiĂłn en plenaria.
116
+
117
+ ::right::
118
+ **Producto esperado**
119
+
120
+ {{WEEK_ACTIVITY}}
121
+
122
+ La evidencia puede presentarse como una respuesta argumentada, esquema, captura, simulaciĂłn, reflexiĂłn, mapa breve o producto digital, segĂşn la orientaciĂłn del docente.
123
+
124
+ <!--
125
+ Notas del presentador:
126
+ Controlar el tiempo de la actividad. Se recomienda no superar veinte minutos para conservar espacio de socializaciĂłn y dudas.
127
+ -->
128
+
129
+ ---
130
+ layout: slide-08-titulo-texto
131
+ ---
132
+
133
+ ::title::
134
+ RelaciĂłn con la evaluaciĂłn
135
+
136
+ ::content::
137
+ El trabajo de la semana se articula con la actividad o evaluaciĂłn del curso mediante:
138
+
139
+ - ComprensiĂłn de conceptos clave.
140
+ - Aplicación en un caso o situación práctica.
141
+ - JustificaciĂłn de decisiones tomadas.
142
+ - ComunicaciĂłn clara de resultados.
143
+ - RevisiĂłn de evidencias y criterios de calidad.
144
+
145
+ <!--
146
+ Notas del presentador:
147
+ Explicar qué debe cuidar el estudiante para avanzar en la actividad evaluativa. Precisar si se requiere entrega en aula virtual, participación en foro, documento, evidencia audiovisual, práctica o cuestionario.
148
+ -->
149
+
150
+ ---
151
+ layout: slide-08-titulo-texto
152
+ ---
153
+
154
+ ::title::
155
+ ResoluciĂłn de dudas
156
+
157
+ ::content::
158
+ Este espacio se orienta a resolver inquietudes sobre:
159
+
160
+ - Conceptos revisados durante la sesiĂłn.
161
+ - Actividad práctica o evaluación relacionada.
162
+ - Criterios de entrega y evidencias esperadas.
163
+ - Uso de herramientas, recursos o materiales de apoyo.
164
+
165
+ <!--
166
+ Notas del presentador:
167
+ Mantener este bloque dentro de un máximo aproximado de quince minutos. Priorizar dudas que afecten la comprensión del tema o la entrega de la actividad.
168
+ -->
169
+
170
+ ---
171
+ layout: slide-12-cierre
172
+ ---
173
+
174
+ <!--
175
+ Notas del presentador:
176
+ Cerrar con una síntesis de tres ideas centrales, recordar el compromiso académico de la semana e invitar a diligenciar la Encuesta de Percepción Estudiantil cuando aplique.
177
+ -->
File without changes
Binary file
File without changes
File without changes
@@ -0,0 +1,33 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { spawnSync } from 'node:child_process';
4
+ import { decks } from './decks.mjs';
5
+
6
+ const isWindows = process.platform === 'win32';
7
+
8
+ function run(args) {
9
+ const result = spawnSync('npx', ['slidev', 'build', ...args], {
10
+ stdio: 'inherit',
11
+ shell: isWindows,
12
+ });
13
+ if (result.status !== 0) process.exit(result.status ?? 1);
14
+ }
15
+
16
+ let built = 0;
17
+ for (const deck of decks) {
18
+ const marker = path.join(deck.out, 'index.html');
19
+ if (fs.existsSync(marker)) {
20
+ console.log(`⏭ Omitiendo: ${deck.name} (ya existe en ${deck.out})`);
21
+ continue;
22
+ }
23
+ console.log(`\n🔨 Construyendo: ${deck.name}`);
24
+ run([deck.entry, '--out', deck.out, '--base', deck.base, '--without-notes']);
25
+ built++;
26
+ }
27
+
28
+ if (built === 0) {
29
+ console.log('\n✅ Todo está al día. No se construyó ninguna presentación nueva.');
30
+ console.log(' Para forzar una reconstrucciĂłn, elimina la carpeta dist/ y ejecuta build:all.\n');
31
+ } else {
32
+ console.log(`\nâś… Listo. Se construyeron ${built} presentaciĂłn(es) nueva(s).\n`);
33
+ }
@@ -0,0 +1,33 @@
1
+ import fs from "node:fs";
2
+ import { spawnSync } from "node:child_process";
3
+ import { decks } from "./decks.mjs";
4
+
5
+ const isWindows = process.platform === "win32";
6
+
7
+ fs.rmSync("dist", { recursive: true, force: true });
8
+
9
+ function run(args) {
10
+ const result = spawnSync("npx", ["slidev", "build", ...args], {
11
+ stdio: "inherit",
12
+ shell: isWindows,
13
+ });
14
+
15
+ if (result.status !== 0) {
16
+ process.exit(result.status ?? 1);
17
+ }
18
+ }
19
+
20
+ for (const deck of decks) {
21
+ console.log(`\nConstruyendo: ${deck.name}`);
22
+
23
+ run([
24
+ deck.entry,
25
+ "--out",
26
+ deck.out,
27
+ "--base",
28
+ deck.base,
29
+ "--without-notes",
30
+ ]);
31
+ }
32
+ fs.writeFileSync("dist/.nojekyll", "", "utf-8");
33
+ console.log("\nâś“ dist/.nojekyll creado para GitHub Pages.\n");
@@ -0,0 +1,29 @@
1
+ function normalizeBase(value) {
2
+ let base = value || "/";
3
+ if (!base.startsWith("/")) base = `/${base}`;
4
+ if (!base.endsWith("/")) base = `${base}/`;
5
+ return base;
6
+ }
7
+
8
+ const SITE_BASE = normalizeBase(process.env.SITE_BASE || "/");
9
+
10
+ function withBase(path = "") {
11
+ return `${SITE_BASE}${path.replace(/^\/+/, "")}`;
12
+ }
13
+
14
+ export const decks = [
15
+ {
16
+ name: "openclass-demo",
17
+ entry: "slides.md",
18
+ out: "dist",
19
+ base: SITE_BASE,
20
+ exportable: false,
21
+ },
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
+ },
29
+ ];
@@ -0,0 +1,37 @@
1
+ import { decks } from "./decks.mjs";
2
+ import { spawn } from "node:child_process";
3
+
4
+ const COLORS = [
5
+ "bgBlue.bold",
6
+ "bgGreen.bold",
7
+ "bgYellow.bold",
8
+ "bgMagenta.bold",
9
+ "bgCyan.bold",
10
+ "bgRed.bold",
11
+ "blue.bold",
12
+ "green.bold",
13
+ "yellow.bold",
14
+ ];
15
+
16
+ const semanas = decks.filter((deck) => deck.entry !== "slides.md");
17
+ const BASE_PORT = 3000;
18
+
19
+ const commands = [
20
+ `slidev slides.md --open --port ${BASE_PORT}`,
21
+ ...semanas.map((deck, index) => `slidev ${deck.entry} --port ${BASE_PORT + index + 1}`),
22
+ ];
23
+
24
+ const names = ["portal", ...semanas.map((deck) => deck.name)].join(",");
25
+ const colors = COLORS.slice(0, commands.length).join(",");
26
+
27
+ console.log("\n🚀 Iniciando servidores de desarrollo...");
28
+ console.log(` portal → http://localhost:${BASE_PORT}`);
29
+ semanas.forEach((deck, index) => {
30
+ console.log(` ${deck.name} → http://localhost:${BASE_PORT + index + 1}`);
31
+ });
32
+ console.log("");
33
+
34
+ spawn("concurrently", ["-n", names, "-c", colors, ...commands], {
35
+ stdio: "inherit",
36
+ shell: true,
37
+ });
@@ -0,0 +1,53 @@
1
+ import fs from "node:fs";
2
+ import { spawnSync } from "node:child_process";
3
+ import { decks } from "./decks.mjs";
4
+
5
+ const isWindows = process.platform === "win32";
6
+
7
+ fs.mkdirSync("public/descargas", { recursive: true });
8
+
9
+ const commonExportOptions = [
10
+ "--timeout",
11
+ "120000",
12
+ "--wait",
13
+ "3000",
14
+ "--wait-until",
15
+ "none",
16
+ ];
17
+
18
+ function run(args) {
19
+ const result = spawnSync("npx", ["slidev", "export", ...args], {
20
+ stdio: "inherit",
21
+ shell: isWindows,
22
+ });
23
+
24
+ if (result.status !== 0) {
25
+ process.exit(result.status ?? 1);
26
+ }
27
+ }
28
+
29
+ for (const deck of decks.filter((deck) => deck.exportable)) {
30
+ console.log(`\nExportando PDF: ${deck.name}`);
31
+
32
+ run([
33
+ deck.entry,
34
+ "--format",
35
+ "pdf",
36
+ ...commonExportOptions,
37
+ "--output",
38
+ `public/descargas/${deck.name}.pdf`,
39
+ ]);
40
+
41
+ console.log(`\nExportando PPTX: ${deck.name}`);
42
+
43
+ run([
44
+ deck.entry,
45
+ "--format",
46
+ "pptx",
47
+ "--with-clicks",
48
+ "false",
49
+ ...commonExportOptions,
50
+ "--output",
51
+ `public/descargas/${deck.name}.pptx`,
52
+ ]);
53
+ }
@@ -0,0 +1,49 @@
1
+ import fs from 'node:fs';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { decks } from './decks.mjs';
4
+
5
+ const isWindows = process.platform === 'win32';
6
+
7
+ fs.mkdirSync('public/descargas', { recursive: true });
8
+
9
+ const commonOptions = ['--timeout', '120000', '--wait', '3000', '--wait-until', 'none'];
10
+
11
+ function run(args) {
12
+ const result = spawnSync('npx', ['slidev', 'export', ...args], {
13
+ stdio: 'inherit',
14
+ shell: isWindows,
15
+ });
16
+ if (result.status !== 0) process.exit(result.status ?? 1);
17
+ }
18
+
19
+ let exported = 0;
20
+ for (const deck of decks.filter(d => d.exportable)) {
21
+ const pdf = `public/descargas/${deck.name}.pdf`;
22
+ const pptx = `public/descargas/${deck.name}.pptx`;
23
+ const pdfOk = fs.existsSync(pdf);
24
+ const pptxOk = fs.existsSync(pptx);
25
+
26
+ if (pdfOk && pptxOk) {
27
+ console.log(`⏭ Omitiendo: ${deck.name} (PDF y PPTX ya existen)`);
28
+ continue;
29
+ }
30
+
31
+ if (!pdfOk) {
32
+ console.log(`\nExportando PDF: ${deck.name}`);
33
+ run([deck.entry, '--format', 'pdf', ...commonOptions, '--output', pdf]);
34
+ exported++;
35
+ }
36
+
37
+ if (!pptxOk) {
38
+ console.log(`\nExportando PPTX: ${deck.name}`);
39
+ run([deck.entry, '--format', 'pptx', '--with-clicks', 'false', ...commonOptions, '--output', pptx]);
40
+ exported++;
41
+ }
42
+ }
43
+
44
+ if (exported === 0) {
45
+ console.log('\n✅ Todo está al día. No se exportó ningún archivo nuevo.');
46
+ console.log(' Para forzar una re-exportaciĂłn, elimina los archivos en public/descargas/.\n');
47
+ } else {
48
+ console.log(`\nâś… Listo. Se exportaron ${exported} archivo(s) nuevo(s).\n`);
49
+ }