@learnpack/learnpack 5.0.334 → 5.0.339
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/run +17 -17
- package/lib/commands/init.js +41 -41
- package/lib/commands/serve.js +645 -129
- package/lib/creatorDist/assets/index-BhqDgBS9.js +8448 -78631
- package/lib/creatorDist/assets/index-CjddKHB_.css +1 -1688
- package/lib/managers/config/exercise.js +2 -14
- package/lib/managers/readmeHistoryService.js +3 -1
- package/lib/managers/server/routes.js +2 -1
- package/lib/utils/configBuilder.js +2 -1
- package/lib/utils/creatorUtilities.js +14 -14
- package/lib/utils/exerciseFileOrder.d.ts +20 -0
- package/lib/utils/exerciseFileOrder.js +49 -0
- package/lib/utils/export/epub.js +26 -26
- package/lib/utils/readmeSanitizer.d.ts +8 -0
- package/lib/utils/readmeSanitizer.js +13 -0
- package/lib/utils/templates/epub/epub.css +146 -146
- package/lib/utils/templates/scorm/config/api.js +175 -175
- package/package.json +1 -1
- package/src/commands/init.ts +655 -655
- package/src/commands/publish.ts +670 -670
- package/src/commands/serve.ts +5853 -5148
- package/src/creator/eslint.config.js +28 -28
- package/src/creator/src/index.css +227 -227
- package/src/creator/src/utils/lib.ts +471 -471
- package/src/creatorDist/assets/index-BhqDgBS9.js +8448 -78631
- package/src/creatorDist/assets/index-CjddKHB_.css +1 -1688
- package/src/managers/config/exercise.ts +3 -15
- package/src/managers/readmeHistoryService.ts +3 -1
- package/src/managers/server/routes.ts +15 -6
- package/src/managers/session.ts +184 -184
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +1950 -1878
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/api.ts +675 -675
- package/src/utils/configBuilder.ts +102 -100
- package/src/utils/creatorUtilities.ts +536 -536
- package/src/utils/errors.ts +108 -108
- package/src/utils/exerciseFileOrder.ts +50 -0
- package/src/utils/export/epub.ts +553 -553
- package/src/utils/export/index.ts +4 -4
- package/src/utils/export/scorm.ts +121 -121
- package/src/utils/export/shared.ts +61 -61
- package/src/utils/export/types.ts +25 -25
- package/src/utils/export/zip.ts +55 -55
- package/src/utils/readmeSanitizer.ts +10 -0
- package/src/utils/rigoActions.ts +642 -642
- package/src/utils/templates/epub/epub.css +146 -146
- package/src/utils/templates/scorm/config/api.js +175 -175
package/src/utils/errors.ts
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
import Console from "./console"
|
|
2
|
-
|
|
3
|
-
import { ISolution, IError } from "../models/errors"
|
|
4
|
-
|
|
5
|
-
const solutions: { [key: string]: ISolution } = {
|
|
6
|
-
"install-jest": {
|
|
7
|
-
gif: "",
|
|
8
|
-
video: "",
|
|
9
|
-
message: "You need to install jest",
|
|
10
|
-
},
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const uknown: ISolution = {
|
|
14
|
-
video: "https://www.youtube.com/watch?v=gD1Sa99GiE4",
|
|
15
|
-
message: "Uknown internal error",
|
|
16
|
-
slug: "uknown",
|
|
17
|
-
gif: "https://github.com/breatheco-de/breathecode-cli/blob/master/docs/errors/uknown.gif?raw=true",
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const getSolution = (slug?: string): ISolution => {
|
|
21
|
-
if (!slug) {
|
|
22
|
-
Console.debug("Getting solution templates from the learnpack repository")
|
|
23
|
-
} else {
|
|
24
|
-
Console.debug(`Getting solution for ${slug}`, solutions)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return typeof solutions[slug || ""] === "undefined" || !slug ?
|
|
28
|
-
uknown :
|
|
29
|
-
solutions[slug]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const ValidationError = (error: IError | string) => {
|
|
33
|
-
const message: string = (error as IError).message || (error as string)
|
|
34
|
-
const _err = new Error(message) as IError
|
|
35
|
-
_err.status = 400
|
|
36
|
-
_err.type = "validation-error"
|
|
37
|
-
|
|
38
|
-
const sol: ISolution = getSolution((error as IError).slug)
|
|
39
|
-
_err.video = sol.video
|
|
40
|
-
_err.gif = sol.gif
|
|
41
|
-
_err.message = typeof message === "string" ? message : sol.message
|
|
42
|
-
return _err
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const NotFoundError = (error: IError | string) => {
|
|
46
|
-
const message = (error as IError).message || (error as string)
|
|
47
|
-
const _err = new Error(message) as IError
|
|
48
|
-
_err.status = 400
|
|
49
|
-
_err.type = "not-found-error"
|
|
50
|
-
|
|
51
|
-
const sol = getSolution((error as IError).slug)
|
|
52
|
-
_err.video = sol.video
|
|
53
|
-
_err.gif = sol.gif
|
|
54
|
-
_err.message = typeof message === "string" ? message : sol.message
|
|
55
|
-
return _err
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export const CompilerError = (error: IError | string) => {
|
|
59
|
-
const message = (error as IError).message || (error as string)
|
|
60
|
-
const _err = new Error(message) as IError
|
|
61
|
-
_err.status = 400
|
|
62
|
-
_err.type = "compiler-error"
|
|
63
|
-
|
|
64
|
-
const sol = getSolution((error as IError).slug)
|
|
65
|
-
_err.video = sol.video
|
|
66
|
-
_err.gif = sol.gif
|
|
67
|
-
_err.message = typeof message === "string" ? message : sol.message
|
|
68
|
-
return _err
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export const TestingError = (error: IError | string) => {
|
|
72
|
-
const message = (error as IError).message || (error as string)
|
|
73
|
-
const _err = new Error(message) as IError
|
|
74
|
-
_err.status = 400
|
|
75
|
-
_err.type = "testing-error"
|
|
76
|
-
return _err
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const AuthError = (error: IError | string) => {
|
|
80
|
-
const message = (error as IError).message || (error as string)
|
|
81
|
-
const _err = new Error(message) as IError
|
|
82
|
-
_err.status = 403
|
|
83
|
-
_err.type = "auth-error"
|
|
84
|
-
return _err
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export const InternalError = (error: IError | string) => {
|
|
88
|
-
const message = (error as IError).message || (error as string)
|
|
89
|
-
const _err = new Error(message) as IError
|
|
90
|
-
_err.status = 500
|
|
91
|
-
_err.type = "internal-error"
|
|
92
|
-
|
|
93
|
-
const sol = getSolution((error as IError).slug)
|
|
94
|
-
_err.video = sol.video
|
|
95
|
-
_err.gif = sol.gif
|
|
96
|
-
_err.message = typeof message === "string" ? message : sol.message
|
|
97
|
-
return _err
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
getSolution()
|
|
101
|
-
export default {
|
|
102
|
-
ValidationError,
|
|
103
|
-
CompilerError,
|
|
104
|
-
TestingError,
|
|
105
|
-
NotFoundError,
|
|
106
|
-
InternalError,
|
|
107
|
-
AuthError,
|
|
108
|
-
}
|
|
1
|
+
import Console from "./console"
|
|
2
|
+
|
|
3
|
+
import { ISolution, IError } from "../models/errors"
|
|
4
|
+
|
|
5
|
+
const solutions: { [key: string]: ISolution } = {
|
|
6
|
+
"install-jest": {
|
|
7
|
+
gif: "",
|
|
8
|
+
video: "",
|
|
9
|
+
message: "You need to install jest",
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const uknown: ISolution = {
|
|
14
|
+
video: "https://www.youtube.com/watch?v=gD1Sa99GiE4",
|
|
15
|
+
message: "Uknown internal error",
|
|
16
|
+
slug: "uknown",
|
|
17
|
+
gif: "https://github.com/breatheco-de/breathecode-cli/blob/master/docs/errors/uknown.gif?raw=true",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const getSolution = (slug?: string): ISolution => {
|
|
21
|
+
if (!slug) {
|
|
22
|
+
Console.debug("Getting solution templates from the learnpack repository")
|
|
23
|
+
} else {
|
|
24
|
+
Console.debug(`Getting solution for ${slug}`, solutions)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return typeof solutions[slug || ""] === "undefined" || !slug ?
|
|
28
|
+
uknown :
|
|
29
|
+
solutions[slug]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const ValidationError = (error: IError | string) => {
|
|
33
|
+
const message: string = (error as IError).message || (error as string)
|
|
34
|
+
const _err = new Error(message) as IError
|
|
35
|
+
_err.status = 400
|
|
36
|
+
_err.type = "validation-error"
|
|
37
|
+
|
|
38
|
+
const sol: ISolution = getSolution((error as IError).slug)
|
|
39
|
+
_err.video = sol.video
|
|
40
|
+
_err.gif = sol.gif
|
|
41
|
+
_err.message = typeof message === "string" ? message : sol.message
|
|
42
|
+
return _err
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const NotFoundError = (error: IError | string) => {
|
|
46
|
+
const message = (error as IError).message || (error as string)
|
|
47
|
+
const _err = new Error(message) as IError
|
|
48
|
+
_err.status = 400
|
|
49
|
+
_err.type = "not-found-error"
|
|
50
|
+
|
|
51
|
+
const sol = getSolution((error as IError).slug)
|
|
52
|
+
_err.video = sol.video
|
|
53
|
+
_err.gif = sol.gif
|
|
54
|
+
_err.message = typeof message === "string" ? message : sol.message
|
|
55
|
+
return _err
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const CompilerError = (error: IError | string) => {
|
|
59
|
+
const message = (error as IError).message || (error as string)
|
|
60
|
+
const _err = new Error(message) as IError
|
|
61
|
+
_err.status = 400
|
|
62
|
+
_err.type = "compiler-error"
|
|
63
|
+
|
|
64
|
+
const sol = getSolution((error as IError).slug)
|
|
65
|
+
_err.video = sol.video
|
|
66
|
+
_err.gif = sol.gif
|
|
67
|
+
_err.message = typeof message === "string" ? message : sol.message
|
|
68
|
+
return _err
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const TestingError = (error: IError | string) => {
|
|
72
|
+
const message = (error as IError).message || (error as string)
|
|
73
|
+
const _err = new Error(message) as IError
|
|
74
|
+
_err.status = 400
|
|
75
|
+
_err.type = "testing-error"
|
|
76
|
+
return _err
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const AuthError = (error: IError | string) => {
|
|
80
|
+
const message = (error as IError).message || (error as string)
|
|
81
|
+
const _err = new Error(message) as IError
|
|
82
|
+
_err.status = 403
|
|
83
|
+
_err.type = "auth-error"
|
|
84
|
+
return _err
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const InternalError = (error: IError | string) => {
|
|
88
|
+
const message = (error as IError).message || (error as string)
|
|
89
|
+
const _err = new Error(message) as IError
|
|
90
|
+
_err.status = 500
|
|
91
|
+
_err.type = "internal-error"
|
|
92
|
+
|
|
93
|
+
const sol = getSolution((error as IError).slug)
|
|
94
|
+
_err.video = sol.video
|
|
95
|
+
_err.gif = sol.gif
|
|
96
|
+
_err.message = typeof message === "string" ? message : sol.message
|
|
97
|
+
return _err
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getSolution()
|
|
101
|
+
export default {
|
|
102
|
+
ValidationError,
|
|
103
|
+
CompilerError,
|
|
104
|
+
TestingError,
|
|
105
|
+
NotFoundError,
|
|
106
|
+
InternalError,
|
|
107
|
+
AuthError,
|
|
108
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared ordering logic for exercise file lists (e.g. editor tabs).
|
|
3
|
+
* Ensures solution files (*.solution.hide.*) always appear after their base file.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const SOLUTION_HIDE = ".solution.hide"
|
|
7
|
+
|
|
8
|
+
const isSolutionFile = (name: string): boolean => name.includes(SOLUTION_HIDE)
|
|
9
|
+
|
|
10
|
+
const getBaseFileName = (name: string): string =>
|
|
11
|
+
name.replace(SOLUTION_HIDE, "")
|
|
12
|
+
|
|
13
|
+
const FILE_PRIORITY: { [key: string]: number } = {
|
|
14
|
+
"index.html": 1,
|
|
15
|
+
"styles.css": 2,
|
|
16
|
+
"styles.scss": 2,
|
|
17
|
+
"style.css": 2,
|
|
18
|
+
"style.scss": 2,
|
|
19
|
+
"index.css": 2,
|
|
20
|
+
"index.scss": 2,
|
|
21
|
+
"index.js": 3,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const DEFAULT_PRIORITY = Infinity
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Comparator for two file names. Use with Array.prototype.sort.
|
|
28
|
+
* Solution files are ordered after their base file; then by priority; then alphabetically.
|
|
29
|
+
* @param nameA - First file name.
|
|
30
|
+
* @param nameB - Second file name.
|
|
31
|
+
* @returns Negative if nameA < nameB, 0 if equal, positive if nameA > nameB.
|
|
32
|
+
*/
|
|
33
|
+
export function compareExerciseFileNames(nameA: string, nameB: string): number {
|
|
34
|
+
if (isSolutionFile(nameA) && getBaseFileName(nameA) === nameB) return 1
|
|
35
|
+
if (isSolutionFile(nameB) && getBaseFileName(nameB) === nameA) return -1
|
|
36
|
+
|
|
37
|
+
const s1 = FILE_PRIORITY[nameA] ?? DEFAULT_PRIORITY
|
|
38
|
+
const s2 = FILE_PRIORITY[nameB] ?? DEFAULT_PRIORITY
|
|
39
|
+
if (s1 !== s2) return s1 - s2
|
|
40
|
+
return nameA.localeCompare(nameB)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sorts an array of file-like objects by name using exercise file ordering rules.
|
|
45
|
+
* @param files - Array of objects with a `name` property.
|
|
46
|
+
* @returns A new sorted array (original is not mutated).
|
|
47
|
+
*/
|
|
48
|
+
export function sortExerciseFiles<T extends { name: string }>(files: T[]): T[] {
|
|
49
|
+
return [...files].sort((a, b) => compareExerciseFileNames(a.name, b.name))
|
|
50
|
+
}
|