@learnpack/learnpack 5.0.309 → 5.0.311

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.
Files changed (88) hide show
  1. package/README.md +409 -409
  2. package/lib/commands/audit.js +15 -15
  3. package/lib/commands/breakToken.js +19 -19
  4. package/lib/commands/clean.js +3 -3
  5. package/lib/commands/logout.js +3 -3
  6. package/lib/commands/publish.js +16 -6
  7. package/lib/commands/serve.js +16 -16
  8. package/lib/creatorDist/assets/{index-B37w_ZhT.js → index-BI7U47zy.js} +13186 -13013
  9. package/lib/creatorDist/index.html +1 -1
  10. package/lib/managers/config/index.js +77 -77
  11. package/lib/utils/creatorUtilities.js +14 -14
  12. package/lib/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  13. package/lib/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  14. package/lib/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
  15. package/lib/utils/templates/scorm/config/index.html +209 -209
  16. package/lib/utils/templates/scorm/ims_xml.xsd +1 -1
  17. package/lib/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
  18. package/lib/utils/templates/scorm/imsmanifest.xml +38 -38
  19. package/lib/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
  20. package/package.json +1 -1
  21. package/src/commands/audit.ts +487 -487
  22. package/src/commands/breakToken.ts +67 -67
  23. package/src/commands/clean.ts +30 -30
  24. package/src/commands/logout.ts +38 -38
  25. package/src/commands/publish.ts +39 -23
  26. package/src/commands/serve.ts +3179 -3179
  27. package/src/commands/start.ts +333 -333
  28. package/src/commands/translate.ts +123 -123
  29. package/src/creator/README.md +54 -54
  30. package/src/creator/package-lock.json +6621 -6621
  31. package/src/creator/package.json +55 -55
  32. package/src/creator/src/App.tsx +611 -608
  33. package/src/creator/src/components/FileUploader.tsx +340 -302
  34. package/src/creator/src/components/Icon.tsx +18 -18
  35. package/src/creator/src/components/LessonItem.tsx +152 -152
  36. package/src/creator/src/components/Login.tsx +259 -259
  37. package/src/creator/src/components/ParamsChecker.tsx +25 -25
  38. package/src/creator/src/components/Uploader.tsx +3 -6
  39. package/src/creator/src/components/syllabus/ContentIndex.tsx +323 -323
  40. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +341 -337
  41. package/src/creator/src/i18n.ts +28 -28
  42. package/src/creator/src/locales/en.json +139 -138
  43. package/src/creator/src/locales/es.json +139 -138
  44. package/src/creator/src/utils/configTypes.ts +122 -122
  45. package/src/creator/src/utils/constants.ts +13 -13
  46. package/src/creator/src/utils/creatorUtils.ts +46 -46
  47. package/src/creator/src/utils/eventBus.ts +2 -2
  48. package/src/creator/src/utils/rigo.ts +1 -1
  49. package/src/creator/src/utils/socket.ts +61 -61
  50. package/src/creator/src/utils/store.ts +222 -222
  51. package/src/creator/src/vite-env.d.ts +1 -1
  52. package/src/creator/vite.config.ts +13 -13
  53. package/src/creatorDist/assets/{index-B37w_ZhT.js → index-BI7U47zy.js} +13186 -13013
  54. package/src/creatorDist/index.html +1 -1
  55. package/src/managers/config/defaults.ts +49 -49
  56. package/src/managers/config/exercise.ts +364 -364
  57. package/src/managers/config/index.ts +775 -775
  58. package/src/managers/file.ts +236 -236
  59. package/src/managers/server/routes.ts +554 -554
  60. package/src/managers/telemetry.ts +188 -188
  61. package/src/models/action.ts +13 -13
  62. package/src/models/config-manager.ts +28 -28
  63. package/src/models/config.ts +106 -106
  64. package/src/models/exercise-obj.ts +30 -30
  65. package/src/models/session.ts +39 -39
  66. package/src/models/socket.ts +61 -61
  67. package/src/models/status.ts +16 -16
  68. package/src/ui/_app/app.css +1 -1
  69. package/src/ui/_app/app.js +477 -407
  70. package/src/ui/app.tar.gz +0 -0
  71. package/src/utils/BaseCommand.ts +56 -56
  72. package/src/utils/api.ts +665 -665
  73. package/src/utils/audit.ts +392 -392
  74. package/src/utils/checkNotInstalled.ts +267 -267
  75. package/src/utils/convertCreds.js +34 -34
  76. package/src/utils/creatorUtilities.ts +504 -504
  77. package/src/utils/export/README.md +178 -178
  78. package/src/utils/incrementVersion.js +74 -74
  79. package/src/utils/misc.ts +58 -58
  80. package/src/utils/sidebarGenerator.ts +195 -195
  81. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  82. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  83. package/src/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
  84. package/src/utils/templates/scorm/config/index.html +209 -209
  85. package/src/utils/templates/scorm/ims_xml.xsd +1 -1
  86. package/src/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
  87. package/src/utils/templates/scorm/imsmanifest.xml +38 -38
  88. package/src/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
