@learnpack/learnpack 5.0.275 → 5.0.276

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 (71) 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/init.js +41 -41
  6. package/lib/commands/logout.js +3 -3
  7. package/lib/commands/publish.js +5 -10
  8. package/lib/commands/serve.js +3 -2
  9. package/lib/creatorDist/assets/index-BfLyIQVh.js +10343 -10224
  10. package/lib/managers/config/index.js +77 -77
  11. package/lib/utils/api.d.ts +1 -1
  12. package/lib/utils/api.js +12 -9
  13. package/lib/utils/creatorUtilities.js +14 -14
  14. package/package.json +1 -1
  15. package/src/commands/audit.ts +487 -487
  16. package/src/commands/breakToken.ts +67 -67
  17. package/src/commands/clean.ts +30 -30
  18. package/src/commands/init.ts +650 -650
  19. package/src/commands/logout.ts +38 -38
  20. package/src/commands/publish.ts +20 -25
  21. package/src/commands/serve.ts +8 -3
  22. package/src/commands/start.ts +333 -333
  23. package/src/commands/translate.ts +123 -123
  24. package/src/creator/README.md +54 -54
  25. package/src/creator/eslint.config.js +28 -28
  26. package/src/creator/src/components/syllabus/ContentIndex.tsx +312 -312
  27. package/src/creator/src/i18n.ts +28 -28
  28. package/src/creator/src/index.css +217 -217
  29. package/src/creator/src/locales/en.json +126 -126
  30. package/src/creator/src/locales/es.json +126 -126
  31. package/src/creator/src/utils/configTypes.ts +122 -122
  32. package/src/creator/src/utils/constants.ts +13 -13
  33. package/src/creator/src/utils/creatorUtils.ts +46 -46
  34. package/src/creator/src/utils/eventBus.ts +2 -2
  35. package/src/creator/src/utils/lib.ts +468 -468
  36. package/src/creator/src/utils/socket.ts +61 -61
  37. package/src/creator/src/utils/store.ts +222 -222
  38. package/src/creator/src/vite-env.d.ts +1 -1
  39. package/src/creator/vite.config.ts +13 -13
  40. package/src/creatorDist/assets/index-BfLyIQVh.js +10343 -10224
  41. package/src/managers/config/defaults.ts +49 -49
  42. package/src/managers/config/exercise.ts +364 -364
  43. package/src/managers/config/index.ts +775 -775
  44. package/src/managers/file.ts +236 -236
  45. package/src/managers/server/routes.ts +554 -554
  46. package/src/managers/session.ts +182 -182
  47. package/src/managers/telemetry.ts +188 -188
  48. package/src/models/action.ts +13 -13
  49. package/src/models/config-manager.ts +28 -28
  50. package/src/models/config.ts +106 -106
  51. package/src/models/creator.ts +47 -47
  52. package/src/models/exercise-obj.ts +30 -30
  53. package/src/models/session.ts +39 -39
  54. package/src/models/socket.ts +61 -61
  55. package/src/models/status.ts +16 -16
  56. package/src/ui/_app/app.css +1 -1
  57. package/src/ui/_app/app.js +366 -363
  58. package/src/ui/app.tar.gz +0 -0
  59. package/src/utils/BaseCommand.ts +56 -56
  60. package/src/utils/api.ts +53 -39
  61. package/src/utils/audit.ts +392 -392
  62. package/src/utils/checkNotInstalled.ts +267 -267
  63. package/src/utils/configBuilder.ts +82 -82
  64. package/src/utils/convertCreds.js +34 -34
  65. package/src/utils/creatorUtilities.ts +504 -504
  66. package/src/utils/incrementVersion.js +74 -74
  67. package/src/utils/misc.ts +58 -58
  68. package/src/utils/rigoActions.ts +500 -500
  69. package/src/utils/sidebarGenerator.ts +195 -195
  70. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  71. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
@@ -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
+ ```