@learnpack/learnpack 2.1.38 → 2.1.40

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. package/README.md +370 -35
  2. package/bin/run +17 -17
  3. package/bin/run.cmd +3 -3
  4. package/lib/commands/audit.d.ts +6 -6
  5. package/lib/commands/audit.js +342 -342
  6. package/lib/commands/clean.d.ts +8 -8
  7. package/lib/commands/clean.js +25 -25
  8. package/lib/commands/download.d.ts +13 -13
  9. package/lib/commands/download.js +55 -55
  10. package/lib/commands/init.d.ts +9 -9
  11. package/lib/commands/init.js +123 -123
  12. package/lib/commands/login.d.ts +14 -14
  13. package/lib/commands/login.js +37 -37
  14. package/lib/commands/logout.d.ts +14 -14
  15. package/lib/commands/logout.js +37 -37
  16. package/lib/commands/publish.d.ts +14 -14
  17. package/lib/commands/publish.js +82 -82
  18. package/lib/commands/start.d.ts +7 -7
  19. package/lib/commands/start.js +239 -205
  20. package/lib/commands/test.d.ts +6 -6
  21. package/lib/commands/test.js +62 -62
  22. package/lib/index.d.ts +1 -1
  23. package/lib/index.js +4 -4
  24. package/lib/managers/config/allowed_files.d.ts +5 -5
  25. package/lib/managers/config/allowed_files.js +30 -30
  26. package/lib/managers/config/defaults.d.ts +41 -41
  27. package/lib/managers/config/defaults.js +44 -44
  28. package/lib/managers/config/exercise.d.ts +36 -36
  29. package/lib/managers/config/exercise.js +236 -236
  30. package/lib/managers/config/index.d.ts +3 -3
  31. package/lib/managers/config/index.js +337 -336
  32. package/lib/managers/file.d.ts +14 -14
  33. package/lib/managers/file.js +153 -153
  34. package/lib/managers/gitpod.d.ts +3 -3
  35. package/lib/managers/gitpod.js +67 -67
  36. package/lib/managers/server/index.d.ts +6 -6
  37. package/lib/managers/server/index.js +58 -58
  38. package/lib/managers/server/routes.d.ts +4 -4
  39. package/lib/managers/server/routes.js +219 -219
  40. package/lib/managers/session.d.ts +3 -3
  41. package/lib/managers/session.js +125 -125
  42. package/lib/managers/socket.d.ts +3 -3
  43. package/lib/managers/socket.js +176 -176
  44. package/lib/managers/telemetry.d.ts +74 -74
  45. package/lib/managers/telemetry.js +206 -206
  46. package/lib/managers/test.js +84 -84
  47. package/lib/models/action.d.ts +2 -2
  48. package/lib/models/action.js +2 -2
  49. package/lib/models/audit.d.ts +15 -15
  50. package/lib/models/audit.js +2 -2
  51. package/lib/models/config-manager.d.ts +21 -21
  52. package/lib/models/config-manager.js +2 -2
  53. package/lib/models/config.d.ts +68 -67
  54. package/lib/models/config.js +2 -2
  55. package/lib/models/counter.d.ts +11 -11
  56. package/lib/models/counter.js +2 -2
  57. package/lib/models/errors.d.ts +15 -15
  58. package/lib/models/errors.js +2 -2
  59. package/lib/models/exercise-obj.d.ts +30 -30
  60. package/lib/models/exercise-obj.js +2 -2
  61. package/lib/models/file.d.ts +5 -5
  62. package/lib/models/file.js +2 -2
  63. package/lib/models/findings.d.ts +17 -17
  64. package/lib/models/findings.js +2 -2
  65. package/lib/models/flags.d.ts +10 -10
  66. package/lib/models/flags.js +2 -2
  67. package/lib/models/front-matter.d.ts +11 -11
  68. package/lib/models/front-matter.js +2 -2
  69. package/lib/models/gitpod-data.d.ts +16 -16
  70. package/lib/models/gitpod-data.js +2 -2
  71. package/lib/models/language.d.ts +4 -4
  72. package/lib/models/language.js +2 -2
  73. package/lib/models/package.d.ts +7 -7
  74. package/lib/models/package.js +2 -2
  75. package/lib/models/plugin-config.d.ts +16 -16
  76. package/lib/models/plugin-config.js +2 -2
  77. package/lib/models/session.d.ts +31 -31
  78. package/lib/models/session.js +2 -2
  79. package/lib/models/socket.d.ts +36 -32
  80. package/lib/models/socket.js +2 -2
  81. package/lib/models/status.d.ts +1 -1
  82. package/lib/models/status.js +2 -2
  83. package/lib/models/success-types.d.ts +1 -1
  84. package/lib/models/success-types.js +2 -2
  85. package/lib/plugin/command/compile.d.ts +6 -6
  86. package/lib/plugin/command/compile.js +18 -18
  87. package/lib/plugin/command/test.d.ts +6 -6
  88. package/lib/plugin/command/test.js +25 -25
  89. package/lib/plugin/index.d.ts +27 -27
  90. package/lib/plugin/index.js +7 -7
  91. package/lib/plugin/plugin.d.ts +8 -8
  92. package/lib/plugin/plugin.js +68 -68
  93. package/lib/plugin/utils.d.ts +16 -16
  94. package/lib/plugin/utils.js +58 -58
  95. package/lib/ui/download.d.ts +5 -5
  96. package/lib/ui/download.js +61 -61
  97. package/lib/utils/BaseCommand.d.ts +8 -8
  98. package/lib/utils/BaseCommand.js +41 -41
  99. package/lib/utils/SessionCommand.d.ts +10 -10
  100. package/lib/utils/SessionCommand.js +43 -43
  101. package/lib/utils/api.d.ts +14 -14
  102. package/lib/utils/api.js +255 -255
  103. package/lib/utils/audit.d.ts +16 -16
  104. package/lib/utils/audit.js +303 -303
  105. package/lib/utils/checkNotInstalled.d.ts +2 -0
  106. package/lib/utils/checkNotInstalled.js +36 -0
  107. package/lib/utils/console.d.ts +12 -12
  108. package/lib/utils/console.js +19 -19
  109. package/lib/utils/errors.d.ts +17 -17
  110. package/lib/utils/errors.js +100 -100
  111. package/lib/utils/exercisesQueue.d.ts +9 -9
  112. package/lib/utils/exercisesQueue.js +38 -38
  113. package/lib/utils/fileQueue.d.ts +40 -40
  114. package/lib/utils/fileQueue.js +168 -168
  115. package/lib/utils/misc.d.ts +1 -1
  116. package/lib/utils/misc.js +23 -23
  117. package/lib/utils/osOperations.d.ts +5 -4
  118. package/lib/utils/osOperations.js +72 -56
  119. package/lib/utils/validators.d.ts +5 -5
  120. package/lib/utils/validators.js +17 -17
  121. package/lib/utils/watcher.d.ts +2 -2
  122. package/lib/utils/watcher.js +25 -25
  123. package/oclif.manifest.json +1 -1
  124. package/package.json +139 -140
  125. package/src/commands/audit.ts +443 -443
  126. package/src/commands/clean.ts +29 -29
  127. package/src/commands/download.ts +61 -61
  128. package/src/commands/init.ts +170 -170
  129. package/src/commands/login.ts +42 -42
  130. package/src/commands/logout.ts +43 -43
  131. package/src/commands/publish.ts +107 -107
  132. package/src/commands/start.ts +54 -17
  133. package/src/commands/test.ts +85 -85
  134. package/src/index.ts +1 -1
  135. package/src/managers/config/allowed_files.ts +29 -29
  136. package/src/managers/config/defaults.ts +42 -42
  137. package/src/managers/config/exercise.ts +311 -311
  138. package/src/managers/config/index.ts +455 -455
  139. package/src/managers/file.ts +196 -196
  140. package/src/managers/gitpod.ts +84 -84
  141. package/src/managers/server/index.ts +78 -78
  142. package/src/managers/server/routes.ts +330 -330
  143. package/src/managers/session.ts +145 -145
  144. package/src/managers/socket.ts +250 -250
  145. package/src/managers/telemetry.ts +346 -346
  146. package/src/managers/test.ts +83 -83
  147. package/src/models/action.ts +10 -10
  148. package/src/models/audit.ts +16 -16
  149. package/src/models/config-manager.ts +23 -23
  150. package/src/models/config.ts +5 -3
  151. package/src/models/counter.ts +11 -11
  152. package/src/models/errors.ts +22 -22
  153. package/src/models/exercise-obj.ts +29 -29
  154. package/src/models/file.ts +5 -5
  155. package/src/models/findings.ts +18 -18
  156. package/src/models/flags.ts +10 -10
  157. package/src/models/front-matter.ts +11 -11
  158. package/src/models/gitpod-data.ts +19 -19
  159. package/src/models/language.ts +4 -4
  160. package/src/models/package.ts +7 -7
  161. package/src/models/plugin-config.ts +17 -17
  162. package/src/models/session.ts +34 -34
  163. package/src/models/socket.ts +5 -0
  164. package/src/models/status.ts +16 -16
  165. package/src/models/success-types.ts +1 -1
  166. package/src/plugin/command/compile.ts +17 -17
  167. package/src/plugin/command/test.ts +30 -30
  168. package/src/plugin/index.ts +6 -6
  169. package/src/plugin/plugin.ts +94 -94
  170. package/src/plugin/utils.ts +87 -87
  171. package/src/types/node-fetch.d.ts +1 -1
  172. package/src/ui/download.ts +71 -71
  173. package/src/utils/BaseCommand.ts +48 -48
  174. package/src/utils/SessionCommand.ts +43 -43
  175. package/src/utils/api.ts +303 -303
  176. package/src/utils/audit.ts +393 -393
  177. package/src/utils/checkNotInstalled.ts +46 -0
  178. package/src/utils/console.ts +24 -24
  179. package/src/utils/errors.ts +117 -117
  180. package/src/utils/exercisesQueue.ts +51 -51
  181. package/src/utils/fileQueue.ts +198 -198
  182. package/src/utils/misc.ts +23 -23
  183. package/src/utils/osOperations.ts +79 -63
  184. package/src/utils/templates/gitignore.txt +19 -19
  185. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.es.md +24 -24
  186. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.md +24 -24
  187. package/src/utils/templates/incremental/README.ejs +4 -4
  188. package/src/utils/templates/incremental/README.es.ejs +4 -4
  189. package/src/utils/templates/isolated/01-hello-world/README.es.md +26 -26
  190. package/src/utils/templates/isolated/01-hello-world/README.md +26 -26
  191. package/src/utils/templates/isolated/README.ejs +4 -4
  192. package/src/utils/templates/isolated/README.es.ejs +4 -4
  193. package/src/utils/templates/no-grading/README.ejs +4 -4
  194. package/src/utils/templates/no-grading/README.es.ejs +4 -4
  195. package/src/utils/validators.ts +18 -18
  196. package/src/utils/watcher.ts +27 -27
