@learnpack/learnpack 2.1.0 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,172 +1,172 @@
1
- import { flags } from "@oclif/command";
2
- import BaseCommand from "../utils/BaseCommand";
3
-
4
- // eslint-disable-next-line
5
- import * as fs from "fs-extra";
6
- import * as prompts from "prompts";
7
- import cli from "cli-ux";
8
- import * as eta from "eta";
9
-
10
- import Console from "../utils/console";
11
- import { ValidationError } from "../utils/errors";
12
- import defaults from "../managers/config/defaults";
13
-
14
- import * as path from "path";
15
-
16
- class InitComand extends BaseCommand {
17
- static description =
18
- "Create a new learning package: Book, Tutorial or Exercise";
19
-
20
- static flags = {
21
- ...BaseCommand.flags,
22
- grading: flags.help({ char: "h" }),
23
- };
24
-
25
- async run() {
26
- const { flags } = this.parse(InitComand);
27
-
28
- // if the folder/file .learn or .breathecode aleady exists
29
- await alreadyInitialized();
30
-
31
- const choices = await prompts([
32
- {
33
- type: "select",
34
- name: "grading",
35
- message: "Is the auto-grading going to be isolated or incremental?",
36
- choices: [
37
- {
38
- title: "Incremental: Build on top of each other like a tutorial",
39
- value: "incremental",
40
- },
41
- { title: "Isolated: Small separated exercises", value: "isolated" },
42
- {
43
- title: "No grading: No feedback or testing whatsoever",
44
- value: null,
45
- },
46
- ],
47
- },
48
- {
49
- type: "text",
50
- name: "title",
51
- initial: "My Interactive Tutorial",
52
- message: "Title for your tutorial? Press enter to leave as it is",
53
- },
54
- {
55
- type: "text",
56
- name: "description",
57
- initial: "",
58
- message: "Description for your tutorial? Press enter to leave blank",
59
- },
60
- {
61
- type: "select",
62
- name: "difficulty",
63
- message: "How difficulty will be to complete the tutorial?",
64
- choices: [
65
- { title: "Begginer (no previous experience)", value: "beginner" },
66
- { title: "Easy (just a bit of experience required)", value: "easy" },
67
- {
68
- title: "Intermediate (you need experience)",
69
- value: "intermediate",
70
- },
71
- { title: "Hard (master the topic)", value: "hard" },
72
- ],
73
- },
74
- {
75
- type: "text",
76
- name: "duration",
77
- initial: "1",
78
- message: "How many hours avg it takes to complete (number)?",
79
- validate: (value: string) => {
80
- const n = Math.floor(Number(value));
81
- return (
82
- n !== Number.POSITIVE_INFINITY && String(n) === value && n >= 0
83
- );
84
- },
85
- },
86
- ]);
87
-
88
- const packageInfo = {
89
- ...defaults.config,
90
- grading: choices.grading,
91
- difficulty: choices.difficulty,
92
- duration: parseInt(choices.duration),
93
- description: choices.description,
94
- title: choices.title,
95
- slug: choices.title
96
- .toLowerCase()
97
- .replace(/ /g, "-")
98
- .replace(/[^\w-]+/g, ""),
99
- };
100
-
101
- cli.action.start("Initializing package");
102
-
103
- const languages = ["en", "es"];
104
-
105
- const templatesDir = path.resolve(
106
- __dirname,
107
- "../../src/utils/templates/" + choices.grading || "no-grading"
108
- );
109
- if (!fs.existsSync(templatesDir))
110
- throw ValidationError(`Template ${templatesDir} does not exists`);
111
- await fs.copySync(templatesDir, "./");
112
-
113
- // Creating README files
114
- // eslint-disable-next-line
115
- languages.forEach((language) => {
116
- const readmeFilename = `README${language !== "en" ? `.${language}` : ""}`;
117
- fs.writeFileSync(
118
- `./${readmeFilename}.md`,
119
- eta.render(
120
- fs.readFileSync(
121
- path.resolve(__dirname, `${templatesDir}/${readmeFilename}.ejs`),
122
- "utf-8"
123
- ),
124
- packageInfo
125
- )
126
- );
127
- if (fs.existsSync(`./${readmeFilename}.ejs`))
128
- fs.removeSync(`./${readmeFilename}.ejs`);
129
- });
130
-
131
- if (!fs.existsSync("./.gitignore"))
132
- fs.copyFile(
133
- path.resolve(__dirname, "../../src/utils/templates/gitignore.txt"),
134
- "./.gitignore"
135
- );
136
- fs.writeFileSync("./learn.json", JSON.stringify(packageInfo, null, 2));
137
-
138
- cli.action.stop();
139
- Console.success(`😋 Package initialized successfully`);
140
- Console.help(
141
- `Start the exercises by running the following command on your terminal: $ learnpack start`
142
- );
143
- }
144
- }
145
-
146
- const alreadyInitialized = () =>
147
- new Promise((resolve, reject) => {
148
- fs.readdir("./", function (err: any, files: any) {
149
- files = files.filter((f: any) =>
150
- [".learn", "learn.json", "bc.json", ".breathecode"].includes(f)
151
- );
152
- if (err) {
153
- reject(ValidationError(err.message));
154
- throw ValidationError(err.message);
155
- } else if (files.length > 0) {
156
- reject(
157
- ValidationError(
158
- "It seems the package is already initialized because we've found the following files: " +
159
- files.join(",")
160
- )
161
- );
162
- throw ValidationError(
163
- "It seems the package is already initialized because we've found the following files: " +
164
- files.join(",")
165
- );
166
- }
167
-
168
- resolve(false);
169
- });
170
- });
171
-
172
- export default InitComand;
1
+ import { flags } from "@oclif/command";
2
+ import BaseCommand from "../utils/BaseCommand";
3
+
4
+ // eslint-disable-next-line
5
+ import * as fs from "fs-extra";
6
+ import * as prompts from "prompts";
7
+ import cli from "cli-ux";
8
+ import * as eta from "eta";
9
+
10
+ import Console from "../utils/console";
11
+ import { ValidationError } from "../utils/errors";
12
+ import defaults from "../managers/config/defaults";
13
+
14
+ import * as path from "path";
15
+
16
+ class InitComand extends BaseCommand {
17
+ static description =
18
+ "Create a new learning package: Book, Tutorial or Exercise";
19
+
20
+ static flags = {
21
+ ...BaseCommand.flags,
22
+ grading: flags.help({ char: "h" }),
23
+ };
24
+
25
+ async run() {
26
+ const { flags } = this.parse(InitComand);
27
+
28
+ // if the folder/file .learn or .breathecode aleady exists
29
+ await alreadyInitialized();
30
+
31
+ const choices = await prompts([
32
+ {
33
+ type: "select",
34
+ name: "grading",
35
+ message: "Is the auto-grading going to be isolated or incremental?",
36
+ choices: [
37
+ {
38
+ title: "Incremental: Build on top of each other like a tutorial",
39
+ value: "incremental",
40
+ },
41
+ { title: "Isolated: Small separated exercises", value: "isolated" },
42
+ {
43
+ title: "No grading: No feedback or testing whatsoever",
44
+ value: null,
45
+ },
46
+ ],
47
+ },
48
+ {
49
+ type: "text",
50
+ name: "title",
51
+ initial: "My Interactive Tutorial",
52
+ message: "Title for your tutorial? Press enter to leave as it is",
53
+ },
54
+ {
55
+ type: "text",
56
+ name: "description",
57
+ initial: "",
58
+ message: "Description for your tutorial? Press enter to leave blank",
59
+ },
60
+ {
61
+ type: "select",
62
+ name: "difficulty",
63
+ message: "How difficulty will be to complete the tutorial?",
64
+ choices: [
65
+ { title: "Begginer (no previous experience)", value: "beginner" },
66
+ { title: "Easy (just a bit of experience required)", value: "easy" },
67
+ {
68
+ title: "Intermediate (you need experience)",
69
+ value: "intermediate",
70
+ },
71
+ { title: "Hard (master the topic)", value: "hard" },
72
+ ],
73
+ },
74
+ {
75
+ type: "text",
76
+ name: "duration",
77
+ initial: "1",
78
+ message: "How many hours avg it takes to complete (number)?",
79
+ validate: (value: string) => {
80
+ const n = Math.floor(Number(value));
81
+ return (
82
+ n !== Number.POSITIVE_INFINITY && String(n) === value && n >= 0
83
+ );
84
+ },
85
+ },
86
+ ]);
87
+
88
+ const packageInfo = {
89
+ ...defaults.config,
90
+ grading: choices.grading,
91
+ difficulty: choices.difficulty,
92
+ duration: parseInt(choices.duration),
93
+ description: choices.description,
94
+ title: choices.title,
95
+ slug: choices.title
96
+ .toLowerCase()
97
+ .replace(/ /g, "-")
98
+ .replace(/[^\w-]+/g, ""),
99
+ };
100
+
101
+ cli.action.start("Initializing package");
102
+
103
+ const languages = ["en", "es"];
104
+
105
+ const templatesDir = path.resolve(
106
+ __dirname,
107
+ "../../src/utils/templates/" + choices.grading || "no-grading"
108
+ );
109
+ if (!fs.existsSync(templatesDir))
110
+ throw ValidationError(`Template ${templatesDir} does not exists`);
111
+ await fs.copySync(templatesDir, "./");
112
+
113
+ // Creating README files
114
+ // eslint-disable-next-line
115
+ languages.forEach((language) => {
116
+ const readmeFilename = `README${language !== "en" ? `.${language}` : ""}`;
117
+ fs.writeFileSync(
118
+ `./${readmeFilename}.md`,
119
+ eta.render(
120
+ fs.readFileSync(
121
+ path.resolve(__dirname, `${templatesDir}/${readmeFilename}.ejs`),
122
+ "utf-8"
123
+ ),
124
+ packageInfo
125
+ )
126
+ );
127
+ if (fs.existsSync(`./${readmeFilename}.ejs`))
128
+ fs.removeSync(`./${readmeFilename}.ejs`);
129
+ });
130
+
131
+ if (!fs.existsSync("./.gitignore"))
132
+ fs.copyFile(
133
+ path.resolve(__dirname, "../../src/utils/templates/gitignore.txt"),
134
+ "./.gitignore"
135
+ );
136
+ fs.writeFileSync("./learn.json", JSON.stringify(packageInfo, null, 2));
137
+
138
+ cli.action.stop();
139
+ Console.success(`😋 Package initialized successfully`);
140
+ Console.help(
141
+ `Start the exercises by running the following command on your terminal: $ learnpack start`
142
+ );
143
+ }
144
+ }
145
+
146
+ const alreadyInitialized = () =>
147
+ new Promise((resolve, reject) => {
148
+ fs.readdir("./", function (err: any, files: any) {
149
+ files = files.filter((f: any) =>
150
+ [".learn", "learn.json", "bc.json", ".breathecode"].includes(f)
151
+ );
152
+ if (err) {
153
+ reject(ValidationError(err.message));
154
+ throw ValidationError(err.message);
155
+ } else if (files.length > 0) {
156
+ reject(
157
+ ValidationError(
158
+ "It seems the package is already initialized because we've found the following files: " +
159
+ files.join(",")
160
+ )
161
+ );
162
+ throw ValidationError(
163
+ "It seems the package is already initialized because we've found the following files: " +
164
+ files.join(",")
165
+ );
166
+ }
167
+
168
+ resolve(false);
169
+ });
170
+ });
171
+
172
+ export default InitComand;
@@ -1,33 +1,34 @@
1
- export default {
2
- config: {
3
- port: 3000,
4
- editor: {
5
- mode: null, // [standalone, preview]
6
- agent: null, // [vscode, theia]
7
- version: null,
8
- },
9
- dirPath: './.learn',
10
- configPath: './learn.json',
11
- outputPath: './.learn/dist',
12
- publicPath: '/preview',
13
- publicUrl: null,
14
- language: 'auto',
15
- grading: 'isolated', // [isolated, incremental]
16
- exercisesPath: './', // path to the folder that contains the exercises
17
- webpackTemplate: null, // if you want webpack to use an HTML template
18
- disableGrading: false,
19
- disabledActions: [], // Possible: 'build', 'test' or 'reset'
20
- actions: [], // ⚠️ deprecated, leave empty )
21
- entries: {
22
- html: 'index.html',
23
- vanillajs: 'index.js',
24
- react: 'app.jsx',
25
- node: 'app.js',
26
- python3: 'app.py',
27
- java: 'app.java',
28
- },
29
- },
30
- address: 'http://localhost',
31
- currentExercise: null,
32
- exercises: [],
33
- }
1
+ export default {
2
+ config: {
3
+ port: 3000,
4
+ editor: {
5
+ mode: null, // [standalone, preview]
6
+ agent: null, // [vscode, gitpod, localhost]
7
+ version: null,
8
+ },
9
+ dirPath: "./.learn",
10
+ configPath: "./learn.json",
11
+ outputPath: "./.learn/dist",
12
+ publicPath: "/preview",
13
+ publicUrl: null,
14
+ language: "auto",
15
+ autoPlay: true,
16
+ grading: "isolated", // [isolated, incremental]
17
+ exercisesPath: "./", // path to the folder that contains the exercises
18
+ webpackTemplate: null, // if you want webpack to use an HTML template
19
+ disableGrading: false,
20
+ disabledActions: [], // Possible: 'build', 'test' or 'reset'
21
+ actions: [], // ⚠️ deprecated, leave empty )
22
+ entries: {
23
+ html: "index.html",
24
+ vanillajs: "index.js",
25
+ react: "app.jsx",
26
+ node: "app.js",
27
+ python3: "app.py",
28
+ java: "app.java",
29
+ },
30
+ },
31
+ address: "http://localhost",
32
+ currentExercise: null,
33
+ exercises: [],
34
+ };
@@ -30,12 +30,7 @@ const chalk = require("chalk");
30
30
  /* exercise folder name standard */
