@learnpack/learnpack 5.0.298 → 5.0.300
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/logout.js +3 -3
- package/lib/commands/serve.js +31 -11
- package/lib/creatorDist/assets/{index-D25zkBaN.js → index-DoYRptnk.js} +11875 -11992
- package/lib/creatorDist/index.html +1 -1
- package/lib/managers/config/index.js +77 -77
- package/lib/utils/creatorUtilities.js +14 -14
- package/lib/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
- package/lib/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
- package/lib/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
- package/lib/utils/templates/scorm/config/index.html +209 -209
- package/lib/utils/templates/scorm/ims_xml.xsd +1 -1
- package/lib/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
- package/lib/utils/templates/scorm/imsmanifest.xml +38 -38
- package/lib/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
- package/package.json +1 -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/logout.ts +38 -38
- package/src/commands/serve.ts +47 -25
- package/src/commands/start.ts +333 -333
- package/src/commands/translate.ts +123 -123
- package/src/creator/README.md +54 -54
- package/src/creator/package-lock.json +6621 -6621
- package/src/creator/package.json +55 -55
- package/src/creator/src/App.tsx +569 -569
- package/src/creator/src/components/FileUploader.tsx +302 -302
- package/src/creator/src/components/Icon.tsx +18 -18
- package/src/creator/src/components/LessonItem.tsx +152 -152
- package/src/creator/src/components/Login.tsx +259 -259
- package/src/creator/src/components/syllabus/ContentIndex.tsx +323 -323
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +337 -337
- package/src/creator/src/i18n.ts +28 -28
- package/src/creator/src/locales/en.json +127 -127
- package/src/creator/src/locales/es.json +127 -127
- 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/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-D25zkBaN.js → index-DoYRptnk.js} +11875 -11992
- package/src/creatorDist/index.html +1 -1
- 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/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/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/utils/BaseCommand.ts +56 -56
- package/src/utils/audit.ts +392 -392
- package/src/utils/checkNotInstalled.ts +267 -267
- package/src/utils/convertCreds.js +34 -34
- package/src/utils/creatorUtilities.ts +504 -504
- package/src/utils/export/README.md +178 -178
- package/src/utils/incrementVersion.js +74 -74
- package/src/utils/misc.ts +58 -58
- package/src/utils/sidebarGenerator.ts +195 -195
- 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 -110
- package/src/utils/templates/scorm/config/index.html +209 -209
- package/src/utils/templates/scorm/ims_xml.xsd +1 -1
- package/src/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
- package/src/utils/templates/scorm/imsmanifest.xml +38 -38
- package/src/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
@@ -1,67 +1,67 @@
|
|
1
|
-
import { flags } from "@oclif/command"
|
2
|
-
import BaseCommand from "../utils/BaseCommand"
|
3
|
-
|
4
|
-
import Console from "../utils/console"
|
5
|
-
|
6
|
-
import {
|
7
|
-
extractParagraphs,
|
8
|
-
splitIntoSyllables,
|
9
|
-
extractWords,
|
10
|
-
countSentences,
|
11
|
-
fleschKincaidGrade,
|
12
|
-
} from "../utils/creatorUtilities"
|
13
|
-
|
14
|
-
const exampleMd = `# How to Install Node.js
|
15
|
-
|
16
|
-
Node.js lets you run JavaScript outside a web browser.
|
17
|
-
|
18
|
-
## Step 1: Download Node.js
|
19
|
-
|
20
|
-
Get the Node.js installer from the [official site](https://nodejs.org/en/download/).
|
21
|
-
|
22
|
-
## Step 2: Install Node.js
|
23
|
-
|
24
|
-
Open the installer and follow the steps to finish.
|
25
|
-
|
26
|
-
## Step 3: Verify the Installation
|
27
|
-
|
28
|
-
Open a terminal and type:
|
29
|
-
|
30
|
-
\`\`\`bash
|
31
|
-
node -v
|
32
|
-
\`\`\`
|
33
|
-
`
|
34
|
-
|
35
|
-
class BreakTokenCommand extends BaseCommand {
|
36
|
-
static description = "Break the token"
|
37
|
-
|
38
|
-
static flags = {
|
39
|
-
...BaseCommand.flags,
|
40
|
-
grading: flags.help({ char: "h" }),
|
41
|
-
}
|
42
|
-
|
43
|
-
async run() {
|
44
|
-
const { flags } = this.parse(BreakTokenCommand)
|
45
|
-
|
46
|
-
// await SessionManager.breakToken()
|
47
|
-
const paragraphs = extractParagraphs(exampleMd)
|
48
|
-
for (const paragraph of paragraphs) {
|
49
|
-
const syllables = splitIntoSyllables(paragraph)
|
50
|
-
const words = extractWords(paragraph)
|
51
|
-
const sentences = countSentences(paragraph)
|
52
|
-
const fkgl = fleschKincaidGrade(paragraph)
|
53
|
-
Console.info(paragraph)
|
54
|
-
Console.info(`Number of syllables: ${syllables.length}`)
|
55
|
-
Console.info(syllables)
|
56
|
-
Console.info(`Number of words: ${words.length}`)
|
57
|
-
Console.info(words)
|
58
|
-
Console.info(`Number of sentences: ${sentences}`)
|
59
|
-
Console.info(`FKGL: ${fkgl}`)
|
60
|
-
Console.info("---")
|
61
|
-
}
|
62
|
-
|
63
|
-
process.exit(0)
|
64
|
-
}
|
65
|
-
}
|
66
|
-
|
67
|
-
export default BreakTokenCommand
|
1
|
+
import { flags } from "@oclif/command"
|
2
|
+
import BaseCommand from "../utils/BaseCommand"
|
3
|
+
|
4
|
+
import Console from "../utils/console"
|
5
|
+
|
6
|
+
import {
|
7
|
+
extractParagraphs,
|
8
|
+
splitIntoSyllables,
|
9
|
+
extractWords,
|
10
|
+
countSentences,
|
11
|
+
fleschKincaidGrade,
|
12
|
+
} from "../utils/creatorUtilities"
|
13
|
+
|
14
|
+
const exampleMd = `# How to Install Node.js
|
15
|
+
|
16
|
+
Node.js lets you run JavaScript outside a web browser.
|
17
|
+
|
18
|
+
## Step 1: Download Node.js
|
19
|
+
|
20
|
+
Get the Node.js installer from the [official site](https://nodejs.org/en/download/).
|
21
|
+
|
22
|
+
## Step 2: Install Node.js
|
23
|
+
|
24
|
+
Open the installer and follow the steps to finish.
|
25
|
+
|
26
|
+
## Step 3: Verify the Installation
|
27
|
+
|
28
|
+
Open a terminal and type:
|
29
|
+
|
30
|
+
\`\`\`bash
|
31
|
+
node -v
|
32
|
+
\`\`\`
|
33
|
+
`
|
34
|
+
|
35
|
+
class BreakTokenCommand extends BaseCommand {
|
36
|
+
static description = "Break the token"
|
37
|
+
|
38
|
+
static flags = {
|
39
|
+
...BaseCommand.flags,
|
40
|
+
grading: flags.help({ char: "h" }),
|
41
|
+
}
|
42
|
+
|
43
|
+
async run() {
|
44
|
+
const { flags } = this.parse(BreakTokenCommand)
|
45
|
+
|
46
|
+
// await SessionManager.breakToken()
|
47
|
+
const paragraphs = extractParagraphs(exampleMd)
|
48
|
+
for (const paragraph of paragraphs) {
|
49
|
+
const syllables = splitIntoSyllables(paragraph)
|
50
|
+
const words = extractWords(paragraph)
|
51
|
+
const sentences = countSentences(paragraph)
|
52
|
+
const fkgl = fleschKincaidGrade(paragraph)
|
53
|
+
Console.info(paragraph)
|
54
|
+
Console.info(`Number of syllables: ${syllables.length}`)
|
55
|
+
Console.info(syllables)
|
56
|
+
Console.info(`Number of words: ${words.length}`)
|
57
|
+
Console.info(words)
|
58
|
+
Console.info(`Number of sentences: ${sentences}`)
|
59
|
+
Console.info(`FKGL: ${fkgl}`)
|
60
|
+
Console.info("---")
|
61
|
+
}
|
62
|
+
|
63
|
+
process.exit(0)
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
export default BreakTokenCommand
|
package/src/commands/clean.ts
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
// import {flags} from '@oclif/command'
|
2
|
-
import Console from "../utils/console"
|
3
|
-
import SessionCommand from "../utils/SessionCommand"
|
4
|
-
|
5
|
-
class CleanCommand extends SessionCommand {
|
6
|
-
static description = `Clean the configuration object
|
7
|
-
...
|
8
|
-
Extra documentation goes here
|
9
|
-
`
|
10
|
-
|
11
|
-
static flags: any = {
|
12
|
-
// name: flags.string({char: 'n', description: 'name to print'}),
|
13
|
-
}
|
14
|
-
|
15
|
-
async init() {
|
16
|
-
const { flags } = this.parse(CleanCommand)
|
17
|
-
await this.initSession(flags)
|
18
|
-
}
|
19
|
-
|
20
|
-
async run() {
|
21
|
-
const { flags } = this.parse(CleanCommand)
|
22
|
-
|
23
|
-
this.configManager?.buildIndex()
|
24
|
-
await this.configManager?.clean()
|
25
|
-
|
26
|
-
Console.success("Package cleaned successfully, ready to publish")
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
export default CleanCommand
|
1
|
+
// import {flags} from '@oclif/command'
|
2
|
+
import Console from "../utils/console"
|
3
|
+
import SessionCommand from "../utils/SessionCommand"
|
4
|
+
|
5
|
+
class CleanCommand extends SessionCommand {
|
6
|
+
static description = `Clean the configuration object
|
7
|
+
...
|
8
|
+
Extra documentation goes here
|
9
|
+
`
|
10
|
+
|
11
|
+
static flags: any = {
|
12
|
+
// name: flags.string({char: 'n', description: 'name to print'}),
|
13
|
+
}
|
14
|
+
|
15
|
+
async init() {
|
16
|
+
const { flags } = this.parse(CleanCommand)
|
17
|
+
await this.initSession(flags)
|
18
|
+
}
|
19
|
+
|
20
|
+
async run() {
|
21
|
+
const { flags } = this.parse(CleanCommand)
|
22
|
+
|
23
|
+
this.configManager?.buildIndex()
|
24
|
+
await this.configManager?.clean()
|
25
|
+
|
26
|
+
Console.success("Package cleaned successfully, ready to publish")
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
export default CleanCommand
|
package/src/commands/logout.ts
CHANGED
@@ -1,38 +1,38 @@
|
|
1
|
-
import SessionCommand from "../utils/SessionCommand"
|
2
|
-
import SessionManager from "../managers/session"
|
3
|
-
import Console from "../utils/console"
|
4
|
-
|
5
|
-
class LogoutCommand extends SessionCommand {
|
6
|
-
static description = `Describe the command here
|
7
|
-
...
|
8
|
-
Extra documentation goes here
|
9
|
-
`
|
10
|
-
|
11
|
-
static flags: any = {
|
12
|
-
// name: flags.string({char: 'n', description: 'name to print'}),
|
13
|
-
}
|
14
|
-
|
15
|
-
static args = [
|
16
|
-
{
|
17
|
-
name: "package", // name of arg to show in help and reference with args[name]
|
18
|
-
required: false, // make the arg required with `required: true`
|
19
|
-
description:
|
20
|
-
"The unique string that identifies this package on learnpack", // help description
|
21
|
-
hidden: false, // hide this arg from help
|
22
|
-
},
|
23
|
-
]
|
24
|
-
|
25
|
-
async init() {
|
26
|
-
const { flags } = this.parse(LogoutCommand)
|
27
|
-
// await this.initSession(flags)
|
28
|
-
Console.debug("Logout command")
|
29
|
-
}
|
30
|
-
|
31
|
-
async run() {
|
32
|
-
// const {flags, args} = this.parse(LogoutCommand)
|
33
|
-
|
34
|
-
SessionManager.destroy()
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
export default LogoutCommand
|
1
|
+
import SessionCommand from "../utils/SessionCommand"
|
2
|
+
import SessionManager from "../managers/session"
|
3
|
+
import Console from "../utils/console"
|
4
|
+
|
5
|
+
class LogoutCommand extends SessionCommand {
|
6
|
+
static description = `Describe the command here
|
7
|
+
...
|
8
|
+
Extra documentation goes here
|
9
|
+
`
|
10
|
+
|
11
|
+
static flags: any = {
|
12
|
+
// name: flags.string({char: 'n', description: 'name to print'}),
|
13
|
+
}
|
14
|
+
|
15
|
+
static args = [
|
16
|
+
{
|
17
|
+
name: "package", // name of arg to show in help and reference with args[name]
|
18
|
+
required: false, // make the arg required with `required: true`
|
19
|
+
description:
|
20
|
+
"The unique string that identifies this package on learnpack", // help description
|
21
|
+
hidden: false, // hide this arg from help
|
22
|
+
},
|
23
|
+
]
|
24
|
+
|
25
|
+
async init() {
|
26
|
+
const { flags } = this.parse(LogoutCommand)
|
27
|
+
// await this.initSession(flags)
|
28
|
+
Console.debug("Logout command")
|
29
|
+
}
|
30
|
+
|
31
|
+
async run() {
|
32
|
+
// const {flags, args} = this.parse(LogoutCommand)
|
33
|
+
|
34
|
+
SessionManager.destroy()
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
export default LogoutCommand
|
package/src/commands/serve.ts
CHANGED
@@ -52,10 +52,7 @@ import {
|
|
52
52
|
import axios from "axios"
|
53
53
|
import * as FormData from "form-data"
|
54
54
|
import api, { RIGOBOT_HOST, RIGOBOT_REALTIME_HOST } from "../utils/api"
|
55
|
-
import {
|
56
|
-
createUploadMiddleware,
|
57
|
-
minutesToISO8601Duration,
|
58
|
-
} from "../utils/misc"
|
55
|
+
import { createUploadMiddleware, minutesToISO8601Duration } from "../utils/misc"
|
59
56
|
import { buildConfig, ConfigResponse } from "../utils/configBuilder"
|
60
57
|
import { checkReadability, slugify } from "../utils/creatorUtilities"
|
61
58
|
import { checkAndFixSidebarPure } from "../utils/sidebarGenerator"
|
@@ -1030,9 +1027,13 @@ export default class ServeCommand extends SessionCommand {
|
|
1030
1027
|
if (files && Array.isArray(files)) {
|
1031
1028
|
console.log("✅ Processing files for coding challenge...")
|
1032
1029
|
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1030
|
+
const configFile = await bucket.file(
|
1031
|
+
`courses/${courseSlug}/.learn/config.json`
|
1032
|
+
)
|
1033
|
+
const [configContent] = await configFile.download()
|
1034
|
+
const { exercises } = JSON.parse(configContent.toString())
|
1035
|
+
|
1036
|
+
const exercise = exercises[parseInt(exercisePosition)]
|
1036
1037
|
|
1037
1038
|
if (!exercise) {
|
1038
1039
|
console.error(
|
@@ -1041,8 +1042,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1041
1042
|
return res.status(404).json({ error: "Exercise not found" })
|
1042
1043
|
}
|
1043
1044
|
|
1044
|
-
const
|
1045
|
-
const exerciseDir = `courses/${courseSlug}/exercises/${exSlug}`
|
1045
|
+
const exerciseDir = `courses/${courseSlug}/exercises/${exercise.slug}`
|
1046
1046
|
|
1047
1047
|
for (const fileStr of files) {
|
1048
1048
|
try {
|
@@ -1071,9 +1071,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1071
1071
|
fileObj.solution,
|
1072
1072
|
solutionFilePath
|
1073
1073
|
)
|
1074
|
-
console.log(
|
1075
|
-
`✅ Saved solution file: ${solutionFilePath}`
|
1076
|
-
)
|
1074
|
+
console.log(`✅ Saved solution file: ${solutionFilePath}`)
|
1077
1075
|
} else {
|
1078
1076
|
// If no extension, just add .solution.hide
|
1079
1077
|
const solutionFileName = `${fileObj.name}.solution.hide`
|
@@ -1084,9 +1082,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1084
1082
|
fileObj.solution,
|
1085
1083
|
solutionFilePath
|
1086
1084
|
)
|
1087
|
-
console.log(
|
1088
|
-
`✅ Saved solution file: ${solutionFilePath}`
|
1089
|
-
)
|
1085
|
+
console.log(`✅ Saved solution file: ${solutionFilePath}`)
|
1090
1086
|
}
|
1091
1087
|
}
|
1092
1088
|
} catch (parseError) {
|
@@ -2754,6 +2750,39 @@ export default class ServeCommand extends SessionCommand {
|
|
2754
2750
|
}
|
2755
2751
|
)
|
2756
2752
|
|
2753
|
+
app.delete(
|
2754
|
+
"/courses/:courseSlug/exercises/:exerciseSlug/file/:filename",
|
2755
|
+
async (req, res) => {
|
2756
|
+
console.log(
|
2757
|
+
"DELETE /courses/:courseSlug/exercises/:exerciseSlug/file/:filename",
|
2758
|
+
req.params
|
2759
|
+
)
|
2760
|
+
const { courseSlug, exerciseSlug, filename } = req.params
|
2761
|
+
|
2762
|
+
try {
|
2763
|
+
const filePath = `courses/${courseSlug}/exercises/${exerciseSlug}/${filename}`
|
2764
|
+
const file = bucket.file(filePath)
|
2765
|
+
const [exists] = await file.exists()
|
2766
|
+
|
2767
|
+
if (!exists) {
|
2768
|
+
return res.status(404).json({ error: "File not found" })
|
2769
|
+
}
|
2770
|
+
|
2771
|
+
await file.delete()
|
2772
|
+
console.log(`✅ Deleted file: ${filePath}`)
|
2773
|
+
return res.json({
|
2774
|
+
success: true,
|
2775
|
+
message: "File deleted successfully",
|
2776
|
+
})
|
2777
|
+
} catch (error) {
|
2778
|
+
console.error("❌ Error deleting file:", error)
|
2779
|
+
return res.status(500).json({
|
2780
|
+
error: (error as Error).message || "Unable to delete file",
|
2781
|
+
})
|
2782
|
+
}
|
2783
|
+
}
|
2784
|
+
)
|
2785
|
+
|
2757
2786
|
const YT_REGEX = /(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]{11})/
|
2758
2787
|
|
2759
2788
|
app.get("/actions/fetch/:link", async (req, res) => {
|
@@ -2796,9 +2825,7 @@ export default class ServeCommand extends SessionCommand {
|
|
2796
2825
|
})
|
2797
2826
|
} catch (error: any) {
|
2798
2827
|
console.error("❌ /actions/fetch error:", error.message || error)
|
2799
|
-
res
|
2800
|
-
.status(500)
|
2801
|
-
.json({ error: error.message || "Failed to fetch link" })
|
2828
|
+
res.status(500).json({ error: error.message || "Failed to fetch link" })
|
2802
2829
|
}
|
2803
2830
|
})
|
2804
2831
|
app.delete("/packages/:slug", async (req, res) => {
|
@@ -2978,10 +3005,7 @@ export default class ServeCommand extends SessionCommand {
|
|
2978
3005
|
!metadata.rights ||
|
2979
3006
|
!metadata.lang
|
2980
3007
|
) {
|
2981
|
-
console.log(
|
2982
|
-
"Missing required metadata for EPUB export",
|
2983
|
-
metadata
|
2984
|
-
)
|
3008
|
+
console.log("Missing required metadata for EPUB export", metadata)
|
2985
3009
|
return res.status(400).json({
|
2986
3010
|
error: "Missing required metadata for EPUB export",
|
2987
3011
|
required: ["creator", "publisher", "title", "rights", "lang"],
|
@@ -3026,9 +3050,7 @@ export default class ServeCommand extends SessionCommand {
|
|
3026
3050
|
})
|
3027
3051
|
} catch (error: any) {
|
3028
3052
|
console.error("Export error:", error)
|
3029
|
-
res
|
3030
|
-
.status(500)
|
3031
|
-
.json({ error: "Export failed", details: error.message })
|
3053
|
+
res.status(500).json({ error: "Export failed", details: error.message })
|
3032
3054
|
}
|
3033
3055
|
})
|
3034
3056
|
|