@learnpack/learnpack 4.0.6 → 4.0.7

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @learnpack/learnpack
21
21
  $ learnpack COMMAND
22
22
  running command...
23
23
  $ learnpack (-v|--version|version)
24
- @learnpack/learnpack/4.0.6 win32-x64 node-v20.10.0
24
+ @learnpack/learnpack/4.0.7 win32-x64 node-v20.16.0
25
25
  $ learnpack --help [COMMAND]
26
26
  USAGE
27
27
  $ learnpack COMMAND
@@ -74,7 +74,7 @@ DESCRIPTION
74
74
  12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
75
75
  ```
76
76
 
77
- _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\audit.ts)_
77
+ _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\audit.ts)_
78
78
 
79
79
  ## `learnpack clean`
80
80
 
@@ -89,7 +89,7 @@ DESCRIPTION
89
89
  Extra documentation goes here
90
90
  ```
91
91
 
92
- _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\clean.ts)_
92
+ _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\clean.ts)_
93
93
 
94
94
  ## `learnpack download [PACKAGE]`
95
95
 
@@ -107,7 +107,7 @@ DESCRIPTION
107
107
  Extra documentation goes here
108
108
  ```
109
109
 
110
- _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\download.ts)_
110
+ _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\download.ts)_
111
111
 
112
112
  ## `learnpack help [COMMAND]`
113
113
 
@@ -138,7 +138,7 @@ OPTIONS
138
138
  -h, --grading show CLI help
139
139
  ```
140
140
 
141
- _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\init.ts)_
141
+ _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\init.ts)_
142
142
 
143
143
  ## `learnpack login [PACKAGE]`
144
144
 
@@ -156,7 +156,7 @@ DESCRIPTION
156
156
  Extra documentation goes here
157
157
  ```
158
158
 
159
- _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\login.ts)_
159
+ _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\login.ts)_
160
160
 
161
161
  ## `learnpack logout [PACKAGE]`
162
162
 
@@ -174,7 +174,7 @@ DESCRIPTION
174
174
  Extra documentation goes here
175
175
  ```
176
176
 
177
- _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\logout.ts)_
177
+ _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\logout.ts)_
178
178
 
179
179
  ## `learnpack plugins`
180
180
 
@@ -309,7 +309,7 @@ DESCRIPTION
309
309
  Extra documentation goes here
310
310
  ```
311
311
 
312
- _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\publish.ts)_
312
+ _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\publish.ts)_
313
313
 
314
314
  ## `learnpack start`
315
315
 
@@ -330,7 +330,7 @@ OPTIONS
330
330
  -w, --watch Watch for file changes
331
331
  ```
332
332
 
333
- _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\start.ts)_
333
+ _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\start.ts)_
334
334
 
335
335
  ## `learnpack test [EXERCISESLUG]`
336
336
 
@@ -344,7 +344,7 @@ ARGUMENTS
344
344
  EXERCISESLUG The name of the exercise to test
