create-openclass-uniminuto 1.6.1 → 1.6.4
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.
- package/bin/create-openclass-uniminuto.mjs +333 -59
- package/package.json +1 -1
- package/template/.github/workflows/deploy.yml +2 -2
- package/template/README.md +477 -149
- package/template/demo_semana1.md +1 -1
- package/template/demo_semana2.md +1 -1
- package/template/demo_semana3.md +1 -1
- package/template/demo_semana4.md +1 -1
- package/template/demo_semana5.md +1 -1
- package/template/demo_semana6.md +1 -1
- package/template/demo_semana7.md +1 -1
- package/template/demo_semana8.md +1 -1
- package/template/package-lock.json +11568 -11568
- package/template/package.json +63 -63
- package/template/plantillas/launcher.md +1 -1
- package/template/plantillas/semana.md +214 -88
- package/template/scripts/decks.mjs +13 -4
- package/template/scripts/dev-all.mjs +20 -7
- package/template/scripts/generar-desde-config.mjs +312 -48
- package/template/slides.md +1 -1
- package/template/theme/uniminuto/styles/base.css +9 -8
|
@@ -6,17 +6,39 @@ import { spawnSync } from "node:child_process";
|
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
9
10
|
const packageRoot = path.resolve(__dirname, "..");
|
|
10
11
|
const templateRoot = path.join(packageRoot, "template");
|
|
11
12
|
|
|
12
13
|
const args = process.argv.slice(2);
|
|
13
14
|
const flags = new Set(args.filter((arg) => arg.startsWith("--")));
|
|
14
15
|
const positional = args.filter((arg) => !arg.startsWith("--"));
|
|
16
|
+
|
|
15
17
|
const targetArg = positional[0] || "openclass-uniminuto";
|
|
16
18
|
const targetDir = path.resolve(process.cwd(), targetArg);
|
|
17
19
|
const isCurrentDirectoryTarget = targetArg === "." || targetArg === "./";
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
+
|
|
21
|
+
const IGNORED_DIRS = new Set(["node_modules", "dist", ".slidev", ".git"]);
|
|
22
|
+
const IGNORED_FILES = new Set(["audit-report.json"]);
|
|
23
|
+
const IGNORED_EXTENSIONS = new Set([".tgz"]);
|
|
24
|
+
|
|
25
|
+
function envFlag(name) {
|
|
26
|
+
const value = process.env[name];
|
|
27
|
+
|
|
28
|
+
if (value === undefined) return false;
|
|
29
|
+
|
|
30
|
+
return ["1", "true", "yes", "on"].includes(String(value).toLowerCase());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const forceOverwrite =
|
|
34
|
+
flags.has("--force") ||
|
|
35
|
+
envFlag("npm_config_force");
|
|
36
|
+
|
|
37
|
+
const updateTheme =
|
|
38
|
+
flags.has("--update-theme") ||
|
|
39
|
+
flags.has("--sync-theme") ||
|
|
40
|
+
envFlag("npm_config_update_theme") ||
|
|
41
|
+
envFlag("npm_config_sync_theme");
|
|
20
42
|
|
|
21
43
|
function log(message = "") {
|
|
22
44
|
console.log(message);
|
|
@@ -27,31 +49,73 @@ function fail(message) {
|
|
|
27
49
|
process.exit(1);
|
|
28
50
|
}
|
|
29
51
|
|
|
52
|
+
function shouldIgnore(src) {
|
|
53
|
+
const base = path.basename(src);
|
|
54
|
+
const ext = path.extname(src).toLowerCase();
|
|
55
|
+
|
|
56
|
+
return IGNORED_DIRS.has(base) || IGNORED_FILES.has(base) || IGNORED_EXTENSIONS.has(ext);
|
|
57
|
+
}
|
|
58
|
+
|
|
30
59
|
function cleanPackageName(value) {
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
60
|
+
return (
|
|
61
|
+
String(value || "openclass-uniminuto")
|
|
62
|
+
.normalize("NFD")
|
|
63
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
64
|
+
.toLowerCase()
|
|
65
|
+
.replace(/[^a-z0-9.-]+/g, "-")
|
|
66
|
+
.replace(/^-+|-+$/g, "") || "openclass-uniminuto"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function relativeToTarget(filePath) {
|
|
71
|
+
return path.relative(targetDir, filePath).replaceAll("\\", "/");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readJson(filePath) {
|
|
75
|
+
if (!fs.existsSync(filePath)) return null;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
79
|
+
} catch (error) {
|
|
80
|
+
fail(`No se pudo leer JSON válido en ${filePath}\n${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function writeJson(filePath, data) {
|
|
85
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
86
|
+
fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf-8");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function patchJson(filePath, patcher) {
|
|
90
|
+
const data = readJson(filePath);
|
|
91
|
+
|
|
92
|
+
if (!data) return false;
|
|
93
|
+
|
|
94
|
+
patcher(data);
|
|
95
|
+
writeJson(filePath, data);
|
|
96
|
+
|
|
97
|
+
return true;
|
|
37
98
|
}
|
|
38
99
|
|
|
39
100
|
function copyTemplate(src, dest) {
|
|
40
|
-
|
|
41
|
-
if (["node_modules", "dist", ".slidev", ".git"].includes(base)) return;
|
|
101
|
+
if (shouldIgnore(src)) return;
|
|
42
102
|
|
|
43
103
|
const stat = fs.statSync(src);
|
|
104
|
+
|
|
44
105
|
if (stat.isDirectory()) {
|
|
45
106
|
fs.mkdirSync(dest, { recursive: true });
|
|
107
|
+
|
|
46
108
|
for (const child of fs.readdirSync(src)) {
|
|
47
109
|
copyTemplate(path.join(src, child), path.join(dest, child));
|
|
48
110
|
}
|
|
111
|
+
|
|
49
112
|
return;
|
|
50
113
|
}
|
|
51
114
|
|
|
52
115
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
116
|
+
|
|
53
117
|
if (fs.existsSync(dest) && !forceOverwrite) {
|
|
54
|
-
log(`↷ Conservado archivo existente: ${
|
|
118
|
+
log(`↷ Conservado archivo existente: ${relativeToTarget(dest)}`);
|
|
55
119
|
return;
|
|
56
120
|
}
|
|
57
121
|
|
|
@@ -59,33 +123,172 @@ function copyTemplate(src, dest) {
|
|
|
59
123
|
}
|
|
60
124
|
|
|
61
125
|
function copyPathAlways(src, dest) {
|
|
62
|
-
|
|
63
|
-
if (["node_modules", "dist", ".slidev", ".git"].includes(base)) return;
|
|
64
|
-
|
|
65
|
-
if (!fs.existsSync(src)) return;
|
|
126
|
+
if (!fs.existsSync(src) || shouldIgnore(src)) return;
|
|
66
127
|
|
|
67
128
|
const stat = fs.statSync(src);
|
|
129
|
+
|
|
68
130
|
if (stat.isDirectory()) {
|
|
69
131
|
fs.mkdirSync(dest, { recursive: true });
|
|
132
|
+
|
|
70
133
|
for (const child of fs.readdirSync(src)) {
|
|
71
134
|
copyPathAlways(path.join(src, child), path.join(dest, child));
|
|
72
135
|
}
|
|
136
|
+
|
|
73
137
|
return;
|
|
74
138
|
}
|
|
75
139
|
|
|
76
140
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
77
141
|
fs.copyFileSync(src, dest);
|
|
78
|
-
|
|
142
|
+
|
|
143
|
+
log(`✓ Actualizado: ${relativeToTarget(dest)}`);
|
|
79
144
|
}
|
|
80
145
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
|
|
146
|
+
function copyPathIfMissing(src, dest) {
|
|
147
|
+
if (!fs.existsSync(src) || shouldIgnore(src)) return false;
|
|
148
|
+
|
|
149
|
+
if (fs.existsSync(dest)) {
|
|
150
|
+
log(`⏭ Conservado: ${relativeToTarget(dest)}`);
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const stat = fs.statSync(src);
|
|
155
|
+
|
|
156
|
+
if (stat.isDirectory()) {
|
|
157
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
158
|
+
|
|
159
|
+
for (const child of fs.readdirSync(src)) {
|
|
160
|
+
copyPathIfMissing(path.join(src, child), path.join(dest, child));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
86
166
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
87
167
|
fs.copyFileSync(src, dest);
|
|
88
|
-
|
|
168
|
+
|
|
169
|
+
log(`✓ Creado: ${relativeToTarget(dest)}`);
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function copyTemplatePathAlways(relativePath) {
|
|
174
|
+
copyPathAlways(path.join(templateRoot, relativePath), path.join(targetDir, relativePath));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function copyTemplatePathIfMissing(relativePath) {
|
|
178
|
+
copyPathIfMissing(path.join(templateRoot, relativePath), path.join(targetDir, relativePath));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function appendGitignoreRules() {
|
|
182
|
+
const gitignorePath = path.join(targetDir, ".gitignore");
|
|
183
|
+
|
|
184
|
+
const rules = [
|
|
185
|
+
"",
|
|
186
|
+
"# Archivos generados por exportación Slidev",
|
|
187
|
+
"public/descargas/*.pdf",
|
|
188
|
+
"public/descargas/*.pptx",
|
|
189
|
+
"!public/descargas/.gitkeep",
|
|
190
|
+
"",
|
|
191
|
+
"# Reportes locales de auditoría",
|
|
192
|
+
"audit-report.json",
|
|
193
|
+
"",
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const existing = fs.existsSync(gitignorePath)
|
|
197
|
+
? fs.readFileSync(gitignorePath, "utf-8")
|
|
198
|
+
: "";
|
|
199
|
+
|
|
200
|
+
const missingRules = rules.filter((rule) => {
|
|
201
|
+
if (rule.trim() === "") return false;
|
|
202
|
+
if (rule.startsWith("#")) return false;
|
|
203
|
+
return !existing.split(/\r?\n/).includes(rule);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
if (!missingRules.length) {
|
|
207
|
+
log("⏭ .gitignore ya contiene las reglas necesarias.");
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const block = rules.join("\n");
|
|
212
|
+
const separator = existing.endsWith("\n") || existing.length === 0 ? "" : "\n";
|
|
213
|
+
|
|
214
|
+
fs.writeFileSync(gitignorePath, `${existing}${separator}${block}`, "utf-8");
|
|
215
|
+
log("✓ Actualizado: .gitignore");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function mergeObject(target, source) {
|
|
219
|
+
if (!source || typeof source !== "object") return target || {};
|
|
220
|
+
|
|
221
|
+
const output = target && typeof target === "object" ? { ...target } : {};
|
|
222
|
+
|
|
223
|
+
for (const [key, value] of Object.entries(source)) {
|
|
224
|
+
output[key] = value;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return output;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function mergePackageFromTemplate({ updateName = false } = {}) {
|
|
231
|
+
const templatePackagePath = path.join(templateRoot, "package.json");
|
|
232
|
+
const targetPackagePath = path.join(targetDir, "package.json");
|
|
233
|
+
|
|
234
|
+
const templatePackage = readJson(templatePackagePath);
|
|
235
|
+
const targetPackage = readJson(targetPackagePath);
|
|
236
|
+
|
|
237
|
+
if (!templatePackage || !targetPackage) return;
|
|
238
|
+
|
|
239
|
+
if (updateName) {
|
|
240
|
+
targetPackage.name = cleanPackageName(path.basename(targetDir));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
targetPackage.scripts = mergeObject(targetPackage.scripts, {
|
|
244
|
+
dev: targetPackage.scripts?.dev || "slidev slides.md --open --port 3000",
|
|
245
|
+
config: "node scripts/generar-desde-config.mjs",
|
|
246
|
+
semana: "node scripts/semana.mjs",
|
|
247
|
+
"pages:check": "node scripts/preparar-github-pages.mjs",
|
|
248
|
+
"actualizar:tema": "npm create openclass-uniminuto@latest . -- --update-theme",
|
|
249
|
+
"actualizar:tema:preview": "npm run actualizar:tema && npm run config && npm run dev",
|
|
250
|
+
"dev:all": "node scripts/dev-all.mjs",
|
|
251
|
+
"dev:todo": "node scripts/dev-all.mjs",
|
|
252
|
+
"build:all": "node scripts/build-site.mjs",
|
|
253
|
+
"build:incremental": "node scripts/build-incremental.mjs",
|
|
254
|
+
"export:downloads": "node scripts/export-downloads.mjs",
|
|
255
|
+
"export:incremental": "node scripts/export-incremental.mjs",
|
|
256
|
+
"pages:build": "npm run config && npm run export:downloads && npm run build:all",
|
|
257
|
+
"pages:preview": "npm run preview:pages",
|
|
258
|
+
publicar: "node scripts/publicar.mjs",
|
|
259
|
+
nuevo: "node scripts/nuevo-curso.mjs",
|
|
260
|
+
"zip:template": "node scripts/zip-template.mjs",
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
targetPackage.dependencies = mergeObject(
|
|
264
|
+
targetPackage.dependencies,
|
|
265
|
+
templatePackage.dependencies,
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
targetPackage.devDependencies = mergeObject(
|
|
269
|
+
targetPackage.devDependencies,
|
|
270
|
+
templatePackage.devDependencies,
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
writeJson(targetPackagePath, targetPackage);
|
|
274
|
+
log("✓ Actualizado: package.json");
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function patchPackageLockName() {
|
|
278
|
+
const lockPath = path.join(targetDir, "package-lock.json");
|
|
279
|
+
const lock = readJson(lockPath);
|
|
280
|
+
|
|
281
|
+
if (!lock) return;
|
|
282
|
+
|
|
283
|
+
const innerName = cleanPackageName(path.basename(targetDir));
|
|
284
|
+
|
|
285
|
+
lock.name = innerName;
|
|
286
|
+
|
|
287
|
+
if (lock.packages && lock.packages[""]) {
|
|
288
|
+
lock.packages[""].name = innerName;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
writeJson(lockPath, lock);
|
|
89
292
|
}
|
|
90
293
|
|
|
91
294
|
function updateThemeOnly() {
|
|
@@ -94,47 +297,79 @@ function updateThemeOnly() {
|
|
|
94
297
|
}
|
|
95
298
|
|
|
96
299
|
log("\n┌──────────────────────────────────────────────┐");
|
|
97
|
-
log("│ Actualizar
|
|
300
|
+
log("│ Actualizar infraestructura Open Class │");
|
|
98
301
|
log("└──────────────────────────────────────────────┘\n");
|
|
99
302
|
log(`Destino: ${targetDir}`);
|
|
100
|
-
log("Modo:
|
|
303
|
+
log("Modo: actualizar tema, scripts, plantillas y recursos base seguros.\n");
|
|
304
|
+
log("No se sobrescriben: semanas/, slides.md ni openclass.config.json existente.\n");
|
|
101
305
|
|
|
102
306
|
const pathsToUpdate = [
|
|
307
|
+
"README.md",
|
|
308
|
+
|
|
103
309
|
"theme/uniminuto/components",
|
|
104
310
|
"theme/uniminuto/layouts",
|
|
105
311
|
"theme/uniminuto/styles",
|
|
106
312
|
"theme/uniminuto/package.json",
|
|
107
313
|
"theme/uniminuto/README-AutoFit.md",
|
|
314
|
+
|
|
108
315
|
"setup",
|
|
109
|
-
"snippets"
|
|
316
|
+
"snippets",
|
|
317
|
+
|
|
318
|
+
"scripts/build-site.mjs",
|
|
319
|
+
"scripts/build-incremental.mjs",
|
|
320
|
+
"scripts/decks.mjs",
|
|
321
|
+
"scripts/dev-all.mjs",
|
|
322
|
+
"scripts/export-downloads.mjs",
|
|
323
|
+
"scripts/export-incremental.mjs",
|
|
324
|
+
"scripts/generar-desde-config.mjs",
|
|
325
|
+
"scripts/nuevo-curso.mjs",
|
|
326
|
+
"scripts/preparar-github-pages.mjs",
|
|
327
|
+
"scripts/publicar.mjs",
|
|
328
|
+
"scripts/semana.mjs",
|
|
329
|
+
"scripts/zip-template.mjs",
|
|
330
|
+
|
|
331
|
+
"plantillas",
|
|
332
|
+
|
|
333
|
+
".github/workflows/deploy.yml",
|
|
334
|
+
|
|
335
|
+
"public/fondos",
|
|
110
336
|
];
|
|
111
337
|
|
|
112
338
|
for (const relativePath of pathsToUpdate) {
|
|
113
|
-
|
|
339
|
+
copyTemplatePathAlways(relativePath);
|
|
114
340
|
}
|
|
115
341
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
342
|
+
copyTemplatePathIfMissing("openclass.config.json");
|
|
343
|
+
|
|
344
|
+
copyTemplatePathIfMissing("public/descargas/.gitkeep");
|
|
345
|
+
copyTemplatePathIfMissing("public/videos/.gitkeep");
|
|
346
|
+
copyTemplatePathIfMissing("public/imagenes/.gitkeep");
|
|
347
|
+
|
|
348
|
+
copyTemplatePathIfMissing("public/favicon.png");
|
|
349
|
+
copyTemplatePathIfMissing("public/imagenes/favicon.png");
|
|
119
350
|
|
|
120
|
-
|
|
351
|
+
copyTemplatePathAlways("public/imagenes/avion.png");
|
|
352
|
+
|
|
353
|
+
appendGitignoreRules();
|
|
354
|
+
|
|
355
|
+
mergePackageFromTemplate({ updateName: false });
|
|
356
|
+
|
|
357
|
+
log("\n✅ Infraestructura actualizada sin tocar el contenido académico.");
|
|
121
358
|
log(" Recomendado ahora:");
|
|
122
|
-
log(" npm
|
|
123
|
-
log(" npm run
|
|
359
|
+
log(" npm install");
|
|
360
|
+
log(" npm run config");
|
|
361
|
+
log(" npm run pages:build");
|
|
124
362
|
log("");
|
|
125
363
|
}
|
|
126
364
|
|
|
127
365
|
function isEffectivelyEmptyProject(dir) {
|
|
128
366
|
if (!fs.existsSync(dir)) return true;
|
|
129
|
-
const entries = fs.readdirSync(dir).filter((entry) => ![".git", ".gitkeep"].includes(entry));
|
|
130
|
-
return entries.length === 0;
|
|
131
|
-
}
|
|
132
367
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
368
|
+
const entries = fs
|
|
369
|
+
.readdirSync(dir)
|
|
370
|
+
.filter((entry) => ![".git", ".gitkeep"].includes(entry));
|
|
371
|
+
|
|
372
|
+
return entries.length === 0;
|
|
138
373
|
}
|
|
139
374
|
|
|
140
375
|
if (!fs.existsSync(templateRoot)) {
|
|
@@ -150,10 +385,14 @@ if (fs.existsSync(targetDir) && !isEffectivelyEmptyProject(targetDir) && !forceO
|
|
|
150
385
|
fail(`La carpeta destino ya contiene archivos: ${targetDir}
|
|
151
386
|
|
|
152
387
|
Para trabajar dentro de un repositorio ya creado en GitHub, usa una carpeta vacía o ejecuta con --force si deseas sobrescribir archivos existentes.
|
|
388
|
+
|
|
153
389
|
Ejemplo:
|
|
154
|
-
npm create openclass-uniminuto@latest . -- --
|
|
390
|
+
npm create openclass-uniminuto@latest . -- --force
|
|
391
|
+
|
|
392
|
+
Para aplicar la configuración IoT inicial:
|
|
393
|
+
npm create openclass-uniminuto@latest . -- --iot
|
|
155
394
|
|
|
156
|
-
Para actualizar únicamente
|
|
395
|
+
Para actualizar únicamente la infraestructura de un proyecto existente:
|
|
157
396
|
npm create openclass-uniminuto@latest . -- --update-theme`);
|
|
158
397
|
}
|
|
159
398
|
|
|
@@ -161,34 +400,57 @@ log("\n┌───────────────────────
|
|
|
161
400
|
log("│ Crear proyecto Open Class UNIMINUTO · Slidev │");
|
|
162
401
|
log("└──────────────────────────────────────────────┘\n");
|
|
163
402
|
log(`Destino: ${targetDir}`);
|
|
164
|
-
|
|
165
|
-
if (
|
|
403
|
+
|
|
404
|
+
if (isCurrentDirectoryTarget) {
|
|
405
|
+
log("Modo: aplicar plantilla en el directorio actual");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (forceOverwrite) {
|
|
409
|
+
log("Modo: --force activo; se podrán sobrescribir archivos existentes");
|
|
410
|
+
}
|
|
166
411
|
|
|
167
412
|
copyTemplate(templateRoot, targetDir);
|
|
168
413
|
|
|
169
414
|
const innerName = cleanPackageName(path.basename(targetDir));
|
|
415
|
+
|
|
170
416
|
patchJson(path.join(targetDir, "package.json"), (pkg) => {
|
|
171
417
|
pkg.name = innerName;
|
|
172
418
|
});
|
|
419
|
+
|
|
173
420
|
patchJson(path.join(targetDir, "package-lock.json"), (lock) => {
|
|
174
421
|
lock.name = innerName;
|
|
175
|
-
|
|
422
|
+
|
|
423
|
+
if (lock.packages && lock.packages[""]) {
|
|
424
|
+
lock.packages[""].name = innerName;
|
|
425
|
+
}
|
|
176
426
|
});
|
|
177
427
|
|
|
178
428
|
if (flags.has("--iot")) {
|
|
179
|
-
const sourceConfig = path.join(
|
|
429
|
+
const sourceConfig = path.join(
|
|
430
|
+
targetDir,
|
|
431
|
+
"config",
|
|
432
|
+
"openclass.config.iot-desde-openclass-iot.json",
|
|
433
|
+
);
|
|
434
|
+
|
|
180
435
|
const destConfig = path.join(targetDir, "openclass.config.json");
|
|
436
|
+
|
|
181
437
|
if (!fs.existsSync(sourceConfig)) {
|
|
182
438
|
fail("No se encontró la configuración IoT incluida en la plantilla.");
|
|
183
439
|
}
|
|
440
|
+
|
|
184
441
|
fs.copyFileSync(sourceConfig, destConfig);
|
|
185
442
|
log("✓ Configuración IoT aplicada en openclass.config.json");
|
|
186
443
|
|
|
187
|
-
const result = spawnSync(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
444
|
+
const result = spawnSync(
|
|
445
|
+
process.execPath,
|
|
446
|
+
["scripts/generar-desde-config.mjs", "--force"],
|
|
447
|
+
{
|
|
448
|
+
cwd: targetDir,
|
|
449
|
+
stdio: "inherit",
|
|
450
|
+
shell: false,
|
|
451
|
+
},
|
|
452
|
+
);
|
|
453
|
+
|
|
192
454
|
if (result.status !== 0) {
|
|
193
455
|
fail("El generador de configuración no pudo completar el proyecto IoT.");
|
|
194
456
|
}
|
|
@@ -196,27 +458,39 @@ if (flags.has("--iot")) {
|
|
|
196
458
|
|
|
197
459
|
if (flags.has("--install")) {
|
|
198
460
|
log("\nInstalando dependencias con npm install...\n");
|
|
461
|
+
|
|
199
462
|
const result = spawnSync("npm", ["install"], {
|
|
200
463
|
cwd: targetDir,
|
|
201
464
|
stdio: "inherit",
|
|
202
465
|
shell: process.platform === "win32",
|
|
203
466
|
});
|
|
467
|
+
|
|
204
468
|
if (result.status !== 0) {
|
|
205
469
|
fail("npm install terminó con error. Revisa la salida de consola.");
|
|
206
470
|
}
|
|
207
471
|
}
|
|
208
472
|
|
|
209
473
|
log("\n✅ Proyecto creado correctamente.\n");
|
|
210
|
-
log(
|
|
474
|
+
log("Siguientes pasos:");
|
|
211
475
|
log(` cd ${path.relative(process.cwd(), targetDir) || "."}`);
|
|
212
|
-
|
|
213
|
-
if (!flags.has("--
|
|
476
|
+
|
|
477
|
+
if (!flags.has("--install")) {
|
|
478
|
+
log(" npm install");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (!flags.has("--iot")) {
|
|
482
|
+
log(" npm run nuevo");
|
|
483
|
+
}
|
|
484
|
+
|
|
214
485
|
log(" npm run semana -- 1");
|
|
215
486
|
log(" npm run dev");
|
|
216
|
-
log("
|
|
217
|
-
log("
|
|
218
|
-
log(
|
|
487
|
+
log("");
|
|
488
|
+
log("Para activar una semana adicional:");
|
|
489
|
+
log(' npm run semana -- 2 --title "Título de la semana 2"');
|
|
490
|
+
log("");
|
|
491
|
+
log("Para actualizar infraestructura en un proyecto existente:");
|
|
219
492
|
log(" npm create openclass-uniminuto@latest . -- --update-theme");
|
|
220
|
-
log("\nPara revisar la publicación en GitHub Pages:");
|
|
221
|
-
log(" npm run pages:check");
|
|
222
493
|
log("");
|
|
494
|
+
log("Para revisar la publicación en GitHub Pages:");
|
|
495
|
+
log(" npm run pages:check");
|
|
496
|
+
log("");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-openclass-uniminuto",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.4",
|
|
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": {
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
- name: Install Chromium for Slidev export
|
|
43
43
|
run: npx playwright install chromium --with-deps
|
|
44
44
|
|
|
45
|
-
- name: Generate and build Open Class
|
|
45
|
+
- name: Generate, export and build Open Class
|
|
46
46
|
run: npm run pages:build
|
|
47
47
|
|
|
48
48
|
- name: Upload GitHub Pages artifact
|
|
@@ -61,4 +61,4 @@ jobs:
|
|
|
61
61
|
steps:
|
|
62
62
|
- name: Deploy to GitHub Pages
|
|
63
63
|
id: deployment
|
|
64
|
-
uses: actions/deploy-pages@v4
|
|
64
|
+
uses: actions/deploy-pages@v4
|