@learnpack/learnpack 5.0.275 → 5.0.277
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/README.md +409 -409
- package/lib/commands/audit.js +15 -15
- package/lib/commands/breakToken.js +19 -19
- package/lib/commands/clean.js +3 -3
- package/lib/commands/init.js +41 -41
- package/lib/commands/logout.js +3 -3
- package/lib/commands/publish.js +5 -10
- package/lib/commands/serve.js +55 -2
- package/lib/creatorDist/assets/index-BfLyIQVh.js +10343 -10224
- package/lib/managers/config/index.js +77 -77
- package/lib/utils/api.d.ts +1 -1
- package/lib/utils/api.js +12 -9
- package/lib/utils/creatorUtilities.js +14 -14
- package/lib/utils/export/epub.d.ts +2 -0
- package/lib/utils/export/epub.js +298 -0
- package/lib/utils/export/index.d.ts +3 -0
- package/lib/utils/export/index.js +7 -0
- package/lib/utils/export/scorm.d.ts +2 -0
- package/lib/utils/export/scorm.js +84 -0
- package/lib/utils/export/shared.d.ts +4 -0
- package/lib/utils/export/shared.js +61 -0
- package/lib/utils/export/types.d.ts +15 -0
- package/lib/utils/export/types.js +2 -0
- package/package.json +2 -1
- package/src/commands/audit.ts +487 -487
- package/src/commands/breakToken.ts +67 -67
- package/src/commands/clean.ts +30 -30
- package/src/commands/init.ts +650 -650
- package/src/commands/logout.ts +38 -38
- package/src/commands/publish.ts +20 -25
- package/src/commands/serve.ts +69 -4
- package/src/commands/start.ts +333 -333
- package/src/commands/translate.ts +123 -123
- package/src/creator/README.md +54 -54
- package/src/creator/eslint.config.js +7 -7
- package/src/creator/src/components/syllabus/ContentIndex.tsx +312 -312
- package/src/creator/src/i18n.ts +28 -28
- package/src/creator/src/index.css +217 -217
- package/src/creator/src/locales/en.json +126 -126
- package/src/creator/src/locales/es.json +126 -126
- package/src/creator/src/utils/configTypes.ts +122 -122
- package/src/creator/src/utils/constants.ts +13 -13
- package/src/creator/src/utils/creatorUtils.ts +46 -46
- package/src/creator/src/utils/eventBus.ts +2 -2
- package/src/creator/src/utils/lib.ts +468 -468
- package/src/creator/src/utils/socket.ts +61 -61
- package/src/creator/src/utils/store.ts +222 -222
- package/src/creator/src/vite-env.d.ts +1 -1
- package/src/creator/vite.config.ts +13 -13
- package/src/creatorDist/assets/index-BfLyIQVh.js +10343 -10224
- package/src/managers/config/defaults.ts +49 -49
- package/src/managers/config/exercise.ts +364 -364
- package/src/managers/config/index.ts +775 -775
- package/src/managers/file.ts +236 -236
- package/src/managers/server/routes.ts +554 -554
- package/src/managers/session.ts +182 -182
- package/src/managers/telemetry.ts +188 -188
- package/src/models/action.ts +13 -13
- package/src/models/config-manager.ts +28 -28
- package/src/models/config.ts +106 -106
- package/src/models/creator.ts +47 -47
- package/src/models/exercise-obj.ts +30 -30
- package/src/models/session.ts +39 -39
- package/src/models/socket.ts +61 -61
- package/src/models/status.ts +16 -16
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +400 -397
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/BaseCommand.ts +56 -56
- package/src/utils/api.ts +53 -39
- package/src/utils/audit.ts +392 -392
- package/src/utils/checkNotInstalled.ts +267 -267
- package/src/utils/configBuilder.ts +82 -82
- package/src/utils/convertCreds.js +34 -34
- package/src/utils/creatorUtilities.ts +504 -504
- package/src/utils/export/README.md +178 -0
- package/src/utils/export/epub.ts +400 -0
- package/src/utils/export/index.ts +3 -0
- package/src/utils/export/scorm.ts +121 -0
- package/src/utils/export/shared.ts +61 -0
- package/src/utils/export/types.ts +17 -0
- package/src/utils/incrementVersion.js +74 -74
- package/src/utils/misc.ts +58 -58
- package/src/utils/rigoActions.ts +500 -500
- package/src/utils/sidebarGenerator.ts +195 -195
- package/src/utils/templates/epub/epub.css +133 -0
- package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
- package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
- package/src/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -0
- package/src/utils/templates/scorm/config/api.js +175 -0
- package/src/utils/templates/scorm/config/index.html +210 -0
- package/src/utils/templates/scorm/ims_xml.xsd +1 -0
- package/src/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -0
- package/src/utils/templates/scorm/imsmanifest.xml +38 -0
- package/src/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
import * as path from "path";
|
2
|
+
import * as fs from "fs";
|
3
|
+
import * as mkdirp from "mkdirp";
|
4
|
+
|
5
|
+
// Utility function to copy directory recursively
|
6
|
+
export function copyDir(src: string, dest: string) {
|
7
|
+
if (!fs.existsSync(dest)) mkdirp.sync(dest);
|
8
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
9
|
+
const srcPath = path.join(src, entry.name);
|
10
|
+
const destPath = path.join(dest, entry.name);
|
11
|
+
if (entry.isDirectory()) {
|
12
|
+
copyDir(srcPath, destPath);
|
13
|
+
} else {
|
14
|
+
fs.copyFileSync(srcPath, destPath);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
// Download all files from a GCS Bucket prefix to a local folder
|
20
|
+
export async function downloadS3Folder(
|
21
|
+
bucket: any,
|
22
|
+
prefix: string,
|
23
|
+
localPath: string
|
24
|
+
) {
|
25
|
+
const [files] = await bucket.getFiles({ prefix });
|
26
|
+
for (const file of files) {
|
27
|
+
const relPath = file.name.replace(prefix, "");
|
28
|
+
if (!relPath) continue;
|
29
|
+
const outPath = path.join(localPath, relPath);
|
30
|
+
mkdirp.sync(path.dirname(outPath));
|
31
|
+
// esling-disable-next-line
|
32
|
+
const [buf] = await file.download();
|
33
|
+
fs.writeFileSync(outPath, buf);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
// Generate file list for manifest, given a folder
|
38
|
+
export function getFilesList(folder: string, base: string) {
|
39
|
+
let list: string[] = [];
|
40
|
+
const files = fs.readdirSync(folder, { withFileTypes: true });
|
41
|
+
for (const file of files) {
|
42
|
+
const filePath = path.join(folder, file.name);
|
43
|
+
if (file.isDirectory()) {
|
44
|
+
// esling-disable-next-line
|
45
|
+
list = list.concat(getFilesList(filePath, path.join(base, file.name)));
|
46
|
+
} else {
|
47
|
+
list.push(
|
48
|
+
`<file href="${path.join(base, file.name).replace(/\\/g, "/")}" />`
|
49
|
+
);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
return list;
|
53
|
+
}
|
54
|
+
|
55
|
+
// Read course metadata from learn.json
|
56
|
+
export async function getCourseMetadata(bucket: any, courseSlug: string) {
|
57
|
+
const [learnBuf] = await bucket
|
58
|
+
.file(`courses/${courseSlug}/learn.json`)
|
59
|
+
.download();
|
60
|
+
return JSON.parse(learnBuf.toString());
|
61
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
export type ExportFormat = "scorm" | "epub";
|
2
|
+
|
3
|
+
export interface ExportOptions {
|
4
|
+
courseSlug: string;
|
5
|
+
format: ExportFormat;
|
6
|
+
bucket: any; // Google Cloud Storage Bucket
|
7
|
+
outDir: string;
|
8
|
+
language?: string; // Optional language parameter for EPUB export
|
9
|
+
}
|
10
|
+
|
11
|
+
export interface CourseMetadata {
|
12
|
+
title: string;
|
13
|
+
description?: string;
|
14
|
+
language?: string;
|
15
|
+
technologies?: string[];
|
16
|
+
difficulty?: string;
|
17
|
+
}
|
@@ -1,74 +1,74 @@
|
|
1
|
-
const fs = require("fs")
|
2
|
-
const path = require("path")
|
3
|
-
const readline = require("readline")
|
4
|
-
|
5
|
-
// Get command-line arguments
|
6
|
-
const args = process.argv.slice(2)
|
7
|
-
const partIndex = args.findIndex(arg => arg === "-p" || arg === "--part")
|
8
|
-
const part =
|
9
|
-
partIndex !== -1 && args[partIndex + 1] ?
|
10
|
-
args[partIndex + 1].toLowerCase() :
|
11
|
-
null
|
12
|
-
|
13
|
-
const packagePath = path.resolve(process.cwd(), "package.json")
|
14
|
-
|
15
|
-
try {
|
16
|
-
// Read package.json file
|
17
|
-
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"))
|
18
|
-
|
19
|
-
// Check if "version" field exists
|
20
|
-
if (!packageJson.version) {
|
21
|
-
throw new Error(
|
22
|
-
'El archivo package.json no contiene una propiedad "version".'
|
23
|
-
)
|
24
|
-
}
|
25
|
-
|
26
|
-
const [major, minor, patch] = packageJson.version.split(".").map(Number)
|
27
|
-
|
28
|
-
// Function to update version
|
29
|
-
const updateVersion = part => {
|
30
|
-
let newVersion
|
31
|
-
switch (part) {
|
32
|
-
case "major":
|
33
|
-
newVersion = `${major + 1}.0.0`
|
34
|
-
break
|
35
|
-
case "minor":
|
36
|
-
newVersion = `${major}.${minor + 1}.0`
|
37
|
-
break
|
38
|
-
case "patch":
|
39
|
-
newVersion = `${major}.${minor}.${patch + 1}`
|
40
|
-
break
|
41
|
-
default:
|
42
|
-
console.error("Opción no válida. Usa: major, minor o patch.")
|
43
|
-
process.exit(1)
|
44
|
-
}
|
45
|
-
|
46
|
-
// Update package.json
|
47
|
-
packageJson.version = newVersion
|
48
|
-
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2), "utf8")
|
49
|
-
|
50
|
-
console.log(`Versión actualizada: ${packageJson.version} -> ${newVersion}`)
|
51
|
-
}
|
52
|
-
|
53
|
-
if (part) {
|
54
|
-
// If flag is provided, update immediately
|
55
|
-
updateVersion(part)
|
56
|
-
} else {
|
57
|
-
// Otherwise, ask the user interactively
|
58
|
-
const rl = readline.createInterface({
|
59
|
-
input: process.stdin,
|
60
|
-
output: process.stdout,
|
61
|
-
})
|
62
|
-
|
63
|
-
rl.question(
|
64
|
-
"¿Qué parte de la versión deseas incrementar? (major, minor, patch): ",
|
65
|
-
answer => {
|
66
|
-
updateVersion(answer.toLowerCase())
|
67
|
-
rl.close()
|
68
|
-
}
|
69
|
-
)
|
70
|
-
}
|
71
|
-
} catch (error) {
|
72
|
-
console.error(`Error: ${error.message}`)
|
73
|
-
process.exit(1)
|
74
|
-
}
|
1
|
+
const fs = require("fs")
|
2
|
+
const path = require("path")
|
3
|
+
const readline = require("readline")
|
4
|
+
|
5
|
+
// Get command-line arguments
|
6
|
+
const args = process.argv.slice(2)
|
7
|
+
const partIndex = args.findIndex(arg => arg === "-p" || arg === "--part")
|
8
|
+
const part =
|
9
|
+
partIndex !== -1 && args[partIndex + 1] ?
|
10
|
+
args[partIndex + 1].toLowerCase() :
|
11
|
+
null
|
12
|
+
|
13
|
+
const packagePath = path.resolve(process.cwd(), "package.json")
|
14
|
+
|
15
|
+
try {
|
16
|
+
// Read package.json file
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"))
|
18
|
+
|
19
|
+
// Check if "version" field exists
|
20
|
+
if (!packageJson.version) {
|
21
|
+
throw new Error(
|
22
|
+
'El archivo package.json no contiene una propiedad "version".'
|
23
|
+
)
|
24
|
+
}
|
25
|
+
|
26
|
+
const [major, minor, patch] = packageJson.version.split(".").map(Number)
|
27
|
+
|
28
|
+
// Function to update version
|
29
|
+
const updateVersion = part => {
|
30
|
+
let newVersion
|
31
|
+
switch (part) {
|
32
|
+
case "major":
|
33
|
+
newVersion = `${major + 1}.0.0`
|
34
|
+
break
|
35
|
+
case "minor":
|
36
|
+
newVersion = `${major}.${minor + 1}.0`
|
37
|
+
break
|
38
|
+
case "patch":
|
39
|
+
newVersion = `${major}.${minor}.${patch + 1}`
|
40
|
+
break
|
41
|
+
default:
|
42
|
+
console.error("Opción no válida. Usa: major, minor o patch.")
|
43
|
+
process.exit(1)
|
44
|
+
}
|
45
|
+
|
46
|
+
// Update package.json
|
47
|
+
packageJson.version = newVersion
|
48
|
+
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2), "utf8")
|
49
|
+
|
50
|
+
console.log(`Versión actualizada: ${packageJson.version} -> ${newVersion}`)
|
51
|
+
}
|
52
|
+
|
53
|
+
if (part) {
|
54
|
+
// If flag is provided, update immediately
|
55
|
+
updateVersion(part)
|
56
|
+
} else {
|
57
|
+
// Otherwise, ask the user interactively
|
58
|
+
const rl = readline.createInterface({
|
59
|
+
input: process.stdin,
|
60
|
+
output: process.stdout,
|
61
|
+
})
|
62
|
+
|
63
|
+
rl.question(
|
64
|
+
"¿Qué parte de la versión deseas incrementar? (major, minor, patch): ",
|
65
|
+
answer => {
|
66
|
+
updateVersion(answer.toLowerCase())
|
67
|
+
rl.close()
|
68
|
+
}
|
69
|
+
)
|
70
|
+
}
|
71
|
+
} catch (error) {
|
72
|
+
console.error(`Error: ${error.message}`)
|
73
|
+
process.exit(1)
|
74
|
+
}
|
package/src/utils/misc.ts
CHANGED
@@ -1,58 +1,58 @@
|
|
1
|
-
export const prioritizeHTMLFile = (entryFiles: string[]) => {
|
2
|
-
let files = []
|
3
|
-
|
4
|
-
// Find the html file and put it as latest in the files array
|
5
|
-
// in order to keep the html file opened in vscode plugin
|
6
|
-
const index = entryFiles.findIndex(file => {
|
7
|
-
return /.*\.html$/.test(file)
|
8
|
-
})
|
9
|
-
|
10
|
-
if (index !== -1) {
|
11
|
-
for (const [i, entryFile] of entryFiles.entries()) {
|
12
|
-
if (i !== index) {
|
13
|
-
files.push(entryFile)
|
14
|
-
}
|
15
|
-
}
|
16
|
-
|
17
|
-
files.push(entryFiles[index])
|
18
|
-
} else {
|
19
|
-
files = entryFiles
|
20
|
-
}
|
21
|
-
|
22
|
-
return files
|
23
|
-
}
|
24
|
-
|
25
|
-
export function minutesToISO8601Duration(minutes: number): string {
|
26
|
-
if (minutes <= 0)
|
27
|
-
return "PT0M"
|
28
|
-
|
29
|
-
const weeks = Math.floor(minutes / (60 * 24 * 7))
|
30
|
-
minutes %= 60 * 24 * 7
|
31
|
-
|
32
|
-
const days = Math.floor(minutes / (60 * 24))
|
33
|
-
minutes %= 60 * 24
|
34
|
-
|
35
|
-
const hours = Math.floor(minutes / 60)
|
36
|
-
const mins = minutes % 60
|
37
|
-
|
38
|
-
let duration = "P"
|
39
|
-
if (weeks)
|
40
|
-
duration += `${weeks}W`
|
41
|
-
if (days)
|
42
|
-
duration += `${days}D`
|
43
|
-
|
44
|
-
if (hours || mins)
|
45
|
-
duration += "T"
|
46
|
-
if (hours)
|
47
|
-
duration += `${hours}H`
|
48
|
-
if (mins)
|
49
|
-
duration += `${mins}M`
|
50
|
-
|
51
|
-
return duration
|
52
|
-
}
|
53
|
-
|
54
|
-
export const createUploadMiddleware = () => {
|
55
|
-
// eslint-disable-next-line
|
56
|
-
const multer = require("multer")
|
57
|
-
return multer({ limits: { fileSize: 25 * 1024 * 1024 } })
|
58
|
-
}
|
1
|
+
export const prioritizeHTMLFile = (entryFiles: string[]) => {
|
2
|
+
let files = []
|
3
|
+
|
4
|
+
// Find the html file and put it as latest in the files array
|
5
|
+
// in order to keep the html file opened in vscode plugin
|
6
|
+
const index = entryFiles.findIndex(file => {
|
7
|
+
return /.*\.html$/.test(file)
|
8
|
+
})
|
9
|
+
|
10
|
+
if (index !== -1) {
|
11
|
+
for (const [i, entryFile] of entryFiles.entries()) {
|
12
|
+
if (i !== index) {
|
13
|
+
files.push(entryFile)
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
files.push(entryFiles[index])
|
18
|
+
} else {
|
19
|
+
files = entryFiles
|
20
|
+
}
|
21
|
+
|
22
|
+
return files
|
23
|
+
}
|
24
|
+
|
25
|
+
export function minutesToISO8601Duration(minutes: number): string {
|
26
|
+
if (minutes <= 0)
|
27
|
+
return "PT0M"
|
28
|
+
|
29
|
+
const weeks = Math.floor(minutes / (60 * 24 * 7))
|
30
|
+
minutes %= 60 * 24 * 7
|
31
|
+
|
32
|
+
const days = Math.floor(minutes / (60 * 24))
|
33
|
+
minutes %= 60 * 24
|
34
|
+
|
35
|
+
const hours = Math.floor(minutes / 60)
|
36
|
+
const mins = minutes % 60
|
37
|
+
|
38
|
+
let duration = "P"
|
39
|
+
if (weeks)
|
40
|
+
duration += `${weeks}W`
|
41
|
+
if (days)
|
42
|
+
duration += `${days}D`
|
43
|
+
|
44
|
+
if (hours || mins)
|
45
|
+
duration += "T"
|
46
|
+
if (hours)
|
47
|
+
duration += `${hours}H`
|
48
|
+
if (mins)
|
49
|
+
duration += `${mins}M`
|
50
|
+
|
51
|
+
return duration
|
52
|
+
}
|
53
|
+
|
54
|
+
export const createUploadMiddleware = () => {
|
55
|
+
// eslint-disable-next-line
|
56
|
+
const multer = require("multer")
|
57
|
+
return multer({ limits: { fileSize: 25 * 1024 * 1024 } })
|
58
|
+
}
|