345
345
  ```
346
346
 
347
- _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.6/src\commands\test.ts)_
347
+ _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\test.ts)_
348
348
  <!-- commandsstop -->
349
349
 
350
350
  > > > > > > > 0cb3e56d84c197f9d008836bb573eade212b7e57
@@ -22,10 +22,9 @@ class StartCommand extends SessionCommand_1.default {
22
22
  await this.initSession(flags);
23
23
  }
24
24
  async run() {
25
- var _a, _b, _c, _d, _e, _f;
25
+ var _a, _b, _c, _d, _e, _f, _g, _h;
26
26
  // get configuration object
27
27
  const configObject = (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.get();
28
- // TODO: console.log(this.config.platform); get the platfrom from Oclif
29
28
  const hasXDG = await osOperations_1.eventManager.checkXDGInstalled();
30
29
  const installedPlugins = this.config.plugins.map(plugin => {
31
30
  return `${plugin.pjson.name}`;
@@ -51,7 +50,7 @@ class StartCommand extends SessionCommand_1.default {
51
50
  // listen to socket commands
52
51
  if (config && this.configManager) {
53
52
  const server = await server_1.default(configObject, this.configManager, process.env.NODE_ENV === "test");
54
- server.setMaxListeners(25);
53
+ server.setMaxListeners(30);
55
54
  // I should call a method to get the EventListener
56
55
  const dispatcher = fileQueue_1.default.dispatcher({
57
56
  create: true,
@@ -78,6 +77,18 @@ class StartCommand extends SessionCommand_1.default {
78
77
  }
79
78
  }
80
79
  socket_1.default.start(config, server, false);
80
+ if ((_g = config === null || config === void 0 ? void 0 : config.warnings) === null || _g === void 0 ? void 0 : _g.agent) {
81
+ const message = config.warnings.agent;
82
+ setTimeout(() => {
83
+ socket_1.default.dialog(message);
84
+ }, 2000);
85
+ }
86
+ if ((_h = config === null || config === void 0 ? void 0 : config.warnings) === null || _h === void 0 ? void 0 : _h.extension) {
87
+ const message = config.warnings.extension;
88
+ setTimeout(() => {
89
+ socket_1.default.dialog(message);
90
+ }, 3000);
91
+ }
81
92
  socket_1.default.on("open", (data) => {
82
93
  console_1.default.debug("Opening these files: ", data);
83
94
  const files = misc_1.prioritizeHTMLFile(data.files);
@@ -37,6 +37,12 @@ declare const _default: {
37
37
  exercises: never[];
38
38
  bugsLink: null;
39
39
  videoSolutions: boolean;
40
+ suggestions: {
41
+ agent: null;
42
+ };
43
+ warnings: {
44
+ agent: null;
45
+ };
40
46
  localhostOnly: boolean;
41
47
  };
42
48
  export default _default;
@@ -41,5 +41,11 @@ exports.default = {
41
41
  exercises: [],
42
42
  bugsLink: null,
43
43
  videoSolutions: false,
44
+ suggestions: {
45
+ agent: null,
46
+ },
47
+ warnings: {
48
+ agent: null,
49
+ },
44
50
  localhostOnly: false,
45
51
  };
@@ -5,7 +5,6 @@ const fs = require("fs");
5
5
  const shell = require("shelljs");
6
6
  const child_process_1 = require("child_process");
7
7
  const util_1 = require("util");
8
- const execAsync = util_1.promisify(child_process_1.exec);
9
8
  const console_1 = require("../../utils/console");
10
9
  const watcher_1 = require("../../utils/watcher");
11
10
  const errors_1 = require("../../utils/errors");
@@ -13,6 +12,7 @@ const defaults_1 = require("./defaults");
13
12
  const exercise_1 = require("./exercise");
14
13
  const file_1 = require("../file");
15
14
  /* exercise folder name standard */
15
+ const execAsync = util_1.promisify(child_process_1.exec);
16
16
  // eslint-disable-next-line
17
17
  const fetch = require("node-fetch");
18
18
  // eslint-disable-next-line
@@ -60,7 +60,7 @@ const getCodespacesNamespace = () => {
60
60
  return codespace_name;
61
61
  };
62
62
  exports.default = async ({ grading, mode, disableGrading, version, }) => {
63
- var _a, _b, _c, _d;
63
+ var _a, _b, _c, _d, _e, _f;
64
64
  const confPath = getConfigPath();
65
65
  console_1.default.debug("This is the config path: ", confPath);
66
66
  let configObj = {};
@@ -108,11 +108,22 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
108
108
  // auto detect agent (if possible)
109
109
  const codespaces_workspace = getCodespacesNamespace();
110
110
  console_1.default.debug("This is the codespace namespace: ", codespaces_workspace);
111
+ if (!configObj.config.editor) {
112
+ configObj.config.editor = {};
113
+ }
111
114
  console_1.default.debug("This is the agent, and this should be null an the beginning: ", (_c = (_b = configObj.config) === null || _b === void 0 ? void 0 : _b.editor) === null || _c === void 0 ? void 0 : _c.agent);
115
+ if ((_e = (_d = configObj.config) === null || _d === void 0 ? void 0 : _d.editor) === null || _e === void 0 ? void 0 : _e.agent) {
116
+ if (configObj.config.suggestions) {
117
+ configObj.config.suggestions.agent = configObj.config.editor.agent;
118
+ }
119
+ else {
120
+ configObj.config.suggestions = { agent: configObj.config.editor.agent };
121
+ }
122
+ }
112
123
  if (shell.which("gp") && configObj && configObj.config) {
113
124
  console_1.default.debug("Gitpod detected");
114
125
  configObj.address = getGitpodAddress();
115
- configObj.config.publicUrl = `https://${configObj.config.port}-${(_d = configObj.address) === null || _d === void 0 ? void 0 : _d.slice(8)}`;
126
+ configObj.config.publicUrl = `https://${configObj.config.port}-${(_f = configObj.address) === null || _f === void 0 ? void 0 : _f.slice(8)}`;
116
127
  configObj.config.editor.agent = "vscode";
117
128
  }
118
129
  else if (configObj.config && Boolean(codespaces_workspace)) {
@@ -125,11 +136,32 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
125
136
  console_1.default.debug("Neither Gitpod nor Codespaces detected, using localhost.");
126
137
  configObj.address = `http://localhost:${configObj.config.port}`;
127
138
  configObj.config.publicUrl = `http://localhost:${configObj.config.port}`;
128
- }
129
- if (!configObj.config.editor.agent) {
130
139
  configObj.config.editor.agent =
131
140
  process.env.TERM_PROGRAM === "vscode" ? "vscode" : "os";
132
141
  }
142
+ if (configObj.config.editor.agent === "vscode" && isCodeCommandAvailable()) {
143
+ const extensionName = "learn-pack.learnpack-vscode";
144
+ if (!isExtensionInstalled(extensionName)) {
145
+ console_1.default.info("The LearnPack extension is not installed, trying to install it automatically.");
146
+ if (!installExtension(extensionName)) {
147
+ configObj.config.warnings = {
148
+ extension: EXTENSION_INSTALLATION_STEPS,
149
+ };
150
+ console_1.default.warning("The LearnPack extension is not installed and this tutorial is meant to be run inside VSCode. Please install the LearnPack extension.");
151
+ }
152
+ }
153
+ }
154
+ if (configObj.config.suggestions &&
155
+ configObj.config.editor &&
156
+ configObj.config.suggestions.agent !== configObj.config.editor.agent) {
157
+ console_1.default.warning(`The suggested agent "${configObj.config.suggestions.agent}" is different from the detected agent "${configObj.config.editor.agent}"`);
158
+ try {
159
+ configObj.config.warnings = Object.assign(Object.assign({}, configObj.config.warnings), { agent: buildAgentWarning(configObj.config.editor.agent, configObj.config.suggestions.agent) });
160
+ }
161
+ catch (_g) {
162
+ console_1.default.error("IMPOSSIBLE TO SET WARNING");
163
+ }
164
+ }
133
165
  if (configObj.config && !configObj.config.publicUrl)
