@learnpack/learnpack 2.1.25 → 2.1.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. package/README.md +16 -16
  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 +327 -302
  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 +165 -165
  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 +39 -37
  27. package/lib/managers/config/defaults.js +40 -38
  28. package/lib/managers/config/exercise.d.ts +36 -36
  29. package/lib/managers/config/exercise.js +233 -230
  30. package/lib/managers/config/index.d.ts +3 -3
  31. package/lib/managers/config/index.js +320 -302
  32. package/lib/managers/file.d.ts +13 -13
  33. package/lib/managers/file.js +134 -134
  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 -51
  38. package/lib/managers/server/routes.d.ts +4 -4
  39. package/lib/managers/server/routes.js +167 -167
  40. package/lib/managers/session.d.ts +3 -3
  41. package/lib/managers/session.js +104 -104
  42. package/lib/managers/socket.d.ts +3 -3
  43. package/lib/managers/socket.js +164 -164
  44. package/lib/managers/test.js +84 -84
  45. package/lib/models/action.d.ts +2 -2
  46. package/lib/models/action.js +2 -2
  47. package/lib/models/audit.d.ts +15 -15
  48. package/lib/models/audit.js +2 -2
  49. package/lib/models/config-manager.d.ts +21 -21
  50. package/lib/models/config-manager.js +2 -2
  51. package/lib/models/config.d.ts +62 -60
  52. package/lib/models/config.js +2 -2
  53. package/lib/models/counter.d.ts +11 -11
  54. package/lib/models/counter.js +2 -2
  55. package/lib/models/errors.d.ts +15 -15
  56. package/lib/models/errors.js +2 -2
  57. package/lib/models/exercise-obj.d.ts +27 -27
  58. package/lib/models/exercise-obj.js +2 -2
  59. package/lib/models/file.d.ts +5 -5
  60. package/lib/models/file.js +2 -2
  61. package/lib/models/findings.d.ts +17 -17
  62. package/lib/models/findings.js +2 -2
  63. package/lib/models/flags.d.ts +10 -10
  64. package/lib/models/flags.js +2 -2
  65. package/lib/models/front-matter.d.ts +11 -11
  66. package/lib/models/front-matter.js +2 -2
  67. package/lib/models/gitpod-data.d.ts +16 -16
  68. package/lib/models/gitpod-data.js +2 -2
  69. package/lib/models/language.d.ts +4 -4
  70. package/lib/models/language.js +2 -2
  71. package/lib/models/package.d.ts +7 -7
  72. package/lib/models/package.js +2 -2
  73. package/lib/models/plugin-config.d.ts +16 -16
  74. package/lib/models/plugin-config.js +2 -2
  75. package/lib/models/session.d.ts +23 -23
  76. package/lib/models/session.js +2 -2
  77. package/lib/models/socket.d.ts +31 -31
  78. package/lib/models/socket.js +2 -2
  79. package/lib/models/status.d.ts +1 -1
  80. package/lib/models/status.js +2 -2
  81. package/lib/models/success-types.d.ts +1 -1
  82. package/lib/models/success-types.js +2 -2
  83. package/lib/plugin/command/compile.d.ts +6 -6
  84. package/lib/plugin/command/compile.js +18 -18
  85. package/lib/plugin/command/test.d.ts +6 -6
  86. package/lib/plugin/command/test.js +25 -25
  87. package/lib/plugin/index.d.ts +27 -27
  88. package/lib/plugin/index.js +7 -7
  89. package/lib/plugin/plugin.d.ts +8 -8
  90. package/lib/plugin/plugin.js +68 -68
  91. package/lib/plugin/utils.d.ts +16 -16
  92. package/lib/plugin/utils.js +58 -58
  93. package/lib/ui/download.d.ts +5 -5
  94. package/lib/ui/download.js +61 -61
  95. package/lib/utils/BaseCommand.d.ts +8 -8
  96. package/lib/utils/BaseCommand.js +41 -41
  97. package/lib/utils/SessionCommand.d.ts +10 -10
  98. package/lib/utils/SessionCommand.js +47 -47
  99. package/lib/utils/api.d.ts +12 -12
  100. package/lib/utils/api.js +173 -173
  101. package/lib/utils/audit.d.ts +16 -16
  102. package/lib/utils/audit.js +302 -302
  103. package/lib/utils/console.d.ts +12 -12
  104. package/lib/utils/console.js +19 -19
  105. package/lib/utils/errors.d.ts +17 -17
  106. package/lib/utils/errors.js +100 -100
  107. package/lib/utils/exercisesQueue.d.ts +9 -9
  108. package/lib/utils/exercisesQueue.js +38 -38
  109. package/lib/utils/fileQueue.d.ts +40 -40
  110. package/lib/utils/fileQueue.js +168 -168
  111. package/lib/utils/misc.d.ts +1 -1
  112. package/lib/utils/misc.js +23 -23
  113. package/lib/utils/validators.d.ts +5 -5
  114. package/lib/utils/validators.js +17 -17
  115. package/lib/utils/watcher.d.ts +2 -2
  116. package/lib/utils/watcher.js +23 -23
  117. package/oclif.manifest.json +1 -1
  118. package/package.json +138 -138
  119. package/src/commands/audit.ts +25 -0
  120. package/src/commands/clean.ts +29 -29
  121. package/src/commands/download.ts +62 -62
  122. package/src/commands/login.ts +42 -42
  123. package/src/commands/logout.ts +43 -43
  124. package/src/commands/publish.ts +107 -107
  125. package/src/commands/start.ts +238 -234
  126. package/src/commands/test.ts +85 -85
  127. package/src/index.ts +1 -1
  128. package/src/managers/config/allowed_files.ts +29 -29
  129. package/src/managers/config/defaults.ts +2 -0
  130. package/src/managers/config/exercise.ts +309 -302
  131. package/src/managers/config/index.ts +22 -1
  132. package/src/managers/file.ts +169 -169
  133. package/src/managers/gitpod.ts +84 -84
  134. package/src/managers/server/index.ts +77 -69
  135. package/src/managers/session.ts +118 -118
  136. package/src/managers/socket.ts +239 -239
  137. package/src/managers/test.ts +83 -83
  138. package/src/models/action.ts +3 -3
  139. package/src/models/config-manager.ts +23 -23
  140. package/src/models/config.ts +2 -0
  141. package/src/models/counter.ts +11 -11
  142. package/src/models/errors.ts +22 -22
  143. package/src/models/file.ts +5 -5
  144. package/src/models/findings.ts +18 -18
  145. package/src/models/flags.ts +10 -10
  146. package/src/models/front-matter.ts +11 -11
  147. package/src/models/gitpod-data.ts +19 -19
  148. package/src/models/language.ts +4 -4
  149. package/src/models/package.ts +7 -7
  150. package/src/models/plugin-config.ts +17 -17
  151. package/src/models/session.ts +26 -26
  152. package/src/models/socket.ts +48 -48
  153. package/src/models/status.ts +15 -15
  154. package/src/models/success-types.ts +1 -1
  155. package/src/plugin/command/compile.ts +17 -17
  156. package/src/plugin/command/test.ts +30 -30
  157. package/src/plugin/index.ts +6 -6
  158. package/src/plugin/plugin.ts +94 -94
  159. package/src/plugin/utils.ts +87 -87
  160. package/src/types/node-fetch.d.ts +1 -1
  161. package/src/ui/download.ts +71 -71
  162. package/src/utils/BaseCommand.ts +48 -48
  163. package/src/utils/SessionCommand.ts +48 -48
  164. package/src/utils/api.ts +194 -194
  165. package/src/utils/audit.ts +395 -395
  166. package/src/utils/console.ts +24 -24
  167. package/src/utils/errors.ts +117 -117
  168. package/src/utils/exercisesQueue.ts +51 -51
  169. package/src/utils/fileQueue.ts +198 -198
  170. package/src/utils/misc.ts +23 -23
  171. package/src/utils/templates/gitignore.txt +19 -19
  172. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.es.md +24 -24
  173. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.md +24 -24
  174. package/src/utils/templates/incremental/README.ejs +4 -4
  175. package/src/utils/templates/incremental/README.es.ejs +4 -4
  176. package/src/utils/templates/isolated/01-hello-world/README.es.md +26 -26
  177. package/src/utils/templates/isolated/01-hello-world/README.md +26 -26
  178. package/src/utils/templates/isolated/README.ejs +4 -4
  179. package/src/utils/templates/isolated/README.es.ejs +4 -4
  180. package/src/utils/templates/no-grading/README.ejs +4 -4
  181. package/src/utils/templates/no-grading/README.es.ejs +4 -4
  182. package/src/utils/validators.ts +18 -18