@@ -1,195 +1,195 @@
1
- import path = require("path")
2
-
3
- import Console from "./console"
4
- import fs = require("fs")
5
- import { IExercise, IExerciseData } from "../models/exercise-obj"
6
- import { IConfigObj } from "../models/config"
7
- import SessionManager from "../managers/session"
8
- import { fillSidebarJSON } from "./rigoActions"
9
-
10
- type TTitleTranslations = {
11
- [key: string]: string
12
- }
13
-
14
- export type TSidebar = {
15
- [key: string]: TTitleTranslations
16
- }
17
-
18
- export const generateSidebar = (exercises: IExercise[], learnPath: string) => {
19
- const sidebarPath = path.join(learnPath, "sidebar.json")
20
- let sidebar: TSidebar = {}
21
- if (fs.existsSync(sidebarPath)) {
22
- sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
23
- }
24
-
25
- for (const exercise of exercises) {
26
- sidebar[exercise.slug] = {
27
- ...sidebar[exercise.slug],
28
- us: exercise.title,
29
- }
30
- }
31
-
32
- fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
33
-
34
- return sidebar
35
- }
36
-
37
- export const addExerciseToSidebar = (
38
- exerciseSlug: string,
39
- targetLanguage: string,
40
- translatedSlug: string,
41
- learnPath: string
42
- ) => {
43
- const sidebarPath = path.join(learnPath, "sidebar.json")
44
- let sidebar: TSidebar = {}
45
- if (fs.existsSync(sidebarPath)) {
46
- sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
47
- }
48
-
49
- sidebar[exerciseSlug] = {
50
- ...sidebar[exerciseSlug],
51
- [targetLanguage]: translatedSlug,
52
- }
53
-
54
- fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
55
-
56
- return sidebar
57
- }
58
-
59
- export const checkAndFixSidebar = async (
60
- configObj: IConfigObj,
61
- autoFix = false
62
- ): Promise<boolean> => {
63
- if (
64
- configObj.config &&
65
- fs.existsSync(configObj.config.dirPath + "/sidebar.json")
66
- ) {
67
- let hasErrors = false
68
- const sidebar = fs.readFileSync(
69
- configObj.config.dirPath + "/sidebar.json",
70
- "utf8"
71
- )
72
- // parse the sidebar.json file
73
- const sidebarJson = JSON.parse(sidebar)
74
-
75
- const exerciseTranslations: Set<string> = new Set()
76
- configObj.exercises?.map(e =>
77
- // eslint-disable-next-line
78
- Object.keys((e.translations || {}) as any).forEach((t) =>
79
- exerciseTranslations.add(t)
80
- )
81
- )
82
- // Validation
83
- for (const [key, value] of Object.entries(sidebarJson) as [
84
- string,
85
- TTitleTranslations
86
- ][]) {
87
- for (const lang of exerciseTranslations) {
88
- if (!Object.prototype.hasOwnProperty.call(value, lang)) {
89
- hasErrors = true
90
- }
91
- }
92
- }
93
-
94
- if (hasErrors && autoFix) {
95
- Console.warning("Filling sidebar.json file with missing translations")
96
- const sessionPayload = await SessionManager.getPayload()
97
-
98
- const rigoToken = sessionPayload.rigobot.key
99
-
100
- if (!rigoToken) {
101
- Console.error("No Rigobot token found, please login first!")
102
- return false
103
- }
104
-
105
- const response = await fillSidebarJSON(rigoToken, {
106
- needed_translations: JSON.stringify(exerciseTranslations),
107
- sidebar_json: JSON.stringify(sidebarJson),
108
- })
109
-
110
- const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
111
- fs.writeFileSync(
112
- configObj.config.dirPath + "/sidebar.json",
113
- JSON.stringify(newSidebarJson, null, 4)
114
- )
115
- Console.info("Sidebar.json was filled with missing translations")
116
- return true
117
- }
118
-
119
- if (hasErrors && !autoFix) {
120
- return false
121
- }
122
-
123
- return true
124
- }
125
-
126
- return false
127
- }
128
-
129
- export const checkAndFixSidebarPure = async (
130
- sidebarJson: Record<string, Record<string, string>>,
131
- exercises: any[],
132
- rigoToken: string,
133
- autoFix = true
134
- ): Promise<{
135
- valid: boolean
136
- fixedSidebar?: Record<string, Record<string, string>>
137
- }> => {
138
- const exerciseTranslations: Set<string> = new Set()
139
- for (const e of exercises) {
140
- for (const lang of Object.keys(e.translations || {})) {
141
- exerciseTranslations.add(lang)
142
- }
143
- }
144
-
145
- let hasErrors = false
146
- const fixedSidebar: Record<string, Record<string, string>> = {
147
- ...sidebarJson,
148
- }
149
-
150
- for (const exercise of exercises) {
151
- const slug = exercise.slug
152
- const existingEntry = fixedSidebar[slug]
153
-
154
- if (!existingEntry) {
155
- hasErrors = true
156
- fixedSidebar[slug] = { us: exercise.slug }
157
- continue
158
- }
159
-
160
- for (const lang of exerciseTranslations) {
161
- if (!Object.prototype.hasOwnProperty.call(existingEntry, lang)) {
162
- hasErrors = true
163
- }
164
- }
165
- }
166
-
167
- if (hasErrors && autoFix) {
168
- if (!rigoToken) {
169
- Console.error("No Rigobot token provided!")
170
- return { valid: false }
171
- }
172
-
173
- Console.warning(
174
- "Filling sidebar JSON with missing translations or exercises"
175
- )
176
-
177
- const response = await fillSidebarJSON(rigoToken, {
178
- needed_translations: JSON.stringify([...exerciseTranslations]),
179
- sidebar_json: JSON.stringify(fixedSidebar),
180
- })
181
-
182
- const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
183
-
184
- Console.info("Sidebar JSON was fixed")
185
- return {
186
- valid: true,
187
- fixedSidebar: newSidebarJson,
188
- }
189
- }
190
-
191
- return {
192
- valid: !hasErrors,
193
- fixedSidebar: hasErrors ? fixedSidebar : undefined,
194
- }
195
- }
1
+ import path = require("path")
2
+
3
+ import Console from "./console"
4
+ import fs = require("fs")
5
+ import { IExercise, IExerciseData } from "../models/exercise-obj"
6
+ import { IConfigObj } from "../models/config"
7
+ import SessionManager from "../managers/session"
8
+ import { fillSidebarJSON } from "./rigoActions"
9
+
10
+ type TTitleTranslations = {
11
+ [key: string]: string
12
+ }
13
+
14
+ export type TSidebar = {
15
+ [key: string]: TTitleTranslations
16
+ }
17
+
18
+ export const generateSidebar = (exercises: IExercise[], learnPath: string) => {
19
+ const sidebarPath = path.join(learnPath, "sidebar.json")
20
+ let sidebar: TSidebar = {}
21
+ if (fs.existsSync(sidebarPath)) {
22
+ sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
23
+ }
24
+
25
+ for (const exercise of exercises) {
26
+ sidebar[exercise.slug] = {
27
+ ...sidebar[exercise.slug],
28
+ us: exercise.title,
29
+ }
30
+ }
31
+
32
+ fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
33
+
34
+ return sidebar
35
+ }
36
+
37
+ export const addExerciseToSidebar = (
38
+ exerciseSlug: string,
39
+ targetLanguage: string,
40
+ translatedSlug: string,
41
+ learnPath: string
42
+ ) => {
43
+ const sidebarPath = path.join(learnPath, "sidebar.json")
44
+ let sidebar: TSidebar = {}
45
+ if (fs.existsSync(sidebarPath)) {
46
+ sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
47
+ }
48
+
49
+ sidebar[exerciseSlug] = {
50
+ ...sidebar[exerciseSlug],
51
+ [targetLanguage]: translatedSlug,
52
+ }
53
+
54
+ fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
55
+
56
+ return sidebar
57
+ }
58
+
59
+ export const checkAndFixSidebar = async (
60
+ configObj: IConfigObj,
61
+ autoFix = false
62
+ ): Promise<boolean> => {
63
+ if (
64
+ configObj.config &&
65
+ fs.existsSync(configObj.config.dirPath + "/sidebar.json")
66
+ ) {
67
+ let hasErrors = false
68
+ const sidebar = fs.readFileSync(
69
+ configObj.config.dirPath + "/sidebar.json",
70
+ "utf8"
71
+ )
72
+ // parse the sidebar.json file
73
+ const sidebarJson = JSON.parse(sidebar)
74
+
75
+ const exerciseTranslations: Set<string> = new Set()
76
+ configObj.exercises?.map(e =>
77
+ // eslint-disable-next-line
78
+ Object.keys((e.translations || {}) as any).forEach((t) =>
79
+ exerciseTranslations.add(t)
80
+ )
81
+ )
82
+ // Validation
83
+ for (const [key, value] of Object.entries(sidebarJson) as [
84
+ string,
85
+ TTitleTranslations
86
+ ][]) {
87
+ for (const lang of exerciseTranslations) {
88
+ if (!Object.prototype.hasOwnProperty.call(value, lang)) {
89
+ hasErrors = true
90
+ }
91
+ }
92
+ }
93
+
94
+ if (hasErrors && autoFix) {
95
+ Console.warning("Filling sidebar.json file with missing translations")
96
+ const sessionPayload = await SessionManager.getPayload()
97
+
98
+ const rigoToken = sessionPayload.rigobot.key
99
+
100
+ if (!rigoToken) {
101
+ Console.error("No Rigobot token found, please login first!")
102
+ return false
103
+ }
104
+
105
+ const response = await fillSidebarJSON(rigoToken, {
106
+ needed_translations: JSON.stringify(exerciseTranslations),
107
+ sidebar_json: JSON.stringify(sidebarJson),
108
+ })
109
+
110
+ const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
111
+ fs.writeFileSync(
112
+ configObj.config.dirPath + "/sidebar.json",
113
+ JSON.stringify(newSidebarJson, null, 4)
114
+ )
115
+ Console.info("Sidebar.json was filled with missing translations")
116
+ return true
117
+ }
118
+
119
+ if (hasErrors && !autoFix) {
120
+ return false
121
+ }
122
+
123
+ return true
124
+ }
125
+
126
+ return false
127
+ }
128
+
129
+ export const checkAndFixSidebarPure = async (
130
+ sidebarJson: Record<string, Record<string, string>>,
131
+ exercises: any[],
132
+ rigoToken: string,
133
+ autoFix = true
134
+ ): Promise<{
135
+ valid: boolean
136
+ fixedSidebar?: Record<string, Record<string, string>>
137
+ }> => {
138
+ const exerciseTranslations: Set<string> = new Set()
139
+ for (const e of exercises) {
140
+ for (const lang of Object.keys(e.translations || {})) {
141
+ exerciseTranslations.add(lang)
142
+ }
143
+ }
144
+
145
+ let hasErrors = false
146
+ const fixedSidebar: Record<string, Record<string, string>> = {
147
+ ...sidebarJson,
148
+ }
149
+
150
+ for (const exercise of exercises) {
151
+ const slug = exercise.slug
152
+ const existingEntry = fixedSidebar[slug]
153
+
154
+ if (!existingEntry) {
155
+ hasErrors = true
156
+ fixedSidebar[slug] = { us: exercise.slug }
157
+ continue
158
+ }
159
+
160
+ for (const lang of exerciseTranslations) {
161
+ if (!Object.prototype.hasOwnProperty.call(existingEntry, lang)) {
162
+ hasErrors = true
163
+ }
164
+ }
165
+ }
166
+
167
+ if (hasErrors && autoFix) {
168
+ if (!rigoToken) {
169
+ Console.error("No Rigobot token provided!")
170
+ return { valid: false }
171
+ }
172
+
173
+ Console.warning(
174
+ "Filling sidebar JSON with missing translations or exercises"
175
+ )
176
+
177
+ const response = await fillSidebarJSON(rigoToken, {
178
+ needed_translations: JSON.stringify([...exerciseTranslations]),
179
+ sidebar_json: JSON.stringify(fixedSidebar),
180
+ })
181
+
182
+ const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
183
+
184
+ Console.info("Sidebar JSON was fixed")
185
+ return {
186
+ valid: true,
187
+ fixedSidebar: newSidebarJson,
188
+ }
189
+ }
190
+
191
+ return {
192
+ valid: !hasErrors,
193
+ fixedSidebar: hasErrors ? fixedSidebar : undefined,
194
+ }
195
+ }
@@ -1,26 +1,26 @@
1
- # `01` Primer Ejercicio
2
-
3
- Hemos creado este primer ejercicio como ejemplo. Lo puedes ubicar en la carpeta `./01-hello-world`.
4
-
5
- 1. Cada ejercicio debe estar ubicado en carpetas separadas y debe tener un archivo README.md con las instrucciones del ejercicio escrito en markdown.
6
- 2. Puedes tener un archivo README el cual será como una página de un libro, sin archivos de código.
7
- 3. También puedes agregar un archivo `README.[lenguaje].md` para traducciones, por ejemplo `README.es.md` para español.
8
-
9
- ## Inserta videos
10
-
11
- Si quieres incluir algún video introductorio para cada ejercicio, agrega la propiedad `intro` en el inicio del README.md para ese ejercicio en particular:
12
-
13
- ```markdown
14
- ---
15
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
- ---
17
- ```
18
-
19
- Tambien puedes agregar un video explicando la solución para cada ejercicio agregando la propiedad `tutorial` al inicio del markdown del README.md correspondiente:
20
-
21
- ```markdown
22
- ---
23
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
- tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
- ---
26
- ```
1
+ # `01` Primer Ejercicio
2
+
3
+ Hemos creado este primer ejercicio como ejemplo. Lo puedes ubicar en la carpeta `./01-hello-world`.
4
+
5
+ 1. Cada ejercicio debe estar ubicado en carpetas separadas y debe tener un archivo README.md con las instrucciones del ejercicio escrito en markdown.
6
+ 2. Puedes tener un archivo README el cual será como una página de un libro, sin archivos de código.
7
+ 3. También puedes agregar un archivo `README.[lenguaje].md` para traducciones, por ejemplo `README.es.md` para español.
8
+
9
+ ## Inserta videos
10
+
11
+ Si quieres incluir algún video introductorio para cada ejercicio, agrega la propiedad `intro` en el inicio del README.md para ese ejercicio en particular:
12
+
13
+ ```markdown
14
+ ---
15
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
+ ---
17
+ ```
18
+
19
+ Tambien puedes agregar un video explicando la solución para cada ejercicio agregando la propiedad `tutorial` al inicio del markdown del README.md correspondiente:
20
+
21
+ ```markdown
22
+ ---
23
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
+ tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
+ ---
26
+ ```
@@ -1,26 +1,26 @@
1
- # `01` First Exercise
2
-
3
- We created this first exercise as an example, you can find it located in the folder `./01-hello-world`.
4
-
5
- 1. Every exercise must be located on a separate folder and it must have a README.md file inside with the exercise instructions written in markdown.
6
- 2. You can have just a README file and it will be like a page in a book, no code files.
7
- 3. You can also add a `README.[lang].md` file for translations, for example: `README.es.md` for spanish.
8
-
9
- ## Video compatibility
10
-
11
- If you want to include some video introduction for each exercise, add a `intro` property in the markdown frontmatter of the README.md for that particular exercise:
12
-
13
- ```markdown
14
- ---
15
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
- ---
17
- ```
18
-
19
- You can also add a video solution for each exercise by adding a `tutorial` property on the markdown frontmatter of it's README.md:
20
-
21
- ```markdown
22
- ---
23
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
- tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
- ---
26
- ```
1
+ # `01` First Exercise
2
+
3
+ We created this first exercise as an example, you can find it located in the folder `./01-hello-world`.
4
+
5
+ 1. Every exercise must be located on a separate folder and it must have a README.md file inside with the exercise instructions written in markdown.
6
+ 2. You can have just a README file and it will be like a page in a book, no code files.
7
+ 3. You can also add a `README.[lang].md` file for translations, for example: `README.es.md` for spanish.
8
+
9
+ ## Video compatibility
10
+
11
+ If you want to include some video introduction for each exercise, add a `intro` property in the markdown frontmatter of the README.md for that particular exercise:
12
+
13
+ ```markdown
14
+ ---
15
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
+ ---
17
+ ```
18
+
19
+ You can also add a video solution for each exercise by adding a `tutorial` property on the markdown frontmatter of it's README.md:
20
+
21
+ ```markdown
22
+ ---
23
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
+ tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
+ ---
26
+ ```