134
166
  configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`;
135
167
  if (configObj.config && !configObj.config.editor.mode && mode) {
@@ -145,7 +177,7 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
145
177
  console_1.default.debug("Config version not found, downloading default.");
146
178
  const resp = await fetch("https://raw.githubusercontent.com/learnpack/ide/master/package.json");
147
179
  const packageJSON = await resp.json();
148
- configObj.config.editor.version = packageJSON.version || "4.0.0";
180
+ configObj.config.editor.version = packageJSON.version || "4.0.2";
149
181
  }
150
182
  configObj.config.dirPath = "./" + confPath.base;
151
183
  configObj.config.exercisesPath = getExercisesPath(confPath.base) || "./";
@@ -188,7 +220,9 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
188
220
  }
189
221
  return {
190
222
  validLanguages: {},
191
- get: () => configObj,
223
+ get: () => {
224
+ return configObj;
225
+ },
192
226
  validateEngine: function (language, server, socket) {
193
227
  // eslint-disable-next-line
194
228
  const alias = (_l) => {
@@ -374,3 +408,130 @@ function deepMerge(...sources) {
374
408
  }
375
409
  return acc;
376
410
  }
411
+ const buildAgentWarning = (current, suggested) => {
412
+ const message = `# Agent mismatch!\n
413
+
414
+ In LearnPack, the agent is in charge of running the LearnPack interface.
415
+
416
+ You're currently using LearnPack through \`${current}\` but the suggested agent is \`${suggested}\`.
417
+
418
+ We recommend strongly recommend changing your agent.
419
+
420
+ ${stepsToChangeAgent(suggested)}
421
+ `;
422
+ return message;
423
+ };
424
+ const stepsToChangeAgent = (agent) => {
425
+ if (agent === "vscode") {
426
+ return `
427
+ # Steps to Change Agent to VSCode
428
+
429
+ 1. **Install VSCode**:
430
+ - Visit the [VSCode website](https://code.visualstudio.com/Download) and download the latest version.
431
+ - Follow the installation instructions for your operating system.
432
+
433
+ 2. **Install LearnPack VSCode Extension**:
434
+ - Open VSCode.
435
+ - Go to the Extensions view by clicking on the Extensions icon in the Activity Bar on the side of the window or by pressing \`Ctrl+Shift+X\`.
436
+ - Search for "LearnPack" and click "Install".
437
+ - If the extension is already installed but disabled, enable it.
438
+
439
+ 3. **Run LearnPack in VSCode**:
440
+ - Open your terminal in VSCode.
441
+ - Navigate to your LearnPack project directory.
442
+ - Run the following command:
443
+ \`\`\`sh
444
+ learnpack start
445
+ \`\`\`
446
+
447
+ We strongly recommend using VSCode for a better learning experience.
448
+ `;
449
+ }
450
+ if (agent === "os") {
451
+ return `
452
+ # Steps to Change Agent to OS
453
+
454
+ This learning package was designed to run outside of VSCode. We strongly recommend closing VSCode and running the package independently.
455
+
456
+ 1. **Close VSCode**:
457
+ - Save your work and close the VSCode application.
458
+
459
+ 2. **Open a New Terminal**:
460
+ - Open a terminal or command prompt on your operating system.
461
+
462
+ 3. **Navigate to Your LearnPack Project Directory**:
463
+ - Use the \`cd\` command to navigate to the directory where your LearnPack project is located.
464
+
465
+ 4. **Run LearnPack**:
466
+ - Run the following command to start LearnPack:
467
+ \`\`\`sh
468
+ learnpack start
469
+ \`\`\`
470
+
471
+ We strongly recommend running the package independently for a better learning experience.
472
+ `;
473
+ }
474
+ return "";
475
+ };
476
+ /**
477
+ * Checks if the 'code' command is available in the terminal.
478
+ *
479
+ * @returns {boolean} True if the 'code' command is available, false otherwise.
480
+ */
481
+ const isCodeCommandAvailable = () => {
482
+ return shell.which("code") !== null;
483
+ };
484
+ /**
485
+ * Checks if a specific VSCode extension is installed.
486
+ *
487
+ * @param {string} extensionName - The name of the extension to check.
488
+ * @returns {boolean} True if the extension is installed, false otherwise.
489
+ */
490
+ const isExtensionInstalled = (extensionName) => {
491
+ if (!isCodeCommandAvailable()) {
492
+ throw new Error("The 'code' command is not available in the terminal. Please ensure that VSCode is installed and the 'code' command is added to your PATH.");
493
+ }
494
+ const result = shell.exec("code --list-extensions", { silent: true });
495
+ return result.stdout.split("\n").includes(extensionName);
496
+ };
497
+ const EXTENSION_INSTALLATION_STEPS = `
498
+ # Steps to Install LearnPack VSCode Extension
499
+
500
+ 1. **Open VSCode**:
501
+ - Launch the Visual Studio Code application on your computer.
502
+
503
+ 2. **Go to Extensions View**:
504
+ - Click on the Extensions icon in the Activity Bar on the side of the window.
505
+ - Alternatively, you can open the Extensions view by pressing \`Ctrl+Shift+X\`.
506
+
507
+ 3. **Search for LearnPack**:
508
+ - In the Extensions view, type "LearnPack" into the search bar.
509
+
510
+ 4. **Install the Extension**:
511
+ - Find the "LearnPack" extension in the search results and click the "Install" button.
512
+ - If the extension is already installed but disabled, click the "Enable" button.
513
+
514
+ 5. **Verify Installation**:
515
+ - Once installed, you can verify the installation by running the following command in the terminal:
516
+ \`\`\`sh
517
+ code --list-extensions | grep learn-pack.learnpack-vscode
518
+ \`\`\`
519
+ - If the extension is listed, it means the installation was successful.
520
+
521
+ We strongly recommend using the LearnPack extension in VSCode for a better learning experience.
522
+ `;
523
+ /**
524
+ * Installs the LearnPack VSCode extension if the 'code' command is available.
525
+ *
526
+ * @param {string} extensionName - The name of the extension to install.
527
+ * @returns {boolean} True if the installation was successful, false otherwise.
528
+ */
529
+ const installExtension = (extensionName) => {
530
+ if (!isCodeCommandAvailable()) {
531
+ throw new Error("The 'code' command is not available in the terminal. Please ensure that VSCode is installed and the 'code' command is added to your PATH.");
532
+ }
533
+ const result = shell.exec(`code --install-extension ${extensionName}`, {
534
+ silent: true,
535
+ });
536
+ return result.code === 0;
537
+ };
@@ -102,7 +102,7 @@ const SocketManager = {
102
102
  });