@@ -1,302 +1,302 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const console_1 = require("./console");
4
- const fs = require("fs");
5
- const path = require("path");
6
- // eslint-disable-next-line
7
- const fetch = require("node-fetch");
8
- // eslint-disable-next-line
9
- const fm = require("front-matter");
10
- // This function checks if a url is valid.
11
- const isUrl = async (url, errors, counter) => {
12
- const regexUrl = /(https?:\/\/[\w./-]+)/gm;
13
- counter.links.total++;
14
- if (!regexUrl.test(url)) {
15
- counter.links.error++;
16
- errors.push({
17
- exercise: undefined,
18
- msg: `The repository value of the configuration file is not a link: ${url}`,
19
- });
20
- return false;
21
- }
22
- const res = await fetch(url, { method: "HEAD" });
23
- if (!res.ok) {
24
- counter.links.error++;
25
- errors.push({
26
- exercise: undefined,
27
- msg: `The link of the repository is broken: ${url}`,
28
- });
29
- }
30
- return true;
31
- };
32
- const checkForEmptySpaces = (str) => {
33
- const isEmpty = true;
34
- for (const letter of str) {
35
- if (letter !== " ") {
36
- return false;
37
- }
38
- }
39
- return isEmpty;
40
- };
41
- const checkLearnpackClean = (configObj, errors) => {
42
- var _a, _b, _c, _d, _e, _f, _g, _h;
43
- if ((((_a = configObj.config) === null || _a === void 0 ? void 0 : _a.outputPath) &&
44
- fs.existsSync((_b = configObj.config) === null || _b === void 0 ? void 0 : _b.outputPath)) ||
45
- fs.existsSync(`${(_c = configObj.config) === null || _c === void 0 ? void 0 : _c.dirPath}/_app`) ||
46
- fs.existsSync(`${(_d = configObj.config) === null || _d === void 0 ? void 0 : _d.dirPath}/reports`) ||
47
- fs.existsSync(`${(_e = configObj.config) === null || _e === void 0 ? void 0 : _e.dirPath}/resets`) ||
48
- fs.existsSync(`${(_f = configObj.config) === null || _f === void 0 ? void 0 : _f.dirPath}/app.tar.gz`) ||
49
- fs.existsSync(`${(_g = configObj.config) === null || _g === void 0 ? void 0 : _g.dirPath}/config.json`) ||
50
- fs.existsSync(`${(_h = configObj.config) === null || _h === void 0 ? void 0 : _h.dirPath}/vscode_queue.json`)) {
51
- errors.push({
52
- exercise: undefined,
53
- msg: "You have to run learnpack clean command",
54
- });
55
- }
56
- };
57
- const findInFile = (types, content) => {
58
- const regex = {
59
- relativeImages: /!\[.*]\s*\((((\.\/)?(\.{2}\/){1,5})(.*\/)*(.[^\s/]*\.[A-Za-z]{2,4})\S*)\)/gm,
60
- externalImages: /!\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
61
- markdownLinks: /(\s)+\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
62
- url: /(https?:\/\/[\w./-]+)/gm,
63
- uploadcare: /https:\/\/ucarecdn.com\/(?:.*\/)*([\w./-]+)/gm,
64
- };
65
- const validTypes = Object.keys(regex);
66
- if (!Array.isArray(types))
67
- types = [types];
68
- const findings = {};
69
- for (const type of types) {
70
- if (!validTypes.includes(type))
71
- throw new Error("Invalid type: " + type);
72
- else
73
- findings[type] = {};
74
- }
75
- for (const type of types) {
76
- let m;
77
- while ((m = regex[type].exec(content)) !== null) {
78
- // This is necessary to avoid infinite loops with zero-width matches
79
- if (m.index === regex.lastIndex) {
80
- regex.lastIndex++;
81
- }
82
- // The result can be accessed through the `m`-variable.
83
- // m.forEach((match, groupIndex) => values.push(match));
84
- findings[type][m[0]] = {
85
- content: m[0],
86
- absUrl: m[1],
87
- mdUrl: m[2],
88
- relUrl: m[6],
89
- };
90
- }
91
- }
92
- return findings;
93
- };
94
- // This function checks that each of the url's are working.
95
- const checkUrl = async (config, filePath, fileName, exercise, errors, warnings, counter) => {
96
- var _a, _b, _c, _d;
97
- if (!fs.existsSync(filePath))
98
- return false;
99
- const content = fs.readFileSync(filePath).toString();
100
- const isEmpty = checkForEmptySpaces(content);
101
- if (isEmpty || !content)
102
- errors.push({
103
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
104
- msg: `This file (${fileName}) doesn't have any content inside.`,
105
- });
106
- const frontmatter = fm(content);
107
- for (const attribute in frontmatter.attributes) {
108
- if (Object.prototype.hasOwnProperty.call(frontmatter.attributes, attribute) &&
109
- (attribute === "intro" || attribute === "tutorial")) {
110
- counter && counter.links.total++;
111
- try {
112
- // eslint-disable-next-line
113
- let res = await fetch(frontmatter.attributes[attribute], {
114
- method: "HEAD",
115
- });
116
- if (!res.ok) {
117
- counter && counter.links.error++;
118
- errors.push({
119
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
120
- msg: `This link is broken (${res.ok}): ${frontmatter.attributes[attribute]}`,
121
- });
122
- }
123
- }
124
- catch (_e) {
125
- counter && counter.links.error++;
126
- errors.push({
127
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
128
- msg: `This link is broken: ${frontmatter.attributes[attribute]}`,
129
- });
130
- }
131
- }
132
- }
133
- // Check url's of each README file.
134
- const findings = findInFile(["relativeImages", "externalImages", "markdownLinks"], content);
135
- for (const finding in findings) {
136
- if (Object.prototype.hasOwnProperty.call(findings, finding)) {
137
- const obj = findings[finding];
138
- // Valdites all the relative path images.
139
- if (finding === "relativeImages" && Object.keys(obj).length > 0) {
140
- for (const img in obj) {
141
- if (Object.prototype.hasOwnProperty.call(obj, img)) {
142
- // Validates if the image is in the assets folder.
143
- counter && counter.images.total++;
144
- const relativePath = path
145
- .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_a = config.config) === null || _a === void 0 ? void 0 : _a.dirPath}/assets/${obj[img].relUrl}`)
146
- .replace(/\\/gm, "/");
147
- if (relativePath !== obj[img].absUrl.split("?").shift()) {
148
- counter && counter.images.error++;
149
- errors.push({
150
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
151
- msg: `This relative path (${obj[img].relUrl}) is not pointing to the assets folder.`,
152
- });
153
- }
154
- if (!fs.existsSync(`${(_b = config.config) === null || _b === void 0 ? void 0 : _b.dirPath}/assets/${obj[img].relUrl}`)) {
155
- counter && counter.images.error++;
156
- errors.push({
157
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
158
- msg: `The file ${obj[img].relUrl} doesn't exist in the assets folder.`,
159
- });
160
- }
161
- }
162
- }
163
- }
164
- else if (finding === "externalImages" && Object.keys(obj).length > 0) {
165
- // Valdites all the aboslute path images.
166
- for (const img in obj) {
167
- if (Object.prototype.hasOwnProperty.call(obj, img)) {
168
- counter && counter.images.total++;
169
- if (fs.existsSync(`${(_c = config.config) === null || _c === void 0 ? void 0 : _c.dirPath}/assets${obj[img].mdUrl
170
- .split("?")
171
- .shift()}`)) {
172
- const relativePath = path
173
- .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_d = config.config) === null || _d === void 0 ? void 0 : _d.dirPath}/assets/${obj[img].mdUrl}`)
174
- .replace(/\\/gm, "/");
175
- warnings.push({
176
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
177
- msg: `On this exercise you have an image with an absolute path "${obj[img].absUrl}". We recommend you to replace it by the relative path: "${relativePath}".`,
178
- });
179
- }
180
- try {
181
- // eslint-disable-next-line
182
- let res = await fetch(obj[img].absUrl, {
183
- method: "HEAD",
184
- });
185
- if (!res.ok) {
186
- counter && counter.images.error++;
187
- errors.push({
188
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
189
- msg: `This link is broken: ${obj[img].absUrl}`,
190
- });
191
- }
192
- }
193
- catch (_f) {
194
- counter && counter.images.error++;
195
- errors.push({
196
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
197
- msg: `This link is broken: ${obj[img].absUrl}`,
198
- });
199
- }
200
- }
201
- }
202
- }
203
- else if (finding === "markdownLinks" && Object.keys(obj).length > 0) {
204
- for (const link in obj) {
205
- if (Object.prototype.hasOwnProperty.call(obj, link)) {
206
- counter && counter.links.total++;
207
- if (!obj[link].mdUrl.includes("twitter")) {
208
- try {
209
- // eslint-disable-next-line
210
- let res = await fetch(obj[link].mdUrl, {
211
- method: "HEAD",
212
- });
213
- if (res.status > 399 && res.status < 500) {
214
- counter && counter.links.error++;
215
- errors.push({
216
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
217
- msg: `This link is broken: ${obj[link].mdUrl}`,
218
- });
219
- }
220
- }
221
- catch (_g) {
222
- counter && counter.links.error++;
223
- errors.push({
224
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
225
- msg: `This link is broken: ${obj[link].mdUrl}`,
226
- });
227
- }
228
- }
229
- }
230
- }
231
- }
232
- }
233
- }
234
- return true;
235
- };
236
- // This function writes a given file with the given content.
237
- const writeFile = async (content, filePath) => {
238
- try {
239
- await fs.promises.writeFile(filePath, content);
240
- }
241
- catch (error) {
242
- if (error)
243
- console_1.default.error(`We weren't able to write the file in this path "${filePath}".`, error);
244
- }
245
- };
246
- // This function checks if there are errors, and show them in the console at the end.
247
- const showErrors = (errors, counter) => {
248
- return new Promise((resolve, reject) => {
249
- if (errors) {
250
- if (errors.length > 0) {
251
- console_1.default.log("Checking for errors...");
252
- for (const [i, error] of errors.entries())
253
- console_1.default.error(`${i + 1}) ${error.msg} ${error.exercise ? `(Exercise: ${error.exercise})` : ""}`);
254
- if (counter) {
255
- console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
256
- }
257
- else {
258
- console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} related with the project integrity.`);
259
- }
260
- process.exit(1);
261
- }
262
- else {
263
- if (counter) {
264
- console_1.default.success(`We didn't find any errors in this repository among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
265
- }
266
- else {
267
- console_1.default.success(`We didn't find any errors in this repository.`);
268
- }
269
- process.exit(0);
270
- }
271
- }
272
- else {
273
- reject("Failed");
274
- }
275
- });
276
- };
277
- // This function checks if there are warnings, and show them in the console at the end.
278
- const showWarnings = (warnings) => {
279
- return new Promise((resolve, reject) => {
280
- if (warnings) {
281
- if (warnings.length > 0) {
282
- console_1.default.log("Checking for warnings...");
283
- for (const [i, warning] of warnings.entries())
284
- console_1.default.warning(`${i + 1}) ${warning.msg} ${warning.exercise ? `File: ${warning.exercise}` : ""}`);
285
- }
286
- resolve("SUCCESS");
287
- }
288
- else {
289
- reject("Failed");
290
- }
291
- });
292
- };
293
- exports.default = {
294
- isUrl,
295
- checkForEmptySpaces,
296
- checkLearnpackClean,
297
- findInFile,
298
- checkUrl,
299
- writeFile,
300
- showErrors,
301
- showWarnings,
302
- };
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const console_1 = require("./console");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ // eslint-disable-next-line
7
+ const fetch = require("node-fetch");
8
+ // eslint-disable-next-line
9
+ const fm = require("front-matter");
10
+ // This function checks if a url is valid.
11
+ const isUrl = async (url, errors, counter) => {
12
+ const regexUrl = /(https?:\/\/[\w./-]+)/gm;
13
+ counter.links.total++;
14
+ if (!regexUrl.test(url)) {
15
+ counter.links.error++;
16
+ errors.push({
17
+ exercise: undefined,
18
+ msg: `The repository value of the configuration file is not a link: ${url}`,
19
+ });
20
+ return false;
21
+ }
22
+ const res = await fetch(url, { method: "HEAD" });
23
+ if (!res.ok) {
24
+ counter.links.error++;
25
+ errors.push({
26
+ exercise: undefined,
27
+ msg: `The link of the repository is broken: ${url}`,
28
+ });
29
+ }
30
+ return true;
31
+ };
32
+ const checkForEmptySpaces = (str) => {
33
+ const isEmpty = true;
34
+ for (const letter of str) {
35
+ if (letter !== " ") {
36
+ return false;
37
+ }
38
+ }
39
+ return isEmpty;
40
+ };
41
+ const checkLearnpackClean = (configObj, errors) => {
42
+ var _a, _b, _c, _d, _e, _f, _g, _h;
43
+ if ((((_a = configObj.config) === null || _a === void 0 ? void 0 : _a.outputPath) &&
44
+ fs.existsSync((_b = configObj.config) === null || _b === void 0 ? void 0 : _b.outputPath)) ||
45
+ fs.existsSync(`${(_c = configObj.config) === null || _c === void 0 ? void 0 : _c.dirPath}/_app`) ||
46
+ fs.existsSync(`${(_d = configObj.config) === null || _d === void 0 ? void 0 : _d.dirPath}/reports`) ||
47
+ fs.existsSync(`${(_e = configObj.config) === null || _e === void 0 ? void 0 : _e.dirPath}/resets`) ||
48
+ fs.existsSync(`${(_f = configObj.config) === null || _f === void 0 ? void 0 : _f.dirPath}/app.tar.gz`) ||
49
+ fs.existsSync(`${(_g = configObj.config) === null || _g === void 0 ? void 0 : _g.dirPath}/config.json`) ||
50
+ fs.existsSync(`${(_h = configObj.config) === null || _h === void 0 ? void 0 : _h.dirPath}/vscode_queue.json`)) {
51
+ errors.push({
52
+ exercise: undefined,
53
+ msg: "You have to run learnpack clean command",
54
+ });
55
+ }
56
+ };
57
+ const findInFile = (types, content) => {
58
+ const regex = {
59
+ relativeImages: /!\[.*]\s*\((((\.\/)?(\.{2}\/){1,5})(.*\/)*(.[^\s/]*\.[A-Za-z]{2,4})\S*)\)/gm,
60
+ externalImages: /!\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
61
+ markdownLinks: /(\s)+\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
62
+ url: /(https?:\/\/[\w./-]+)/gm,
63
+ uploadcare: /https:\/\/ucarecdn.com\/(?:.*\/)*([\w./-]+)/gm,
64
+ };
65
+ const validTypes = Object.keys(regex);
66
+ if (!Array.isArray(types))
67
+ types = [types];
68
+ const findings = {};
69
+ for (const type of types) {
70
+ if (!validTypes.includes(type))
71
+ throw new Error("Invalid type: " + type);
72
+ else
73
+ findings[type] = {};
74
+ }
75
+ for (const type of types) {
76
+ let m;
77
+ while ((m = regex[type].exec(content)) !== null) {
78
+ // This is necessary to avoid infinite loops with zero-width matches
79
+ if (m.index === regex.lastIndex) {
80
+ regex.lastIndex++;
81
+ }
82
+ // The result can be accessed through the `m`-variable.
83
+ // m.forEach((match, groupIndex) => values.push(match));
84
+ findings[type][m[0]] = {
85
+ content: m[0],
86
+ absUrl: m[1],
87
+ mdUrl: m[2],
88
+ relUrl: m[6],
89
+ };
90
+ }
91
+ }
92
+ return findings;
93
+ };
94
+ // This function checks that each of the url's are working.
95
+ const checkUrl = async (config, filePath, fileName, exercise, errors, warnings, counter) => {
96
+ var _a, _b, _c, _d;
97
+ if (!fs.existsSync(filePath))
98
+ return false;
99
+ const content = fs.readFileSync(filePath).toString();
100
+ const isEmpty = checkForEmptySpaces(content);
101
+ if (isEmpty || !content)
102
+ errors.push({
103
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
104
+ msg: `This file (${fileName}) doesn't have any content inside.`,
105
+ });
106
+ const frontmatter = fm(content);
107
+ for (const attribute in frontmatter.attributes) {
108
+ if (Object.prototype.hasOwnProperty.call(frontmatter.attributes, attribute) &&
109
+ (attribute === "intro" || attribute === "tutorial")) {
110
+ counter && counter.links.total++;
111
+ try {
112
+ // eslint-disable-next-line
113
+ let res = await fetch(frontmatter.attributes[attribute], {
114
+ method: "HEAD",
115
+ });
116
+ if (!res.ok) {
117
+ counter && counter.links.error++;
118
+ errors.push({
119
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
120
+ msg: `This link is broken (${res.ok}): ${frontmatter.attributes[attribute]}`,
121
+ });
122
+ }
123
+ }
124
+ catch (_e) {
125
+ counter && counter.links.error++;
126
+ errors.push({
127
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
128
+ msg: `This link is broken: ${frontmatter.attributes[attribute]}`,
129
+ });
130
+ }
131
+ }
132
+ }
133
+ // Check url's of each README file.
134
+ const findings = findInFile(["relativeImages", "externalImages", "markdownLinks"], content);
135
+ for (const finding in findings) {
136
+ if (Object.prototype.hasOwnProperty.call(findings, finding)) {
137
+ const obj = findings[finding];
138
+ // Valdites all the relative path images.
139
+ if (finding === "relativeImages" && Object.keys(obj).length > 0) {
140
+ for (const img in obj) {
141
+ if (Object.prototype.hasOwnProperty.call(obj, img)) {
142
+ // Validates if the image is in the assets folder.
143
+ counter && counter.images.total++;
144
+ const relativePath = path
145
+ .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_a = config.config) === null || _a === void 0 ? void 0 : _a.dirPath}/assets/${obj[img].relUrl}`)
146
+ .replace(/\\/gm, "/");
147
+ if (relativePath !== obj[img].absUrl.split("?").shift()) {
148
+ counter && counter.images.error++;
149
+ errors.push({
150
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
151
+ msg: `This relative path (${obj[img].relUrl}) is not pointing to the assets folder.`,
152
+ });
153
+ }
154
+ if (!fs.existsSync(`${(_b = config.config) === null || _b === void 0 ? void 0 : _b.dirPath}/assets/${obj[img].relUrl}`)) {
155
+ counter && counter.images.error++;
156
+ errors.push({
157
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
158
+ msg: `The file ${obj[img].relUrl} doesn't exist in the assets folder.`,
159
+ });
160
+ }
161
+ }
162
+ }
163
+ }
164
+ else if (finding === "externalImages" && Object.keys(obj).length > 0) {
165
+ // Valdites all the aboslute path images.
166
+ for (const img in obj) {
167
+ if (Object.prototype.hasOwnProperty.call(obj, img)) {
168
+ counter && counter.images.total++;
169
+ if (fs.existsSync(`${(_c = config.config) === null || _c === void 0 ? void 0 : _c.dirPath}/assets${obj[img].mdUrl
170
+ .split("?")
171
+ .shift()}`)) {
172
+ const relativePath = path
173
+ .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_d = config.config) === null || _d === void 0 ? void 0 : _d.dirPath}/assets/${obj[img].mdUrl}`)
174
+ .replace(/\\/gm, "/");
175
+ warnings.push({
176
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
177
+ msg: `On this exercise you have an image with an absolute path "${obj[img].absUrl}". We recommend you to replace it by the relative path: "${relativePath}".`,
178
+ });
179
+ }
180
+ try {
181
+ // eslint-disable-next-line
182
+ let res = await fetch(obj[img].absUrl, {
183
+ method: "HEAD",
184
+ });
185
+ if (!res.ok) {
186
+ counter && counter.images.error++;
187
+ errors.push({
188
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
189
+ msg: `This link is broken: ${obj[img].absUrl}`,
190
+ });
191
+ }
192
+ }
193
+ catch (_f) {
194
+ counter && counter.images.error++;
195
+ errors.push({
196
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
197
+ msg: `This link is broken: ${obj[img].absUrl}`,
198
+ });
199
+ }
200
+ }
201
+ }
202
+ }
203
+ else if (finding === "markdownLinks" && Object.keys(obj).length > 0) {
204
+ for (const link in obj) {
205
+ if (Object.prototype.hasOwnProperty.call(obj, link)) {
206
+ counter && counter.links.total++;
207
+ if (!obj[link].mdUrl.includes("twitter")) {
208
+ try {
209
+ // eslint-disable-next-line
210
+ let res = await fetch(obj[link].mdUrl, {
211
+ method: "HEAD",
212
+ });
213
+ if (res.status > 399 && res.status < 500) {
214
+ counter && counter.links.error++;
215
+ errors.push({
216
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
217
+ msg: `This link is broken: ${obj[link].mdUrl}`,
218
+ });
219
+ }
220
+ }
221
+ catch (_g) {
222
+ counter && counter.links.error++;
223
+ errors.push({
224
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
225
+ msg: `This link is broken: ${obj[link].mdUrl}`,
226
+ });
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+ return true;
235
+ };
236
+ // This function writes a given file with the given content.
237
+ const writeFile = async (content, filePath) => {
238
+ try {
239
+ await fs.promises.writeFile(filePath, content);
240
+ }
241
+ catch (error) {
242
+ if (error)
243
+ console_1.default.error(`We weren't able to write the file in this path "${filePath}".`, error);
244
+ }
245
+ };
246
+ // This function checks if there are errors, and show them in the console at the end.
247
+ const showErrors = (errors, counter) => {
248
+ return new Promise((resolve, reject) => {
249
+ if (errors) {
250
+ if (errors.length > 0) {
251
+ console_1.default.log("Checking for errors...");
252
+ for (const [i, error] of errors.entries())
253
+ console_1.default.error(`${i + 1}) ${error.msg} ${error.exercise ? `(Exercise: ${error.exercise})` : ""}`);
254
+ if (counter) {
255
+ console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
256
+ }
257
+ else {
258
+ console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} related with the project integrity.`);
259
+ }
260
+ process.exit(1);
261
+ }
262
+ else {
263
+ if (counter) {
264
+ console_1.default.success(`We didn't find any errors in this repository among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
265
+ }
266
+ else {
267
+ console_1.default.success(`We didn't find any errors in this repository.`);
268
+ }
269
+ process.exit(0);
270
+ }
271
+ }
272
+ else {
273
+ reject("Failed");
274
+ }
275
+ });
276
+ };
277
+ // This function checks if there are warnings, and show them in the console at the end.
278
+ const showWarnings = (warnings) => {
279
+ return new Promise((resolve, reject) => {
280
+ if (warnings) {
281
+ if (warnings.length > 0) {
282
+ console_1.default.log("Checking for warnings...");
283
+ for (const [i, warning] of warnings.entries())
284
+ console_1.default.warning(`${i + 1}) ${warning.msg} ${warning.exercise ? `File: ${warning.exercise}` : ""}`);
285
+ }
286
+ resolve("SUCCESS");
287
+ }
288
+ else {
289
+ reject("Failed");
290
+ }
291
+ });
292
+ };
293
+ exports.default = {
294
+ isUrl,
295
+ checkForEmptySpaces,
296
+ checkLearnpackClean,
297
+ findInFile,
298
+ checkUrl,
299
+ writeFile,
300
+ showErrors,
301
+ showWarnings,
302
+ };
@@ -1,12 +1,12 @@
1
- declare const _default: {
2
- _debug: boolean;
3
- startDebug: () => void;
4
- log: (msg: string | Array<string>, ...args: Array<any>) => void;
5
- error: (msg: string, ...args: Array<any>) => void;
6
- success: (msg: string, ...args: Array<any>) => void;
7
- info: (msg: string, ...args: Array<any>) => void;
8
- help: (msg: string) => void;
9
- debug(...args: Array<any>): void;
10
- warning: (msg: string) => void;
11
- };
12
- export default _default;
1
+ declare const _default: {
2
+ _debug: boolean;
3
+ startDebug: () => void;
4
+ log: (msg: string | Array<string>, ...args: Array<any>) => void;
5
+ error: (msg: string, ...args: Array<any>) => void;
6
+ success: (msg: string, ...args: Array<any>) => void;
7
+ info: (msg: string, ...args: Array<any>) => void;
8
+ help: (msg: string) => void;
9
+ debug(...args: Array<any>): void;
10
+ warning: (msg: string) => void;
11
+ };
12
+ export default _default;