@learnpack/learnpack 5.0.196 → 5.0.202
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/lib/commands/serve.d.ts +5 -28
- package/lib/commands/serve.js +45 -20
- package/lib/creatorDist/assets/index-C_HbkVCg.js +38491 -0
- package/lib/creatorDist/index.html +1 -1
- package/lib/models/creator.d.ts +30 -0
- package/lib/models/creator.js +2 -0
- package/lib/utils/creatorUtilities.js +3 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/src/commands/serve.ts +59 -59
- package/src/creator/package-lock.json +97 -1
- package/src/creator/package.json +3 -0
- package/src/creator/src/App.tsx +91 -32
- package/src/creator/src/components/FileCard.tsx +2 -2
- package/src/creator/src/components/FileUploader.tsx +6 -5
- package/src/creator/src/components/LinkUploader.tsx +3 -1
- package/src/creator/src/components/Login.tsx +33 -27
- package/src/creator/src/components/PurposeSelector.tsx +32 -25
- package/src/creator/src/components/StepWizard.tsx +8 -4
- package/src/creator/src/components/Uploader.tsx +8 -5
- package/src/creator/src/components/syllabus/ContentIndex.tsx +17 -11
- package/src/creator/src/components/syllabus/Sidebar.tsx +7 -7
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +79 -76
- package/src/creator/src/i18n.ts +28 -0
- package/src/creator/src/locales/en.json +110 -0
- package/src/creator/src/locales/es.json +110 -0
- package/src/creator/src/main.tsx +1 -0
- package/src/creator/src/utils/creatorUtils.ts +7 -3
- package/src/creator/src/utils/lib.ts +17 -1
- package/src/creator/src/utils/store.ts +37 -10
- package/src/creatorDist/assets/index-C_HbkVCg.js +38491 -0
- package/src/creatorDist/index.html +1 -1
- package/src/models/creator.ts +32 -0
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +55 -55
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/creatorUtilities.ts +4 -4
- package/lib/creatorDist/assets/index-CXaPa6wN.js +0 -35382
- package/src/creatorDist/assets/index-CXaPa6wN.js +0 -35382
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/5.0.
|
24
|
+
@learnpack/learnpack/5.0.202 win32-x64 node-v22.15.0
|
25
25
|
$ learnpack --help [COMMAND]
|
26
26
|
USAGE
|
27
27
|
$ learnpack COMMAND
|
@@ -80,7 +80,7 @@ DESCRIPTION
|
|
80
80
|
12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
|
81
81
|
```
|
82
82
|
|
83
|
-
_See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
83
|
+
_See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\audit.ts)_
|
84
84
|
|
85
85
|
## `learnpack breakToken`
|
86
86
|
|
@@ -95,7 +95,7 @@ OPTIONS
|
|
95
95
|
-y, --yes Skip all prompts and initialize an empty project
|
96
96
|
```
|
97
97
|
|
98
|
-
_See code: [src\commands\breakToken.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
98
|
+
_See code: [src\commands\breakToken.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\breakToken.ts)_
|
99
99
|
|
100
100
|
## `learnpack clean`
|
101
101
|
|
@@ -110,7 +110,7 @@ DESCRIPTION
|
|
110
110
|
Extra documentation goes here
|
111
111
|
```
|
112
112
|
|
113
|
-
_See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
113
|
+
_See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\clean.ts)_
|
114
114
|
|
115
115
|
## `learnpack download [PACKAGE]`
|
116
116
|
|
@@ -128,7 +128,7 @@ DESCRIPTION
|
|
128
128
|
Extra documentation goes here
|
129
129
|
```
|
130
130
|
|
131
|
-
_See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
131
|
+
_See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\download.ts)_
|
132
132
|
|
133
133
|
## `learnpack help [COMMAND]`
|
134
134
|
|
@@ -160,7 +160,7 @@ OPTIONS
|
|
160
160
|
-y, --yes Skip all prompts and initialize an empty project
|
161
161
|
```
|
162
162
|
|
163
|
-
_See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
163
|
+
_See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\init.ts)_
|
164
164
|
|
165
165
|
## `learnpack login [PACKAGE]`
|
166
166
|
|
@@ -178,7 +178,7 @@ DESCRIPTION
|
|
178
178
|
Extra documentation goes here
|
179
179
|
```
|
180
180
|
|
181
|
-
_See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
181
|
+
_See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\login.ts)_
|
182
182
|
|
183
183
|
## `learnpack logout [PACKAGE]`
|
184
184
|
|
@@ -196,7 +196,7 @@ DESCRIPTION
|
|
196
196
|
Extra documentation goes here
|
197
197
|
```
|
198
198
|
|
199
|
-
_See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
199
|
+
_See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\logout.ts)_
|
200
200
|
|
201
201
|
## `learnpack plugins`
|
202
202
|
|
@@ -328,7 +328,7 @@ OPTIONS
|
|
328
328
|
-s, --strict strict mode
|
329
329
|
```
|
330
330
|
|
331
|
-
_See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
331
|
+
_See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\publish.ts)_
|
332
332
|
|
333
333
|
## `learnpack serve`
|
334
334
|
|
@@ -345,7 +345,7 @@ OPTIONS
|
|
345
345
|
-y, --yes Skip all prompts and initialize an empty project
|
346
346
|
```
|
347
347
|
|
348
|
-
_See code: [src\commands\serve.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
348
|
+
_See code: [src\commands\serve.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\serve.ts)_
|
349
349
|
|
350
350
|
## `learnpack start`
|
351
351
|
|
@@ -367,7 +367,7 @@ OPTIONS
|
|
367
367
|
-y, --yes Skip all prompts and initialize an empty project
|
368
368
|
```
|
369
369
|
|
370
|
-
_See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
370
|
+
_See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\start.ts)_
|
371
371
|
|
372
372
|
## `learnpack test [EXERCISESLUG]`
|
373
373
|
|
@@ -384,7 +384,7 @@ OPTIONS
|
|
384
384
|
-y, --yes Skip all prompts and initialize an empty project
|
385
385
|
```
|
386
386
|
|
387
|
-
_See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
387
|
+
_See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\test.ts)_
|
388
388
|
|
389
389
|
## `learnpack translate`
|
390
390
|
|
@@ -398,7 +398,7 @@ OPTIONS
|
|
398
398
|
-y, --yes Skip all prompts and initialize an empty project
|
399
399
|
```
|
400
400
|
|
401
|
-
_See code: [src\commands\translate.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.
|
401
|
+
_See code: [src\commands\translate.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.202/src\commands\translate.ts)_
|
402
402
|
<!-- commandsstop -->
|
403
403
|
|
404
404
|
> > > > > > > 0cb3e56d84c197f9d008836bb573eade212b7e57
|
package/lib/commands/serve.d.ts
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
import SessionCommand from "../utils/SessionCommand";
|
2
2
|
import { Bucket } from "@google-cloud/storage";
|
3
|
+
import { FormState, Lesson } from "../models/creator";
|
3
4
|
export declare const createLearnJson: (courseInfo: FormState) => {
|
4
5
|
slug: string;
|
5
6
|
title: {
|
6
7
|
us: string;
|
8
|
+
} | {
|
9
|
+
[x: string]: string;
|
10
|
+
us?: undefined;
|
7
11
|
};
|
8
12
|
technologies: string[];
|
9
13
|
difficulty: string;
|
@@ -17,37 +21,10 @@ export declare const createLearnJson: (courseInfo: FormState) => {
|
|
17
21
|
preview: string;
|
18
22
|
};
|
19
23
|
export declare const processImage: (bucket: Bucket, tutorialDir: string, url: string, description: string, rigoToken: string) => Promise<boolean>;
|
20
|
-
export declare function processExercise(bucket: Bucket, rigoToken: string, steps: Lesson[], packageContext:
|
21
|
-
interface Lesson {
|
22
|
-
id: string;
|
23
|
-
uid: string;
|
24
|
-
title: string;
|
25
|
-
type: "READ" | "CODE" | "QUIZ";
|
26
|
-
description: string;
|
27
|
-
duration?: number;
|
28
|
-
}
|
29
|
-
interface ParsedLink {
|
30
|
-
name: string;
|
31
|
-
text: string;
|
32
|
-
}
|
33
|
-
type FormState = {
|
34
|
-
description: string;
|
35
|
-
duration: number;
|
36
|
-
targetAudience: string;
|
37
|
-
hasContentIndex: boolean;
|
38
|
-
contentIndex: string;
|
39
|
-
sources: ParsedLink[];
|
40
|
-
isCompleted: boolean;
|
41
|
-
variables: string[];
|
42
|
-
currentStep: string;
|
43
|
-
title: string;
|
44
|
-
technologies?: string[];
|
45
|
-
purpose: string;
|
46
|
-
};
|
24
|
+
export declare function processExercise(bucket: Bucket, rigoToken: string, steps: Lesson[], packageContext: FormState, exercise: Lesson, exercisesDir: string, courseSlug: string, purposeSlug: string): Promise<string>;
|
47
25
|
export default class ServeCommand extends SessionCommand {
|
48
26
|
static description: string;
|
49
27
|
static flags: any;
|
50
28
|
init(): Promise<void>;
|
51
29
|
run(): Promise<void>;
|
52
30
|
}
|
53
|
-
export {};
|
package/lib/commands/serve.js
CHANGED
@@ -33,15 +33,38 @@ const sidebarGenerator_1 = require("../utils/sidebarGenerator");
|
|
33
33
|
const publish_1 = require("./publish");
|
34
34
|
const frontMatter = require("front-matter");
|
35
35
|
dotenv.config();
|
36
|
+
const validateLanguage = (language) => {
|
37
|
+
if (!language || language.length !== 2) {
|
38
|
+
return "en";
|
39
|
+
}
|
40
|
+
return language;
|
41
|
+
};
|
42
|
+
function fixSlugLength(slug) {
|
43
|
+
let clean = slug.toLowerCase();
|
44
|
+
clean = clean.replace(/[^\da-z-]+/g, "-");
|
45
|
+
clean = clean.replace(/-+/g, "-");
|
46
|
+
clean = clean.slice(0, 49);
|
47
|
+
clean = clean.replace(/^-+/, "").replace(/-+$/, "");
|
48
|
+
clean = clean.replace(/^[^\da-z]+/, "").replace(/[^\da-z]+$/, "");
|
49
|
+
if (!clean)
|
50
|
+
throw new Error("Invalid slug after cleaning");
|
51
|
+
return clean;
|
52
|
+
}
|
36
53
|
const createLearnJson = (courseInfo) => {
|
37
54
|
console.log("courseInfo to create learn json", courseInfo);
|
38
55
|
const expectedPreviewUrl = `https://${(0, creatorUtilities_2.slugify)(courseInfo.title)}.learn-pack.com/preview.png`;
|
39
56
|
console.log("Preview url in generated learn.json", expectedPreviewUrl);
|
57
|
+
const language = courseInfo.language || "en";
|
40
58
|
const learnJson = {
|
41
59
|
slug: (0, creatorUtilities_2.slugify)(courseInfo.title),
|
42
|
-
title:
|
43
|
-
|
44
|
-
|
60
|
+
title: language === "en" ?
|
61
|
+
{
|
62
|
+
us: courseInfo.title,
|
63
|
+
} :
|
64
|
+
{
|
65
|
+
[language]: courseInfo.title,
|
66
|
+
// us: courseInfo.title,
|
67
|
+
},
|
45
68
|
technologies: courseInfo.technologies || [],
|
46
69
|
difficulty: "beginner",
|
47
70
|
description: {
|
@@ -108,7 +131,9 @@ async function processExercise(bucket, rigoToken, steps, packageContext, exercis
|
|
108
131
|
// const tid = toast.loading("Generating lesson...")
|
109
132
|
const exSlug = (0, creatorUtilities_2.slugify)(exercise.id + "-" + exercise.title);
|
110
133
|
console.log("exSlug", exSlug);
|
111
|
-
const readmeFilename =
|
134
|
+
const readmeFilename = `README.${packageContext.language && packageContext.language !== "en" ?
|
135
|
+
`${packageContext.language}.` :
|
136
|
+
""}md`;
|
112
137
|
const targetDir = `${exercisesDir}/${exSlug}`;
|
113
138
|
console.log("✍🏻 Generating lesson", exercise.id, exercise.title);
|
114
139
|
const isGeneratingText = `
|
@@ -119,15 +144,15 @@ async function processExercise(bucket, rigoToken, steps, packageContext, exercis
|
|
119
144
|
await uploadFileToBucket(bucket, isGeneratingText, `${targetDir}/${readmeFilename}`);
|
120
145
|
const readme = await (0, rigoActions_1.readmeCreator)(rigoToken, {
|
121
146
|
title: `${exercise.id} - ${exercise.title}`,
|
122
|
-
output_lang: "en",
|
147
|
+
output_lang: packageContext.language || "en",
|
123
148
|
list_of_exercises: JSON.stringify(steps),
|
124
|
-
tutorial_description: packageContext,
|
149
|
+
tutorial_description: JSON.stringify(packageContext),
|
125
150
|
lesson_description: exercise.description,
|
126
151
|
kind: exercise.type.toLowerCase(),
|
127
152
|
}, purposeSlug);
|
128
153
|
const duration = exercise.duration;
|
129
154
|
let attempts = 0;
|
130
|
-
let readability = (0, creatorUtilities_2.checkReadability)(readme.parsed.content,
|
155
|
+
let readability = (0, creatorUtilities_2.checkReadability)(readme.parsed.content, 250, duration || 3);
|
131
156
|
while (readability.fkglResult.fkgl > PARAMS.max_fkgl &&
|
132
157
|
attempts < PARAMS.max_rewrite_attempts) {
|
133
158
|
(0, creatorSocket_1.emitToCourse)(courseSlug, "course-creation", {
|
@@ -158,7 +183,7 @@ async function processExercise(bucket, rigoToken, steps, packageContext, exercis
|
|
158
183
|
console.log("🔍 Creating code file for", exercise.title);
|
159
184
|
const codeFile = await (0, rigoActions_1.createCodeFile)(rigoToken, {
|
160
185
|
readme: readability.newMarkdown,
|
161
|
-
tutorial_info: packageContext,
|
186
|
+
tutorial_info: JSON.stringify(packageContext),
|
162
187
|
});
|
163
188
|
await uploadFileToBucket(bucket, codeFile.parsed.content, `${targetDir}/index.${codeFile.parsed.extension.replace(".", "")}`);
|
164
189
|
(0, creatorSocket_1.emitToCourse)(courseSlug, "course-creation", {
|
@@ -196,12 +221,6 @@ class ServeCommand extends SessionCommand_1.default {
|
|
196
221
|
console.log("GCP_CREDENTIALS_JSON is not set");
|
197
222
|
process.exit(1);
|
198
223
|
}
|
199
|
-
let deploymentURL = process.env.DEPLOYMENT_URL;
|
200
|
-
if (!deploymentURL) {
|
201
|
-
console.log("DEPLOYMENT_URL is not set, using default value");
|
202
|
-
deploymentURL = "https://app.learnpack.co";
|
203
|
-
}
|
204
|
-
console.log("DEPLOYMENT_URL", deploymentURL);
|
205
224
|
const credentials = JSON.parse(crendsEnv);
|
206
225
|
const bucketStorage = new storage_1.Storage({
|
207
226
|
credentials,
|
@@ -656,7 +675,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
656
675
|
await uploadFileToBucket(bucket, JSON.stringify(learnJson), `${tutorialDir}/learn.json`);
|
657
676
|
console.log("🔄 Learn.json uploaded to bucket to", tutorialDir);
|
658
677
|
console.log("🔄 Processing lessons with purpose", syllabus.courseInfo.purpose);
|
659
|
-
const lessonsPromises = syllabus.lessons.map(lesson => processExercise(bucket, rigoToken, syllabus.lessons,
|
678
|
+
const lessonsPromises = syllabus.lessons.map(lesson => processExercise(bucket, rigoToken, syllabus.lessons, syllabus.courseInfo, lesson, tutorialDir + "/exercises", (0, creatorUtilities_2.slugify)(syllabus.courseInfo.title), syllabus.courseInfo.purpose));
|
660
679
|
const readmeContents = await Promise.all(lessonsPromises);
|
661
680
|
let imagesArray = [];
|
662
681
|
for (const content of readmeContents) {
|
@@ -715,10 +734,12 @@ class ServeCommand extends SessionCommand_1.default {
|
|
715
734
|
if (!rigoToken || !bcToken) {
|
716
735
|
return res
|
717
736
|
.status(400)
|
718
|
-
.json({ error: "
|
737
|
+
.json({ error: "Authentication failed, missing tokens" });
|
719
738
|
}
|
720
739
|
const { config, exercises } = await (0, configBuilder_1.buildConfig)(bucket, slug);
|
721
|
-
//
|
740
|
+
// console.log(slug, "SLUG")
|
741
|
+
const fixedSlug = fixSlugLength(slug);
|
742
|
+
// console.log(fixedSlug, "FIXED SLUG")
|
722
743
|
const prefix = `courses/${slug}/`;
|
723
744
|
const tmpRoot = path.join(os.tmpdir(), `learnpack-${slug}`);
|
724
745
|
const buildRoot = path.join(tmpRoot, "build");
|
@@ -746,7 +767,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
746
767
|
.replace(/{{title}}/g, config.title.us)
|
747
768
|
.replace(/<title>.*<\/title>/, `<title>${config.title.us}</title>`)
|
748
769
|
.replace(/{{description}}/g, config.description.us)
|
749
|
-
.replace(/{{preview}}/g, fixPreviewUrl(
|
770
|
+
.replace(/{{preview}}/g, fixPreviewUrl(fixedSlug, "") ||
|
750
771
|
"https://raw.githubusercontent.com/learnpack/ide/master/public/learnpack.svg")
|
751
772
|
.replace(/{{slug}}/g, slug)
|
752
773
|
.replace(/{{duration}}/g, (0, misc_1.minutesToISO8601Duration)(config.duration));
|
@@ -767,9 +788,13 @@ class ServeCommand extends SessionCommand_1.default {
|
|
767
788
|
}));
|
768
789
|
// 8) Crear el config.json en buildRoot con lo que retorna buildConfig
|
769
790
|
const fullConfig = { config, exercises };
|
791
|
+
fullConfig.config.slug = fixedSlug;
|
792
|
+
fullConfig.config.preview =
|
793
|
+
fixPreviewUrl(fixedSlug, "") ||
|
794
|
+
"https://raw.githubusercontent.com/learnpack/ide/master/public/learnpack.svg";
|
770
795
|
fs.writeFileSync(path.join(buildRoot, "config.json"), JSON.stringify(fullConfig, null, 2), "utf-8");
|
771
796
|
// 9) Empaquetar en ZIP (solo contenido de buildRoot)
|
772
|
-
const zipName = `${
|
797
|
+
const zipName = `${fixedSlug}.zip`;
|
773
798
|
const zipPath = path.join(tmpRoot, zipName);
|
774
799
|
const output = fs.createWriteStream(zipPath);
|
775
800
|
const archive = archiver("zip", { zlib: { level: 9 } });
|
@@ -781,7 +806,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
781
806
|
const rigoRes = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/learnpack/upload`, form, {
|
782
807
|
headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: `Token ${rigoToken}` }),
|
783
808
|
});
|
784
|
-
await (0, publish_1.handleAssetCreation)({ token: bcToken, rigobotToken: rigoToken }, config, rigoRes.data.url);
|
809
|
+
await (0, publish_1.handleAssetCreation)({ token: bcToken, rigobotToken: rigoToken }, fullConfig.config, rigoRes.data.url);
|
785
810
|
rimraf.sync(tmpRoot);
|
786
811
|
console.log("RIGO RES", rigoRes.data);
|
787
812
|
return res.json({ url: rigoRes.data.url });
|