103
103
  },
104
104
  reload: function (files = null, exercises = null) {
105
- this.emit("reload", (files === null || files === void 0 ? void 0 : files.join("")) || "" /* TODO: Check it out this */, exercises);
105
+ this.emit("reload", (files === null || files === void 0 ? void 0 : files.join("")) || "", exercises);
106
106
  },
107
107
  openWindow: function (url = "") {
108
108
  fileQueue_1.default.dispatcher().enqueue(fileQueue_1.default.events.OPEN_WINDOW, url);
@@ -8,10 +8,9 @@ export declare type TCompiler = "webpack" | "vanillajs" | "react" | "html" | "no
8
8
  export interface IConfigPath {
9
9
  base: string;
10
10
  }
11
- declare type TAgent = "vscode" | "os";
12
11
  export interface IEditor {
13
12
  mode?: TMode;
14
- version: string;
13
+ version?: string;
15
14
  agent?: TAgent;
16
15
  hideTerminal?: boolean;
17
16
  }
@@ -56,9 +55,19 @@ export interface IConfig {
56
55
  skills: Array<string>;
57
56
  telemetry?: TTelemetryUrls;
58
57
  variables?: TVariables;
58
+ suggestions: TSuggestions;
59
+ warnings: TWarnings;
59
60
  runHook: (...agrs: Array<any>) => void;
60
61
  testingFinishedCallback: (arg: any | undefined) => void;
61
62
  }
63
+ export declare type TAgent = "os" | "vscode" | null;
64
+ declare type TSuggestions = {
65
+ agent: TAgent;
66
+ };
67
+ declare type TWarnings = {
68
+ agent?: string;
69
+ extension?: string;
70
+ };
62
71
  declare type TVariable = {
63
72
  type: "command" | "string";
64
73
  source: string;
@@ -1 +1 @@
1
- {"version":"4.0.6","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]}}}
1
+ {"version":"4.0.7","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]}}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@learnpack/learnpack",
3
3
  "description": "Create, sell or download and take learning amazing learning packages",
4
- "version": "4.0.6",
4
+ "version": "4.0.7",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -77,7 +77,6 @@ export default class StartCommand extends SessionCommand {
77
77
  // get configuration object
78
78
  const configObject = this.configManager?.get()
79
79
 
80
- // TODO: console.log(this.config.platform); get the platfrom from Oclif
81
80
  const hasXDG = await eventManager.checkXDGInstalled()
82
81
 
83
82
  const installedPlugins = this.config.plugins.map(plugin => {
@@ -86,6 +85,7 @@ export default class StartCommand extends SessionCommand {
86
85
 
87
86
  if (configObject) {
88
87
  const { config } = configObject
88
+
89
89
  // build exerises
90
90
  this.configManager?.buildIndex()
91
91
 
@@ -112,9 +112,7 @@ export default class StartCommand extends SessionCommand {
112
112
  this.exit(1)
113
113
  }
114
114
 
115
- const appAlreadyExists = checkIfDirectoryExists(
116
- `${config?.dirPath}/_app`
117
- )
115
+ const appAlreadyExists = checkIfDirectoryExists(`${config?.dirPath}/_app`)
118
116
 
119
117
  if (!appAlreadyExists) {
120
118
  // download app and decompress
@@ -137,7 +135,7 @@ export default class StartCommand extends SessionCommand {
137
135
  this.configManager,
138
136
  process.env.NODE_ENV === "test"
139
137
  )
140
- server.setMaxListeners(25)
138
+ server.setMaxListeners(30)
141
139
 
142
140
  // I should call a method to get the EventListener
143
141
  const dispatcher = queue.dispatcher({
@@ -172,6 +170,20 @@ export default class StartCommand extends SessionCommand {
172
170
 
173
171
  socket.start(config, server, false)
174
172
 
173
+ if (config?.warnings?.agent) {
174
+ const message = config.warnings.agent
175
+ setTimeout(() => {
176
+ socket.dialog(message)
177
+ }, 2000)
178
+ }
179
+
180
+ if (config?.warnings?.extension) {
181
+ const message = config.warnings.extension
182
+ setTimeout(() => {
183
+ socket.dialog(message)
184
+ }, 3000)
185
+ }
186
+
175
187
  socket.on("open", (data: IGitpodData) => {
176
188
  Console.debug("Opening these files: ", data)
177
189
 
@@ -1,43 +1,49 @@
1
- import * as os from "os"
2
- export default {
3
- config: {
4
- port: 3000,
5
- os: (function () {
6
- return os.platform()
7
- })(),
8
- editor: {
9
- mode: null, // [extension, preview]
10
- agent: null, // ["vscode", "os"] ("os" is the agent when running outside a coding editor
11
- version: null, // By default downloads the latest version
12
- },
13
- dirPath: "./.learn",
14
- configPath: "./learn.json",
15
- outputPath: "./.learn/dist",
16
- publicPath: "/preview",
17
- publicUrl: null,
18
- contact: "https://github.com/learnpack/learnpack/issues/new",
19
- language: "auto",
20
- autoPlay: true,
21
- projectType: "tutorial", // [tutorial, project]
22
- grading: "isolated", // [isolated, incremental]
23
- exercisesPath: "./", // path to the folder that contains the exercises
24
- webpackTemplate: null, // if you want webpack to use an HTML template
25
- disableGrading: false,
26
- disabledActions: [], // Possible: 'build', 'test' or 'reset'
27
- actions: [], // ⚠️ deprecated, leave empty )
28
- entries: {
29
- html: "index.html",
30
- vanillajs: "index.js",
31
- react: "app.jsx",
32
- node: "app.js",
33
- python3: "app.py",
34
- java: "app.java",
35
- },
36
- },
37
- address: "http://localhost",
38
- currentExercise: null,
39
- exercises: [],
40
- bugsLink: null,
41
- videoSolutions: false,
42
- localhostOnly: false, // if true, the exercise should not run on gitpod or codespaces but show an error message encouraging the user to run locally
43
- }
1
+ import * as os from "os"
2
+ export default {
3
+ config: {
4
+ port: 3000,
5
+ os: (function () {
6
+ return os.platform()
7
+ })(),
8
+ editor: {
9
+ mode: null, // [extension, preview]
10
+ agent: null, // ["vscode", "os"] ("os" is the agent when running outside a coding editor
11
+ version: null, // By default downloads the latest version
12
+ },
13
+ dirPath: "./.learn",
14
+ configPath: "./learn.json",
15
+ outputPath: "./.learn/dist",
16
+ publicPath: "/preview",
17
+ publicUrl: null,
18
+ contact: "https://github.com/learnpack/learnpack/issues/new",
19
+ language: "auto",
20
+ autoPlay: true,
21
+ projectType: "tutorial", // [tutorial, project]
22
+ grading: "isolated", // [isolated, incremental]
23
+ exercisesPath: "./", // path to the folder that contains the exercises
24
+ webpackTemplate: null, // if you want webpack to use an HTML template
25
+ disableGrading: false,
26
+ disabledActions: [], // Possible: 'build', 'test' or 'reset'
27
+ actions: [], // ⚠️ deprecated, leave empty )
28
+ entries: {
29
+ html: "index.html",
30
+ vanillajs: "index.js",
31
+ react: "app.jsx",
32
+ node: "app.js",
33
+ python3: "app.py",
34
+ java: "app.java",
35
+ },
36
+ },
37
+ address: "http://localhost",
38
+ currentExercise: null,
39
+ exercises: [],
40
+ bugsLink: null,
41
+ videoSolutions: false,
42
+ suggestions: {
43
+ agent: null,
44
+ },
45
+ warnings: {
46
+ agent: null,
47
+ },
48
+ localhostOnly: false, // if true, the exercise should not run on gitpod or codespaces but show an error message encouraging the user to run locally
49
+ }
@@ -4,8 +4,6 @@ import * as shell from "shelljs"
4
4
  import { exec } from "child_process"
5
5
  import { promisify } from "util"
6
6
 
7
- const execAsync = promisify(exec)
8
-
9
7
  import Console from "../../utils/console"
10
8
  import watch from "../../utils/watcher"
11
9
  import {
@@ -18,7 +16,12 @@ import defaults from "./defaults"
18
16
  import { exercise } from "./exercise"
19
17
 
20
18
  import { rmSync } from "../file"
21
- import { IConfigObj, TConfigObjAttributes, TMode } from "../../models/config"
19
+ import {
20
+ IConfigObj,
21
+ TConfigObjAttributes,
22
+ TMode,
23
+ TAgent,
24
+ } from "../../models/config"
22
25
  import {
23
26
  IConfigManagerAttributes,
24
27
  IConfigManager,
@@ -26,6 +29,7 @@ import {
26
29
  import { IFile } from "../../models/file"
27
30
 
28
31
  /* exercise folder name standard */
32
+ const execAsync = promisify(exec)
29
33
 
30
34
  // eslint-disable-next-line
31
35
  const fetch = require("node-fetch")
@@ -158,11 +162,23 @@ throw InternalError("Config object not found")
158
162
  const codespaces_workspace = getCodespacesNamespace()
159
163
  Console.debug("This is the codespace namespace: ", codespaces_workspace)
160
164
 
165
+ if (!configObj.config.editor) {
166
+ configObj.config.editor = {}
167
+ }
168
+
161
169
  Console.debug(
162
170
  "This is the agent, and this should be null an the beginning: ",
163
171
  configObj.config?.editor?.agent
164
172
  )
165
173
 
174
+ if (configObj.config?.editor?.agent) {
175
+ if (configObj.config.suggestions) {
176
+ configObj.config.suggestions.agent = configObj.config.editor.agent
177
+ } else {
178
+ configObj.config.suggestions = { agent: configObj.config.editor.agent }
179
+ }
180
+ }
181
+
166
182
  if (shell.which("gp") && configObj && configObj.config) {
167
183
  Console.debug("Gitpod detected")
168
184
  configObj.address = getGitpodAddress()
@@ -179,13 +195,51 @@ throw InternalError("Config object not found")
179
195
  Console.debug("Neither Gitpod nor Codespaces detected, using localhost.")
180
196
  configObj.address = `http://localhost:${configObj.config.port}`
181
197
  configObj.config.publicUrl = `http://localhost:${configObj.config.port}`
182
- }
183
-
184
- if (!configObj.config.editor.agent) {
185
198
  configObj.config.editor.agent =
186
199
  process.env.TERM_PROGRAM === "vscode" ? "vscode" : "os"
187
200
  }
188
201
 
202
+ if (configObj.config.editor.agent === "vscode" && isCodeCommandAvailable()) {
203
+ const extensionName = "learn-pack.learnpack-vscode"
204
+
205
+ if (!isExtensionInstalled(extensionName)) {
206
+ Console.info(
207
+ "The LearnPack extension is not installed, trying to install it automatically."
208
+ )
209
+
210
+ if (!installExtension(extensionName)) {
211
+ configObj.config.warnings = {
212
+ extension: EXTENSION_INSTALLATION_STEPS,
213
+ }
214
+ Console.warning(
215
+ "The LearnPack extension is not installed and this tutorial is meant to be run inside VSCode. Please install the LearnPack extension."
216
+ )
217
+ }
218
+ }
219
+ }
220
+
221
+ if (
222
+ configObj.config.suggestions &&
223
+ configObj.config.editor &&
224
+ configObj.config.suggestions.agent !== configObj.config.editor.agent
225
+ ) {
226
+ Console.warning(
227
+ `The suggested agent "${configObj.config.suggestions.agent}" is different from the detected agent "${configObj.config.editor.agent}"`
228
+ )
229
+
230
+ try {
231
+ configObj.config.warnings = {
232
+ ...configObj.config.warnings, // Ensure we don't overwrite other warnings
233
+ agent: buildAgentWarning(
234
+ configObj.config.editor.agent,
235
+ configObj.config.suggestions.agent
236
+ ),
237
+ }
238
+ } catch {
239
+ Console.error("IMPOSSIBLE TO SET WARNING")
240
+ }
241
+ }
242
+
189
243
  if (configObj.config && !configObj.config.publicUrl)
190
244
  configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`
191
245
 
@@ -206,7 +260,7 @@ configObj.config.editor.version = version
206
260
  "https://raw.githubusercontent.com/learnpack/ide/master/package.json"
207
261
  )
208
262
  const packageJSON = await resp.json()
209
- configObj.config.editor.version = packageJSON.version || "4.0.0"
263
+ configObj.config.editor.version = packageJSON.version || "4.0.2"
210
264
  }
211
265
 
212
266
  configObj.config.dirPath = "./" + confPath.base
@@ -258,7 +312,9 @@ return
258
312
 
259
313
  return {
260
314
  validLanguages: {},
261
- get: () => configObj,
315
+ get: () => {
316
+ return configObj
317
+ },
262
318
  validateEngine: function (language: string, server: any, socket: any) {
263
319
  // eslint-disable-next-line
264
320
  const alias = (_l: string) => {
@@ -500,3 +556,145 @@ acc = { ...acc, [key]: value }
500
556
 
501
557
  return acc
502
558
  }
559
+
560
+ const buildAgentWarning = (current: TAgent, suggested: TAgent): string => {
561
+ const message = `# Agent mismatch!\n
562
+
563
+ In LearnPack, the agent is in charge of running the LearnPack interface.
564
+
565
+ You're currently using LearnPack through \`${current}\` but the suggested agent is \`${suggested}\`.
566
+
567
+ We recommend strongly recommend changing your agent.
568
+
569
+ ${stepsToChangeAgent(suggested)}
570
+ `
571
+
572
+ return message
573
+ }
574
+
575
+ const stepsToChangeAgent = (agent: TAgent): string => {
576
+ if (agent === "vscode") {
577
+ return `
578
+ # Steps to Change Agent to VSCode
579
+
580
+ 1. **Install VSCode**:
581
+ - Visit the [VSCode website](https://code.visualstudio.com/Download) and download the latest version.
582
+ - Follow the installation instructions for your operating system.
583
+
584
+ 2. **Install LearnPack VSCode Extension**:
585
+ - Open VSCode.
586
+ - Go to the Extensions view by clicking on the Extensions icon in the Activity Bar on the side of the window or by pressing \`Ctrl+Shift+X\`.
587
+ - Search for "LearnPack" and click "Install".
588
+ - If the extension is already installed but disabled, enable it.
589
+
590
+ 3. **Run LearnPack in VSCode**:
591
+ - Open your terminal in VSCode.
592
+ - Navigate to your LearnPack project directory.
593
+ - Run the following command:
594
+ \`\`\`sh
595
+ learnpack start
596
+ \`\`\`
597
+
598
+ We strongly recommend using VSCode for a better learning experience.
599
+ `
600
+ }
601
+
602
+ if (agent === "os") {
603
+ return `
604
+ # Steps to Change Agent to OS
605
+
606
+ This learning package was designed to run outside of VSCode. We strongly recommend closing VSCode and running the package independently.
607
+
608
+ 1. **Close VSCode**:
609
+ - Save your work and close the VSCode application.
610
+
611
+ 2. **Open a New Terminal**:
612
+ - Open a terminal or command prompt on your operating system.
613
+
614
+ 3. **Navigate to Your LearnPack Project Directory**:
615
+ - Use the \`cd\` command to navigate to the directory where your LearnPack project is located.
616
+
617
+ 4. **Run LearnPack**:
618
+ - Run the following command to start LearnPack:
619
+ \`\`\`sh
620
+ learnpack start
621
+ \`\`\`
622
+
623
+ We strongly recommend running the package independently for a better learning experience.
624
+ `
625
+ }
626
+
627
+ return ""
628
+ }
629
+
630
+ /**
631
+ * Checks if the 'code' command is available in the terminal.
632
+ *
633
+ * @returns {boolean} True if the 'code' command is available, false otherwise.
634
+ */
635
+ const isCodeCommandAvailable = (): boolean => {
636
+ return shell.which("code") !== null
637
+ }
638
+
639
+ /**
640
+ * Checks if a specific VSCode extension is installed.
641
+ *
642
+ * @param {string} extensionName - The name of the extension to check.
643
+ * @returns {boolean} True if the extension is installed, false otherwise.
644
+ */
645
+ const isExtensionInstalled = (extensionName: string): boolean => {
646
+ if (!isCodeCommandAvailable()) {
647
+ throw new Error(
648
+ "The 'code' command is not available in the terminal. Please ensure that VSCode is installed and the 'code' command is added to your PATH."
649
+ )
650
+ }
651
+
652
+ const result = shell.exec("code --list-extensions", { silent: true })
653
+ return result.stdout.split("\n").includes(extensionName)
654
+ }
655
+
656
+ const EXTENSION_INSTALLATION_STEPS = `
657
+ # Steps to Install LearnPack VSCode Extension
658
+
659
+ 1. **Open VSCode**:
660
+ - Launch the Visual Studio Code application on your computer.
661
+
662
+ 2. **Go to Extensions View**:
663
+ - Click on the Extensions icon in the Activity Bar on the side of the window.
664
+ - Alternatively, you can open the Extensions view by pressing \`Ctrl+Shift+X\`.
665
+
666
+ 3. **Search for LearnPack**:
667
+ - In the Extensions view, type "LearnPack" into the search bar.
668
+
669
+ 4. **Install the Extension**:
670
+ - Find the "LearnPack" extension in the search results and click the "Install" button.
671
+ - If the extension is already installed but disabled, click the "Enable" button.
672
+
673
+ 5. **Verify Installation**:
674
+ - Once installed, you can verify the installation by running the following command in the terminal:
675
+ \`\`\`sh
676
+ code --list-extensions | grep learn-pack.learnpack-vscode
677
+ \`\`\`
678
+ - If the extension is listed, it means the installation was successful.
679
+
680
+ We strongly recommend using the LearnPack extension in VSCode for a better learning experience.
681
+ `
682
+
683
+ /**
684
+ * Installs the LearnPack VSCode extension if the 'code' command is available.
685
+ *
686
+ * @param {string} extensionName - The name of the extension to install.
687
+ * @returns {boolean} True if the installation was successful, false otherwise.
688
+ */
689
+ const installExtension = (extensionName: string): boolean => {
690
+ if (!isCodeCommandAvailable()) {
691
+ throw new Error(
692
+ "The 'code' command is not available in the terminal. Please ensure that VSCode is installed and the 'code' command is added to your PATH."
693
+ )
694
+ }
695
+
696
+ const result = shell.exec(`code --install-extension ${extensionName}`, {
697
+ silent: true,
698
+ })
699
+ return result.code === 0
700
+ }
@@ -144,11 +144,7 @@ actions = [actions]
144
144
  files: Array<string> | null = null,
145
145
  exercises: Array<string> | null = null
146
146
  ) {
147
- this.emit(
148
- "reload",
149
- files?.join("") || "" /* TODO: Check it out this */,
150
- exercises!
151
- )
147
+ this.emit("reload", files?.join("") || "", exercises!)
152
148
  },
153
149
  openWindow: function (url = "") {
154
150
  queue.dispatcher().enqueue(queue.events.OPEN_WINDOW, url)
@@ -195,7 +191,7 @@ actions = [actions]
195
191
  }
196
192
 
197
193
  // eslint-disable-next-line
198
- this.config?.disabledActions?.forEach((a) => this.removeAllowed(a));
194
+ this.config?.disabledActions?.forEach((a) => this.removeAllowed(a))
199
195
 
200
196
  this.socket?.emit("compiler", {
201
197
  action,
@@ -1,18 +1,13 @@
1
1
  import { IExercise } from "./exercise-obj"
2
2
  import { TTelemetryUrls } from "../managers/telemetry"
3
3
 
4
- export type TGrading = "isolated" | "incremental" | "no-grading";
4
+ export type TGrading = "isolated" | "incremental" | "no-grading"
5
5
 
6
- export type TMode = "preview" | "extension";
6
+ export type TMode = "preview" | "extension"
7
7
 
8
- export type TConfigAction =
9
- | "test"
10
- | "build"
11
- | "tutorial"
12
- | "reset"
13
- | "generate";
8
+ export type TConfigAction = "test" | "build" | "tutorial" | "reset" | "generate"
14
9
 
15
- export type TConfigObjAttributes = "config" | "exercises" | "grading";
10
+ export type TConfigObjAttributes = "config" | "exercises" | "grading"
16
11
 
17
12
  export type TCompiler =
18
13
  | "webpack"
@@ -21,82 +16,91 @@ export type TCompiler =
21
16
  | "html"
22
17
  | "node"
23
18
  | "python"
24
- | "css";
19
+ | "css"
25
20
 
26
21
  export interface IConfigPath {
27
- base: string;
22
+ base: string
28
23
  }
29
24
 
30
- type TAgent = "vscode" | "os";
31
-
32
25
  export interface IEditor {
33
- mode?: TMode;
34
- version: string;
35
- agent?: TAgent;
36
- hideTerminal?: boolean;
26
+ mode?: TMode
27
+ version?: string
28
+ agent?: TAgent
29
+ hideTerminal?: boolean
37
30
  }
38
31
 
39
32
  export interface TEntries {
40
- python3?: string;
41
- html?: string;
42
- node?: string;
43
- react?: string;
44
- java?: string;
33
+ python3?: string
34
+ html?: string
35
+ node?: string
36
+ react?: string
37
+ java?: string
45
38
  }
46
39
 
47
40
  export interface IConfig {
48
- os: string;
49
- port?: string;
50
- repository?: string;
51
- description?: string;
52
- slug?: string;
53
- dirPath: string;
54
- preview?: string; // Picture thumbnail
55
- entries: TEntries;
56
- grading: TGrading;
57
- configPath: string;
58
- translations: Array<string>;
59
- outputPath?: string;
60
- editor: IEditor;
61
- language: string;
62
- title: string;
63
- duration: number;
64
- difficulty?: string;
65
- exercisesPath: string;
66
- disableGrading: boolean; // TODO: Deprecate
67
- actions: Array<string>; // TODO: Deprecate
68
- autoPlay: boolean;
69
- projectType?: string;
41
+ os: string
42
+ port?: string
43
+ repository?: string
44
+ description?: string
45
+ slug?: string
46
+ dirPath: string
47
+ preview?: string // Picture thumbnail
48
+ entries: TEntries
49
+ grading: TGrading
50
+ configPath: string
51
+ translations: Array<string>
52
+ outputPath?: string
53
+ editor: IEditor
54
+ language: string
55
+ title: string
56
+ duration: number
57
+ difficulty?: string
58
+ exercisesPath: string
59
+ disableGrading: boolean // TODO: Deprecate
60
+ actions: Array<string> // TODO: Deprecate
61
+ autoPlay: boolean
62
+ projectType?: string
70
63
  // TODO: nameExerciseValidation
71
- contact?: string;
72
- disabledActions?: Array<TConfigAction>;
73
- compiler: TCompiler;
74
- compilers: Array<TCompiler>;
75
- publicPath: string;
76
- publicUrl?: string;
77
- bugsLink?: string;
78
- videoSolutions?: boolean;
79
- skills: Array<string>;
80
- telemetry?: TTelemetryUrls;
81
- variables?: TVariables;
64
+ contact?: string
65
+ disabledActions?: Array<TConfigAction>
66
+ compiler: TCompiler
67
+ compilers: Array<TCompiler>
68
+ publicPath: string
69
+ publicUrl?: string
70
+ bugsLink?: string
71
+ videoSolutions?: boolean
72
+ skills: Array<string>
73
+ telemetry?: TTelemetryUrls
74
+ variables?: TVariables
75
+ suggestions: TSuggestions
76
+ warnings: TWarnings
77
+ runHook: (...agrs: Array<any>) => void
78
+ testingFinishedCallback: (arg: any | undefined) => void
79
+ }
80
+ export type TAgent = "os" | "vscode" | null
81
+
82
+ type TSuggestions = {
83
+ agent: TAgent
84
+ }
82
85
 
83
- runHook: (...agrs: Array<any>) => void;
84
- testingFinishedCallback: (arg: any | undefined) => void;
86
+ type TWarnings = {
87
+ agent?: string
88
+ extension?: string
85
89
  }
86
90
 
87
91
  type TVariable = {
88
- type: "command" | "string";
89
- source: string;
90
- };
92
+ type: "command" | "string"
93
+ source: string
94
+ }
91
95
  type TVariables = {
92
- [key: string]: TVariable | string;
93
- };
96
+ [key: string]: TVariable | string
97
+ }
94
98
 
95
99
  export interface IConfigObj {
96
- session?: number;
97
- currentExercise?: any;
98
- config?: IConfig;
99
- exercises?: Array<IExercise>;
100
- confPath?: IConfigPath;
101
- address?: string; // Maybe
100
+ session?: number
101
+ currentExercise?: any
102
+ config?: IConfig
103
+ exercises?: Array<IExercise>
104
+ confPath?: IConfigPath
105
+ address?: string // Maybe
102
106
  }