31
31
 
32
32
  const getConfigPath = () => {
33
- const possibleFileNames = [
34
- "learn.json",
35
- ".learn/learn.json",
36
- "bc.json",
37
- ".breathecode/bc.json",
38
- ];
33
+ const possibleFileNames = ["learn.json", ".learn/learn.json"];
39
34
  const config = possibleFileNames.find(file => fs.existsSync(file)) || null;
40
35
  if (config && fs.existsSync(".breathecode"))
41
36
  return { config, base: ".breathecode" };
@@ -75,7 +70,6 @@ export default async ({
75
70
 
76
71
  if (confPath) {
77
72
  const bcContent = fs.readFileSync(confPath.config);
78
-
79
73
  let hiddenBcContent = {};
80
74
  if (fs.existsSync(confPath.base + "/config.json")) {
81
75
  hiddenBcContent = fs.readFileSync(confPath.base + "/config.json");
@@ -131,7 +125,6 @@ export default async ({
131
125
 
132
126
  // auto detect agent (if possible)
133
127
  if (shell.which("gp") && configObj && configObj.config) {
134
- configObj.config.editor.agent = "gitpod";
135
128
  configObj.address = getGitpodAddress();
136
129
  configObj.config.publicUrl = `https://${
137
130
  configObj.config.port
@@ -144,8 +137,8 @@ export default async ({
144
137
  configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`;
145
138
 
146
139
  // Assign default editor mode if not set already
147
- if (configObj.config && mode !== null) {
148
- configObj.config.editor.mode = (mode as TMode) || ("vscode" as TMode);
140
+ if (configObj.config && !mode) {
141
+ configObj.config.editor.mode = mode as TMode;
149
142
  }
150
143
 
151
144
  if (configObj.config && !configObj.config.editor.mode)
@@ -160,7 +153,7 @@ configObj.config.editor.version = version;
160
153
  "https://raw.githubusercontent.com/learnpack/coding-ide/learnpack/package.json"
161
154
  );
162
155
  const packageJSON = await resp.json();
163
- configObj.config.editor.version = packageJSON.version || "1.0.72";
156
+ configObj.config.editor.version = packageJSON.version || "1.0.73";
164
157
  }
165
158
 
166
159
  if (configObj.config) {
@@ -54,6 +54,7 @@ export interface IConfig {
54
54
  exercisesPath: string;
55
55
  disableGrading: boolean; // TODO: Deprecate
56
56
  actions: Array<string>; // TODO: Deprecate
57
+ autoPlay: boolean;
57
58
  // TODO: nameExerciseValidation
58
59
  disabledActions?: Array<TConfigAction>;
59
60
  compiler: TCompiler;