create-openclass-uniminuto 1.6.2 → 1.6.5
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 +309 -91
- package/package.json +1 -1
- package/template/.github/workflows/deploy.yml +2 -2
- package/template/README.md +385 -343
- 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 -64
- package/template/plantillas/launcher.md +1 -1
- package/template/plantillas/semana.md +214 -88
- package/template/scripts/decks.mjs +11 -40
- package/template/scripts/generar-desde-config.mjs +312 -48
- package/template/slides.md +1 -1
|
@@ -6,18 +6,27 @@ 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 === "./";
|
|
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
|
+
|
|
18
25
|
function envFlag(name) {
|
|
19
26
|
const value = process.env[name];
|
|
27
|
+
|
|
20
28
|
if (value === undefined) return false;
|
|
29
|
+
|
|
21
30
|
return ["1", "true", "yes", "on"].includes(String(value).toLowerCase());
|
|
22
31
|
}
|
|
23
32
|
|
|
@@ -40,31 +49,73 @@ function fail(message) {
|
|
|
40
49
|
process.exit(1);
|
|
41
50
|
}
|
|
42
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
|
+
|
|
43
59
|
function cleanPackageName(value) {
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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;
|
|
50
98
|
}
|
|
51
99
|
|
|
52
100
|
function copyTemplate(src, dest) {
|
|
53
|
-
|
|
54
|
-
if (["node_modules", "dist", ".slidev", ".git"].includes(base)) return;
|
|
101
|
+
if (shouldIgnore(src)) return;
|
|
55
102
|
|
|
56
103
|
const stat = fs.statSync(src);
|
|
104
|
+
|
|
57
105
|
if (stat.isDirectory()) {
|
|
58
106
|
fs.mkdirSync(dest, { recursive: true });
|
|
107
|
+
|
|
59
108
|
for (const child of fs.readdirSync(src)) {
|
|
60
109
|
copyTemplate(path.join(src, child), path.join(dest, child));
|
|
61
110
|
}
|
|
111
|
+
|
|
62
112
|
return;
|
|
63
113
|
}
|
|
64
114
|
|
|
65
115
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
116
|
+
|
|
66
117
|
if (fs.existsSync(dest) && !forceOverwrite) {
|
|
67
|
-
log(`↷ Conservado archivo existente: ${
|
|
118
|
+
log(`↷ Conservado archivo existente: ${relativeToTarget(dest)}`);
|
|
68
119
|
return;
|
|
69
120
|
}
|
|
70
121
|
|
|
@@ -72,33 +123,172 @@ function copyTemplate(src, dest) {
|
|
|
72
123
|
}
|
|
73
124
|
|
|
74
125
|
function copyPathAlways(src, dest) {
|
|
75
|
-
|
|
76
|
-
if (["node_modules", "dist", ".slidev", ".git"].includes(base)) return;
|
|
77
|
-
|
|
78
|
-
if (!fs.existsSync(src)) return;
|
|
126
|
+
if (!fs.existsSync(src) || shouldIgnore(src)) return;
|
|
79
127
|
|
|
80
128
|
const stat = fs.statSync(src);
|
|
129
|
+
|
|
81
130
|
if (stat.isDirectory()) {
|
|
82
131
|
fs.mkdirSync(dest, { recursive: true });
|
|
132
|
+
|
|
83
133
|
for (const child of fs.readdirSync(src)) {
|
|
84
134
|
copyPathAlways(path.join(src, child), path.join(dest, child));
|
|
85
135
|
}
|
|
136
|
+
|
|
86
137
|
return;
|
|
87
138
|
}
|
|
88
139
|
|
|
89
140
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
90
141
|
fs.copyFileSync(src, dest);
|
|
91
|
-
|
|
142
|
+
|
|
143
|
+
log(`✓ Actualizado: ${relativeToTarget(dest)}`);
|
|
92
144
|
}
|
|
93
145
|
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
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
|
+
|
|
99
166
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
100
167
|
fs.copyFileSync(src, dest);
|
|
101
|
-
|
|
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);
|
|
102
292
|
}
|
|
103
293
|
|
|
104
294
|
function updateThemeOnly() {
|
|
@@ -107,88 +297,79 @@ function updateThemeOnly() {
|
|
|
107
297
|
}
|
|
108
298
|
|
|
109
299
|
log("\n┌──────────────────────────────────────────────┐");
|
|
110
|
-
log("│ Actualizar
|
|
300
|
+
log("│ Actualizar infraestructura Open Class │");
|
|
111
301
|
log("└──────────────────────────────────────────────┘\n");
|
|
112
302
|
log(`Destino: ${targetDir}`);
|
|
113
|
-
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");
|
|
114
305
|
|
|
115
306
|
const pathsToUpdate = [
|
|
116
307
|
"README.md",
|
|
117
|
-
|
|
308
|
+
|
|
309
|
+
"theme/uniminuto/components",
|
|
118
310
|
"theme/uniminuto/layouts",
|
|
119
311
|
"theme/uniminuto/styles",
|
|
120
312
|
"theme/uniminuto/package.json",
|
|
121
313
|
"theme/uniminuto/README-AutoFit.md",
|
|
314
|
+
|
|
122
315
|
"setup",
|
|
123
316
|
"snippets",
|
|
317
|
+
|
|
124
318
|
"scripts/build-site.mjs",
|
|
125
319
|
"scripts/build-incremental.mjs",
|
|
126
320
|
"scripts/decks.mjs",
|
|
127
321
|
"scripts/dev-all.mjs",
|
|
128
322
|
"scripts/export-downloads.mjs",
|
|
129
323
|
"scripts/export-incremental.mjs",
|
|
324
|
+
"scripts/generar-desde-config.mjs",
|
|
325
|
+
"scripts/nuevo-curso.mjs",
|
|
130
326
|
"scripts/preparar-github-pages.mjs",
|
|
327
|
+
"scripts/publicar.mjs",
|
|
131
328
|
"scripts/semana.mjs",
|
|
132
|
-
"
|
|
329
|
+
"scripts/zip-template.mjs",
|
|
330
|
+
|
|
331
|
+
"plantillas",
|
|
332
|
+
|
|
333
|
+
".github/workflows/deploy.yml",
|
|
334
|
+
|
|
335
|
+
"public/fondos",
|
|
133
336
|
];
|
|
134
337
|
|
|
135
338
|
for (const relativePath of pathsToUpdate) {
|
|
136
|
-
|
|
339
|
+
copyTemplatePathAlways(relativePath);
|
|
137
340
|
}
|
|
138
341
|
|
|
139
|
-
|
|
140
|
-
ensureFileFromTemplate("public/imagenes/favicon.png", { onlyIfMissing: true });
|
|
141
|
-
ensureFileFromTemplate("public/imagenes/avion.png", { onlyIfMissing: false });
|
|
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
|
-
});
|
|
342
|
+
copyTemplatePathIfMissing("openclass.config.json");
|
|
158
343
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
174
|
-
log("\n✅ Tema actualizado sin tocar semanas, slides.md ni openclass.config.json.");
|
|
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");
|
|
350
|
+
|
|
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.");
|
|
175
358
|
log(" Recomendado ahora:");
|
|
176
|
-
log(" npm
|
|
177
|
-
log(" npm run
|
|
359
|
+
log(" npm install");
|
|
360
|
+
log(" npm run config");
|
|
361
|
+
log(" npm run pages:build");
|
|
178
362
|
log("");
|
|
179
363
|
}
|
|
180
364
|
|
|
181
365
|
function isEffectivelyEmptyProject(dir) {
|
|
182
366
|
if (!fs.existsSync(dir)) return true;
|
|
183
|
-
const entries = fs.readdirSync(dir).filter((entry) => ![".git", ".gitkeep"].includes(entry));
|
|
184
|
-
return entries.length === 0;
|
|
185
|
-
}
|
|
186
367
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
368
|
+
const entries = fs
|
|
369
|
+
.readdirSync(dir)
|
|
370
|
+
.filter((entry) => ![".git", ".gitkeep"].includes(entry));
|
|
371
|
+
|
|
372
|
+
return entries.length === 0;
|
|
192
373
|
}
|
|
193
374
|
|
|
194
375
|
if (!fs.existsSync(templateRoot)) {
|
|
@@ -204,10 +385,14 @@ if (fs.existsSync(targetDir) && !isEffectivelyEmptyProject(targetDir) && !forceO
|
|
|
204
385
|
fail(`La carpeta destino ya contiene archivos: ${targetDir}
|
|
205
386
|
|
|
206
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
|
+
|
|
207
389
|
Ejemplo:
|
|
208
|
-
npm create openclass-uniminuto@latest . -- --
|
|
390
|
+
npm create openclass-uniminuto@latest . -- --force
|
|
209
391
|
|
|
210
|
-
Para
|
|
392
|
+
Para aplicar la configuración IoT inicial:
|
|
393
|
+
npm create openclass-uniminuto@latest . -- --iot
|
|
394
|
+
|
|
395
|
+
Para actualizar únicamente la infraestructura de un proyecto existente:
|
|
211
396
|
npm create openclass-uniminuto@latest . -- --update-theme`);
|
|
212
397
|
}
|
|
213
398
|
|
|
@@ -215,34 +400,57 @@ log("\n┌───────────────────────
|
|
|
215
400
|
log("│ Crear proyecto Open Class UNIMINUTO · Slidev │");
|
|
216
401
|
log("└──────────────────────────────────────────────┘\n");
|
|
217
402
|
log(`Destino: ${targetDir}`);
|
|
218
|
-
|
|
219
|
-
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
|
+
}
|
|
220
411
|
|
|
221
412
|
copyTemplate(templateRoot, targetDir);
|
|
222
413
|
|
|
223
414
|
const innerName = cleanPackageName(path.basename(targetDir));
|
|
415
|
+
|
|
224
416
|
patchJson(path.join(targetDir, "package.json"), (pkg) => {
|
|
225
417
|
pkg.name = innerName;
|
|
226
418
|
});
|
|
419
|
+
|
|
227
420
|
patchJson(path.join(targetDir, "package-lock.json"), (lock) => {
|
|
228
421
|
lock.name = innerName;
|
|
229
|
-
|
|
422
|
+
|
|
423
|
+
if (lock.packages && lock.packages[""]) {
|
|
424
|
+
lock.packages[""].name = innerName;
|
|
425
|
+
}
|
|
230
426
|
});
|
|
231
427
|
|
|
232
428
|
if (flags.has("--iot")) {
|
|
233
|
-
const sourceConfig = path.join(
|
|
429
|
+
const sourceConfig = path.join(
|
|
430
|
+
targetDir,
|
|
431
|
+
"config",
|
|
432
|
+
"openclass.config.iot-desde-openclass-iot.json",
|
|
433
|
+
);
|
|
434
|
+
|
|
234
435
|
const destConfig = path.join(targetDir, "openclass.config.json");
|
|
436
|
+
|
|
235
437
|
if (!fs.existsSync(sourceConfig)) {
|
|
236
438
|
fail("No se encontró la configuración IoT incluida en la plantilla.");
|
|
237
439
|
}
|
|
440
|
+
|
|
238
441
|
fs.copyFileSync(sourceConfig, destConfig);
|
|
239
442
|
log("✓ Configuración IoT aplicada en openclass.config.json");
|
|
240
443
|
|
|
241
|
-
const result = spawnSync(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
+
|
|
246
454
|
if (result.status !== 0) {
|
|
247
455
|
fail("El generador de configuración no pudo completar el proyecto IoT.");
|
|
248
456
|
}
|
|
@@ -250,29 +458,39 @@ if (flags.has("--iot")) {
|
|
|
250
458
|
|
|
251
459
|
if (flags.has("--install")) {
|
|
252
460
|
log("\nInstalando dependencias con npm install...\n");
|
|
461
|
+
|
|
253
462
|
const result = spawnSync("npm", ["install"], {
|
|
254
463
|
cwd: targetDir,
|
|
255
464
|
stdio: "inherit",
|
|
256
465
|
shell: process.platform === "win32",
|
|
257
466
|
});
|
|
467
|
+
|
|
258
468
|
if (result.status !== 0) {
|
|
259
469
|
fail("npm install terminó con error. Revisa la salida de consola.");
|
|
260
470
|
}
|
|
261
471
|
}
|
|
262
472
|
|
|
263
473
|
log("\n✅ Proyecto creado correctamente.\n");
|
|
264
|
-
log(
|
|
474
|
+
log("Siguientes pasos:");
|
|
265
475
|
log(` cd ${path.relative(process.cwd(), targetDir) || "."}`);
|
|
266
|
-
|
|
267
|
-
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
|
+
|
|
268
485
|
log(" npm run semana -- 1");
|
|
269
486
|
log(" npm run dev");
|
|
270
|
-
log("
|
|
271
|
-
log("
|
|
272
|
-
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:");
|
|
273
492
|
log(" npm create openclass-uniminuto@latest . -- --update-theme");
|
|
274
|
-
log("\nPara revisar la publicación en GitHub Pages:");
|
|
275
|
-
log(" npm run pages:check");
|
|
276
493
|
log("");
|
|
277
|
-
|
|
278
|
-
|
|
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.5",
|
|
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
|