@@ -1,198 +1,198 @@
1
- import logger from "../utils/console"
2
- import * as fs from "fs"
3
- // import em from "events"
4
- import * as XXH from "xxhashjs"
5
-
6
- // possible events to dispatch
7
- const events = {
8
- START_EXERCISE: "start_exercise",
9
- INIT: "initializing",
10
- RUNNING: "configuration_loaded",
11
- END: "connection_ended",
12
- RESET_EXERCISE: "reset_exercise",
13
- OPEN_FILES: "open_files",
14
- OPEN_WINDOW: "open_window",
15
- INSTRUCTIONS_CLOSED: "instructions_closed",
16
- }
17
-
18
- let options = {
19
- path: null,
20
- create: false,
21
- }
22
- let lastHash: any = null
23
- let watcher: any = null // subscribe to file and listen to changes
24
- let actions: any = null // action queue
25
-
26
- const loadDispatcher = (opts: any) => {
27
- actions = [{ name: "initializing", time: now() }]
28
- logger.debug(`Loading from ${opts.path}`)
29
-
30
- let exists = fs.existsSync(opts.path)
31
- if (opts.create) {
32
- if (exists)
33
- actions.push({ name: "reset", time: now() })
34
- fs.writeFileSync(opts.path, JSON.stringify(actions), { flag: "w" })
35
- exists = true
36
- }
37
-
38
- if (!exists)
39
- throw new Error(`Invalid queue path, missing file at: ${opts.path}`)
40
-
41
- let incomingActions = []
42
- try {
43
- const content = fs.readFileSync(opts.path, "utf-8")
44
- incomingActions = JSON.parse(content)
45
- if (!Array.isArray(incomingActions))
46
- incomingActions = []
47
- } catch {
48
- incomingActions = []
49
- logger.debug("Error loading VSCode Actions file")
50
- }
51
-
52
- logger.debug("Actions load ", incomingActions)
53
- return incomingActions
54
- }
55
-
56
- // eslint-disable-next-line
57
- const enqueue = (name: string, data: any | undefined = undefined) => {
58
- if (!Object.values(events).includes(name)) {
59
- logger.debug(`Invalid event ${name}`)
60
- throw new Error(`Invalid action ${name}`)
61
- }
62
-
63
- if (!actions)
64
- actions = []
65
-
66
- actions.push({ name, time: now(), data: data })
67
- logger.debug(`EMIT -> ${name}:Exporting changes to ${options.path}`)
68
-
69
- return fs.writeFileSync(options.path || "", JSON.stringify(actions))
70
- }
71
-
72
- const now = () => {
73
- const hrTime = process.hrtime()
74
- // eslint-disable-next-line
75
- const htTime0 = hrTime[0] * 1000000;
76
- return (htTime0 + hrTime[1]) / 1000
77
- }
78
-
79
- const loadFile = (filePath: string) => {
80
- if (!fs.existsSync(filePath))
81
- throw new Error(`No queue.json file to load on ${filePath}`)
82
-
83
- const content = fs.readFileSync(filePath, "utf8")
84
- const newHash = XXH.h32(content, 0xAB_CD).toString(16)
85
- const isUpdated = lastHash !== newHash
86
- lastHash = newHash
87
- const incomingActions = JSON.parse(content)
88
- return { isUpdated, incomingActions }
89
- }
90
-
91
- const dequeue = () => {
92
- // first time dequeue loads
93
- if (!actions)
94
- actions = []
95
-
96
- const { isUpdated, incomingActions } = loadFile(options.path || "")
97
-
98
- if (!isUpdated) {
99
- /**
100
- * make sure no tasks are executed from the queue by matching both
101
- * queues (the incoming with current one)
102
- */
103
- actions = incomingActions
104
- logger.debug(
105
- `No new actions to process: ${actions.length}/${incomingActions.length}`
106
- )
107
- return null
108
- }
109
-
110
- // do i need to reset actions to zero?
111
- if (actions.length > 0 && actions[0].time !== incomingActions[0].time) {
112
- actions = []
113
- }
114
-
115
- const action = incomingActions[incomingActions.length - 1]
116
- logger.debug("Dequeing action ", action)
117
- actions.push(action)
118
- return action
119
- }
120
-
121
- const pull = (callback: (T: any) => any) => {
122
- logger.debug("Pulling actions")
123
- let incoming = dequeue()
124
- while (incoming) {
125
- callback(incoming)
126
- incoming = dequeue()
127
- }
128
- }
129
-
130
- const reset = (callback: (T?: any) => any) => {
131
- logger.debug("Queue reseted")
132
- actions = []
133
- if (fs.existsSync(options.path || "")) {
134
- fs.writeFileSync(options.path || "", "[]")
135
- callback()
136
- }
137
- }
138
-
139
- const onPull = (callback: (T?: any) => any) => {
140
- // eslint-disable-next-line
141
- const chokidar = require("chokidar");
142
-
143
- logger.debug("Starting to listen...")
144
- try {
145
- loadFile(options.path || "")
146
- } catch {
147
- logger.debug("No previoues queue file, waiting for it to be created...")
148
- }
149
-
150
- if (!watcher) {
151
- logger.debug(`Watching ${options.path}`)
152
- watcher = chokidar.watch(`${options.path}`, {
153
- persistent: true,
154
- })
155
- } else
156
- logger.debug("Already watching queue path")
157
-
158
- watcher.on("add", () => pull(callback)).on("change", () => pull(callback))
159
-
160
- return true
161
- }
162
-
163
- const onReset = (callback: (T?: any) => any) => {
164
- // eslint-disable-next-line
165
- const chokidar = require("chokidar");
166
-
167
- if (!watcher) {
168
- logger.debug(`Watching ${options.path}`)
169
- watcher = chokidar.watch(`${options.path}`, {
170
- persistent: true,
171
- })
172
- }
173
-
174
- watcher.on("unlink", () => reset(callback))
175
-
176
- return true
177
- }
178
-
179
- export default {
180
- events,
181
- dispatcher: (opts: any = {}) => {
182
- if (!actions) {
183
- options = { ...options, ...opts }
184
- logger.debug("Initializing queue dispatcher", options)
185
- actions = loadDispatcher(options)
186
- }
187
-
188
- return { enqueue, events }
189
- },
190
- listener: (opts: any = {}) => {
191
- if (!actions) {
192
- options = { ...options, ...opts }
193
- logger.debug("Initializing queue listener", options)
194
- }
195
-
196
- return { onPull, onReset, events }
197
- },
198
- }
1
+ import logger from "../utils/console"
2
+ import * as fs from "fs"
3
+ // import em from "events"
4
+ import * as XXH from "xxhashjs"
5
+
6
+ // possible events to dispatch
7
+ const events = {
8
+ START_EXERCISE: "start_exercise",
9
+ INIT: "initializing",
10
+ RUNNING: "configuration_loaded",
11
+ END: "connection_ended",
12
+ RESET_EXERCISE: "reset_exercise",
13
+ OPEN_FILES: "open_files",
14
+ OPEN_WINDOW: "open_window",
15
+ INSTRUCTIONS_CLOSED: "instructions_closed",
16
+ }
17
+
18
+ let options = {
19
+ path: null,
20
+ create: false,
21
+ }
22
+ let lastHash: any = null
23
+ let watcher: any = null // subscribe to file and listen to changes
24
+ let actions: any = null // action queue
25
+
26
+ const loadDispatcher = (opts: any) => {
27
+ actions = [{ name: "initializing", time: now() }]
28
+ logger.debug(`Loading from ${opts.path}`)
29
+
30
+ let exists = fs.existsSync(opts.path)
31
+ if (opts.create) {
32
+ if (exists)
33
+ actions.push({ name: "reset", time: now() })
34
+ fs.writeFileSync(opts.path, JSON.stringify(actions), { flag: "w" })
35
+ exists = true
36
+ }
37
+
38
+ if (!exists)
39
+ throw new Error(`Invalid queue path, missing file at: ${opts.path}`)
40
+
41
+ let incomingActions = []
42
+ try {
43
+ const content = fs.readFileSync(opts.path, "utf-8")
44
+ incomingActions = JSON.parse(content)
45
+ if (!Array.isArray(incomingActions))
46
+ incomingActions = []
47
+ } catch {
48
+ incomingActions = []
49
+ logger.debug("Error loading VSCode Actions file")
50
+ }
51
+
52
+ logger.debug("Actions load ", incomingActions)
53
+ return incomingActions
54
+ }
55
+
56
+ // eslint-disable-next-line
57
+ const enqueue = (name: string, data: any | undefined = undefined) => {
58
+ if (!Object.values(events).includes(name)) {
59
+ logger.debug(`Invalid event ${name}`)
60
+ throw new Error(`Invalid action ${name}`)
61
+ }
62
+
63
+ if (!actions)
64
+ actions = []
65
+
66
+ actions.push({ name, time: now(), data: data })
67
+ logger.debug(`EMIT -> ${name}:Exporting changes to ${options.path}`)
68
+
69
+ return fs.writeFileSync(options.path || "", JSON.stringify(actions))
70
+ }
71
+
72
+ const now = () => {
73
+ const hrTime = process.hrtime()
74
+ // eslint-disable-next-line
75
+ const htTime0 = hrTime[0] * 1000000;
76
+ return (htTime0 + hrTime[1]) / 1000
77
+ }
78
+
79
+ const loadFile = (filePath: string) => {
80
+ if (!fs.existsSync(filePath))
81
+ throw new Error(`No queue.json file to load on ${filePath}`)
82
+
83
+ const content = fs.readFileSync(filePath, "utf8")
84
+ const newHash = XXH.h32(content, 0xAB_CD).toString(16)
85
+ const isUpdated = lastHash !== newHash
86
+ lastHash = newHash
87
+ const incomingActions = JSON.parse(content)
88
+ return { isUpdated, incomingActions }
89
+ }
90
+
91
+ const dequeue = () => {
92
+ // first time dequeue loads
93
+ if (!actions)
94
+ actions = []
95
+
96
+ const { isUpdated, incomingActions } = loadFile(options.path || "")
97
+
98
+ if (!isUpdated) {
99
+ /**
100
+ * make sure no tasks are executed from the queue by matching both
101
+ * queues (the incoming with current one)
102
+ */
103
+ actions = incomingActions
104
+ logger.debug(
105
+ `No new actions to process: ${actions.length}/${incomingActions.length}`
106
+ )
107
+ return null
108
+ }
109
+
110
+ // do i need to reset actions to zero?
111
+ if (actions.length > 0 && actions[0].time !== incomingActions[0].time) {
112
+ actions = []
113
+ }
114
+
115
+ const action = incomingActions[incomingActions.length - 1]
116
+ logger.debug("Dequeing action ", action)
117
+ actions.push(action)
118
+ return action
119
+ }
120
+
121
+ const pull = (callback: (T: any) => any) => {
122
+ logger.debug("Pulling actions")
123
+ let incoming = dequeue()
124
+ while (incoming) {
125
+ callback(incoming)
126
+ incoming = dequeue()
127
+ }
128
+ }
129
+
130
+ const reset = (callback: (T?: any) => any) => {
131
+ logger.debug("Queue reseted")
132
+ actions = []
133
+ if (fs.existsSync(options.path || "")) {
134
+ fs.writeFileSync(options.path || "", "[]")
135
+ callback()
136
+ }
137
+ }
138
+
139
+ const onPull = (callback: (T?: any) => any) => {
140
+ // eslint-disable-next-line
141
+ const chokidar = require("chokidar");
142
+
143
+ logger.debug("Starting to listen...")
144
+ try {
145
+ loadFile(options.path || "")
146
+ } catch {
147
+ logger.debug("No previoues queue file, waiting for it to be created...")
148
+ }
149
+
150
+ if (!watcher) {
151
+ logger.debug(`Watching ${options.path}`)
152
+ watcher = chokidar.watch(`${options.path}`, {
153
+ persistent: true,
154
+ })
155
+ } else
156
+ logger.debug("Already watching queue path")
157
+
158
+ watcher.on("add", () => pull(callback)).on("change", () => pull(callback))
159
+
160
+ return true
161
+ }
162
+
163
+ const onReset = (callback: (T?: any) => any) => {
164
+ // eslint-disable-next-line
165
+ const chokidar = require("chokidar");
166
+
167
+ if (!watcher) {
168
+ logger.debug(`Watching ${options.path}`)
169
+ watcher = chokidar.watch(`${options.path}`, {
170
+ persistent: true,
171
+ })
172
+ }
173
+
174
+ watcher.on("unlink", () => reset(callback))
175
+
176
+ return true
177
+ }
178
+
179
+ export default {
180
+ events,
181
+ dispatcher: (opts: any = {}) => {
182
+ if (!actions) {
183
+ options = { ...options, ...opts }
184
+ logger.debug("Initializing queue dispatcher", options)
185
+ actions = loadDispatcher(options)
186
+ }
187
+
188
+ return { enqueue, events }
189
+ },
190
+ listener: (opts: any = {}) => {
191
+ if (!actions) {
192
+ options = { ...options, ...opts }
193
+ logger.debug("Initializing queue listener", options)
194
+ }
195
+
196
+ return { onPull, onReset, events }
197
+ },
198
+ }
package/src/utils/misc.ts CHANGED
@@ -1,23 +1,23 @@
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
- }
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
+ }
@@ -1,63 +1,79 @@
1
- import { exec } from "child_process"
2
- import * as os from "os"
3
- import * as path from "path"
4
- import cli from "cli-ux"
5
-
6
- const openFile = (filePath: string): void => {
7
- const fullPath = path.join(process.cwd(), filePath)
8
- let command: string
9
-
10
- switch (os.platform()) {
11
- case "darwin": // macOS
12
- command = `open ${fullPath}`
13
- break
14
- case "win32": // Windows
15
- command = `start ${fullPath}`
16
- break
17
- case "linux": // Linux
18
- command = `xdg-open ${fullPath}`
19
- break
20
- default:
21
- throw new Error("Unsupported OS")
22
- }
23
-
24
- exec(command, (error, stdout, stderr) => {
25
- if (error) {
26
- console.error(`exec error: ${error}`)
27
-
28
- }
29
- })
30
- }
31
-
32
- const eventManager = {
33
- enqueue: (event: string, data: any) => {
34
- if (event === "start_exercise") {
35
- const exercise = data
36
- const filesToOpen = exercise.files
37
- .filter((file: any) => !file.hidden)
38
- .map((file: any) => {
39
- return file.path.replace("\\", "/")
40
- })
41
-
42
- for (const file of filesToOpen) {
43
- openFile(file)
44
- }
45
- }
46
-
47
- if (event === "open_files") {
48
- const files = data
49
-
50
- for (const file of files) {
51
- const correctedPath = file.replace("\\", "/")
52
- openFile(correctedPath)
53
- }
54
- }
55
-
56
- if (event === "open_window") {
57
- const url = data.url
58
- cli.open(url)
59
- }
60
- },
61
- }
62
-
63
- export { eventManager }
1
+ import { exec } from "child_process"
2
+ import * as os from "os"
3
+ import * as path from "path"
4
+ import cli from "cli-ux"
5
+
6
+ const checkXDGInstalled = (): Promise<boolean> => {
7
+ return new Promise((resolve, reject) => {
8
+ exec("which xdg-open", (error, stdout, stderr) => {
9
+ if (error) {
10
+ resolve(false)
11
+ }
12
+
13
+ if (stdout) {
14
+ resolve(true)
15
+ } else {
16
+ resolve(false)
17
+ }
18
+ })
19
+ })
20
+ }
21
+
22
+ const openFile = (filePath: string): void => {
23
+ const fullPath = path.join(process.cwd(), filePath)
24
+ let command: string
25
+
26
+ switch (os.platform()) {
27
+ case "darwin": // macOS
28
+ command = `open ${fullPath}`
29
+ break
30
+ case "win32": // Windows
31
+ command = `start ${fullPath}`
32
+ break
33
+ case "linux": // Linux
34
+ command = `xdg-open ${fullPath}`
35
+ break
36
+ default:
37
+ throw new Error("Unsupported OS")
38
+ }
39
+
40
+ exec(command, (error, stdout, stderr) => {
41
+ if (error) {
42
+ console.error(`exec error: ${error}`)
43
+ }
44
+ })
45
+ }
46
+
47
+ const eventManager = {
48
+ enqueue: (event: string, data: any) => {
49
+ if (event === "start_exercise") {
50
+ const exercise = data
51
+ const filesToOpen = exercise.files
52
+ .filter((file: any) => !file.hidden)
53
+ .map((file: any) => {
54
+ return file.path.replace("\\", "/")
55
+ })
56
+
57
+ for (const file of filesToOpen) {
58
+ openFile(file)
59
+ }
60
+ }
61
+
62
+ if (event === "open_files") {
63
+ const files = data
64
+
65
+ for (const file of files) {
66
+ const correctedPath = file.replace("\\", "/")
67
+ openFile(correctedPath)
68
+ }
69
+ }
70
+
71
+ if (event === "open_window") {
72
+ const url = data.url
73
+ cli.open(url)
74
+ }
75
+ },
76
+ checkXDGInstalled,
77
+ }
78
+
79
+ export { eventManager }
@@ -1,20 +1,20 @@
1
- # configuration and readme
2
- !.gitignore
3
- !.gitpod.yml
4
- !.gitpod.Dockerfile
5
- !learn.json
6
- !README.md
7
-
8
- # exercises
9
- !.learn/
10
- !.learn/*
11
- .learn/_app
12
- .learn/.session
13
- .learn/dist
14
- .learn/app.tar.gz
15
- .learn/config.json
16
-
17
- # python compiled files
18
- *.pyc
19
- __pycache__/
1
+ # configuration and readme
2
+ !.gitignore
3
+ !.gitpod.yml
4
+ !.gitpod.Dockerfile
5
+ !learn.json
6
+ !README.md
7
+
8
+ # exercises
9
+ !.learn/
10
+ !.learn/*
11
+ .learn/_app
12
+ .learn/.session
13
+ .learn/dist
14
+ .learn/app.tar.gz
15
+ .learn/config.json
16
+
17
+ # python compiled files
18
+ *.pyc
19
+ __pycache__/
20
20
  .pytest_cache/
@@ -1,24 +1,24 @@
1
- # `01` Hello World
2
-
3
- Puedes tener un archivo README el cual será como una página de un libro, sin archivos de código.
4
-
5
- También puedes agregar un archivo `README.[lenguaje].md` para traducciones, por ejemplo `README.es.md` para español.
6
-
7
- ## Inserta videos
8
-
9
- 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:
10
-
11
- ```markdown
12
- ---
13
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
14
- ---
15
- ```
16
-
17
- Tambien puedes agregar un video explicando la solución para cada ejercicio agregando la propiedad `tutorial` al inicio del markdown del README.md correspondiente:
18
-
19
- ```markdown
20
- ---
21
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
22
- tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
23
- ---
24
- ```
1
+ # `01` Hello World
2
+
3
+ Puedes tener un archivo README el cual será como una página de un libro, sin archivos de código.
4
+
5
+ También puedes agregar un archivo `README.[lenguaje].md` para traducciones, por ejemplo `README.es.md` para español.
6
+
7
+ ## Inserta videos
8
+
9
+ 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:
10
+
11
+ ```markdown
12
+ ---
13
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
14
+ ---
15
+ ```
16
+
17
+ Tambien puedes agregar un video explicando la solución para cada ejercicio agregando la propiedad `tutorial` al inicio del markdown del README.md correspondiente:
18
+
19
+ ```markdown
20
+ ---
21
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
22
+ tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
23
+ ---
24
+ ```