@learnpack/learnpack 5.0.246 → 5.0.252
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/lib/commands/audit.js +1 -1
- package/lib/commands/publish.js +4 -3
- package/lib/commands/serve.d.ts +0 -3
- package/lib/commands/serve.js +25 -45
- package/lib/creatorDist/assets/{index-CZYzWk3G.js → index-CFM_Ypyi.js} +25 -22
- package/lib/creatorDist/index.html +1 -1
- package/lib/managers/config/exercise.js +1 -1
- package/lib/utils/api.d.ts +2 -0
- package/lib/utils/api.js +4 -4
- package/lib/utils/configBuilder.js +1 -1
- package/lib/utils/creatorUtilities.d.ts +1 -0
- package/lib/utils/creatorUtilities.js +5 -1
- package/package.json +1 -1
- package/src/commands/audit.ts +9 -18
- package/src/commands/publish.ts +4 -3
- package/src/commands/serve.ts +41 -65
- package/src/creator/src/App.tsx +1 -1
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +1 -1
- package/src/creator/src/utils/rigo.ts +2 -0
- package/src/creatorDist/assets/{index-CZYzWk3G.js → index-CFM_Ypyi.js} +25 -22
- package/src/creatorDist/index.html +1 -1
- package/src/managers/config/exercise.ts +8 -16
- package/src/utils/api.ts +4 -5
- package/src/utils/configBuilder.ts +1 -1
- package/src/utils/creatorUtilities.ts +4 -0
- package/src/utils/templates/incremental/.vscode/schema.json +5 -5
- package/src/utils/templates/isolated/.vscode/schema.json +5 -5
package/lib/commands/audit.js
CHANGED
@@ -309,7 +309,7 @@ class AuditCommand extends SessionCommand_1.default {
|
|
309
309
|
for (const readmeFile of readmeFiles) {
|
310
310
|
// Checking the language of each README file.
|
311
311
|
if (readmeFile === "README.md")
|
312
|
-
translations.push("
|
312
|
+
translations.push("en");
|
313
313
|
else {
|
314
314
|
const regexGroups = translationRegex.exec(readmeFile);
|
315
315
|
if (regexGroups)
|
package/lib/commands/publish.js
CHANGED
@@ -22,6 +22,7 @@ const creatorUtilities_1 = require("../utils/creatorUtilities");
|
|
22
22
|
const uploadZipEndpont = api_1.RIGOBOT_HOST + "/v1/learnpack/upload";
|
23
23
|
const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, learnpackDeployUrl, b64IndexReadme, all_translations = []) => {
|
24
24
|
const categories = {
|
25
|
+
en: 9,
|
25
26
|
us: 9,
|
26
27
|
es: 10,
|
27
28
|
};
|
@@ -232,8 +233,8 @@ class BuildCommand extends SessionCommand_1.default {
|
|
232
233
|
const buildManifestPWA = path.join(buildDir, "manifest.webmanifest");
|
233
234
|
if (fs.existsSync(indexHtmlPath)) {
|
234
235
|
let indexHtmlContent = fs.readFileSync(indexHtmlPath, "utf-8");
|
235
|
-
const description = learnJson.description.
|
236
|
-
const title = learnJson.title.
|
236
|
+
const description = learnJson.description.en || "LearnPack is awesome!";
|
237
|
+
const title = learnJson.title.en || "LearnPack: Interactive Learning as a Service";
|
237
238
|
const previewUrl = learnJson.preview ||
|
238
239
|
"https://raw.githubusercontent.com/learnpack/ide/refs/heads/master/public/learnpack.svg";
|
239
240
|
// Replace placeholders and the <title>Old title </title> tag for a new tag with the title
|
@@ -301,7 +302,7 @@ class BuildCommand extends SessionCommand_1.default {
|
|
301
302
|
console.log(res.data);
|
302
303
|
fs.unlinkSync(zipFilePath);
|
303
304
|
this.removeDirectory(buildDir);
|
304
|
-
await (0, exports.handleAssetCreation)(sessionPayload, learnJson, "
|
305
|
+
await (0, exports.handleAssetCreation)(sessionPayload, learnJson, "en", res.data.url, "", []);
|
305
306
|
}
|
306
307
|
catch (error) {
|
307
308
|
if (axios_1.default.isAxiosError(error)) {
|
package/lib/commands/serve.d.ts
CHANGED
package/lib/commands/serve.js
CHANGED
@@ -42,21 +42,16 @@ function findLast(array, predicate) {
|
|
42
42
|
const createLearnJson = (courseInfo) => {
|
43
43
|
// console.log("courseInfo to create learn json", courseInfo)
|
44
44
|
const expectedPreviewUrl = `https://${courseInfo.slug}.learn-pack.com/preview.png`;
|
45
|
-
console.log("Preview url in generated learn.json", expectedPreviewUrl);
|
46
45
|
const language = courseInfo.language || "en";
|
47
46
|
const learnJson = {
|
48
47
|
slug: courseInfo.slug,
|
49
|
-
title:
|
50
|
-
|
51
|
-
|
52
|
-
} :
|
53
|
-
{
|
54
|
-
[language]: courseInfo.title,
|
55
|
-
},
|
48
|
+
title: {
|
49
|
+
[language]: courseInfo.title,
|
50
|
+
},
|
56
51
|
technologies: courseInfo.technologies || [],
|
57
52
|
difficulty: "beginner",
|
58
53
|
description: {
|
59
|
-
[language
|
54
|
+
[language]: courseInfo.description,
|
60
55
|
},
|
61
56
|
grading: "isolated",
|
62
57
|
telemetry: {
|
@@ -96,11 +91,10 @@ const processImage = async (url, description, rigoToken, courseSlug) => {
|
|
96
91
|
};
|
97
92
|
exports.processImage = processImage;
|
98
93
|
const createInitialSidebar = async (slugs, initialLanguage = "en") => {
|
99
|
-
const language = initialLanguage === "en" ? "us" : initialLanguage;
|
100
94
|
const sidebar = {};
|
101
95
|
for (const slug of slugs) {
|
102
96
|
sidebar[slug] = {
|
103
|
-
[
|
97
|
+
[initialLanguage]: slug,
|
104
98
|
};
|
105
99
|
}
|
106
100
|
return sidebar;
|
@@ -126,13 +120,17 @@ const createMultiLangAsset = async (bucket, rigoToken, bcToken, courseSlug, cour
|
|
126
120
|
const all_translations = [];
|
127
121
|
for (const lang of availableLangs) {
|
128
122
|
// eslint-disable-next-line no-await-in-loop
|
129
|
-
const indexReadme = await bucket.file(`courses/${courseSlug}/README
|
123
|
+
const indexReadme = await bucket.file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(lang)}`);
|
130
124
|
// eslint-disable-next-line no-await-in-loop
|
131
125
|
const [indexReadmeContent] = await indexReadme.download();
|
132
126
|
const indexReadmeString = indexReadmeContent.toString();
|
133
127
|
const b64IndexReadme = Buffer.from(indexReadmeString).toString("base64");
|
134
128
|
// eslint-disable-next-line no-await-in-loop
|
135
129
|
const asset = await (0, publish_1.handleAssetCreation)({ token: bcToken, rigobotToken: rigoToken.trim() }, courseJson, lang, deployUrl, b64IndexReadme, all_translations);
|
130
|
+
if (!asset) {
|
131
|
+
console.log("No se pudo crear el asset, saltando idioma", lang);
|
132
|
+
continue;
|
133
|
+
}
|
136
134
|
all_translations.push(asset.slug);
|
137
135
|
}
|
138
136
|
};
|
@@ -191,6 +189,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
191
189
|
console.log("GCP_CREDENTIALS_JSON is not set");
|
192
190
|
process.exit(1);
|
193
191
|
}
|
192
|
+
await api_1.default.updateTechnologiesPeriodically();
|
194
193
|
const credentials = JSON.parse(crendsEnv);
|
195
194
|
const bucketStorage = new storage_1.Storage({
|
196
195
|
credentials,
|
@@ -333,13 +332,8 @@ class ServeCommand extends SessionCommand_1.default {
|
|
333
332
|
const { courseSlug } = req.params;
|
334
333
|
const body = req.body;
|
335
334
|
// Save the file as courses/courseSlug/README.md
|
336
|
-
const filePath = `courses/${courseSlug}/README
|
337
|
-
body.parsed.language_code === "en" ?
|
338
|
-
"md" :
|
339
|
-
`${body.parsed.language_code}.md`}`;
|
340
|
-
console.log("Saving initial readme to", filePath);
|
335
|
+
const filePath = `courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(body.parsed.language_code)}`;
|
341
336
|
await uploadFileToBucket(bucket, body.parsed.content, filePath);
|
342
|
-
console.log("Initial readme saved to", filePath);
|
343
337
|
res.json({ status: "SUCCESS" });
|
344
338
|
});
|
345
339
|
app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
|
@@ -496,7 +490,8 @@ class ServeCommand extends SessionCommand_1.default {
|
|
496
490
|
console.log("GET /exercise/:slug/readme");
|
497
491
|
const { slug } = req.params;
|
498
492
|
const courseSlug = req.query.slug;
|
499
|
-
const lang = req.query.lang || "
|
493
|
+
const lang = req.query.lang || "en";
|
494
|
+
console.log("LANG", lang);
|
500
495
|
if (!courseSlug) {
|
501
496
|
return res.status(400).json({ error: "Missing courseSlug" });
|
502
497
|
}
|
@@ -508,15 +503,14 @@ class ServeCommand extends SessionCommand_1.default {
|
|
508
503
|
if (readmeFiles.length === 0) {
|
509
504
|
return res.status(404).json({ error: "No README files found" });
|
510
505
|
}
|
511
|
-
const requestedFilename =
|
512
|
-
`${basePath}README.md` :
|
513
|
-
`${basePath}README.${lang}.md`;
|
506
|
+
const requestedFilename = `${basePath}README${(0, creatorUtilities_1.getReadmeExtension)(lang)}`;
|
514
507
|
let selectedFile = readmeFiles.find(f => f === requestedFilename);
|
515
508
|
if (!selectedFile) {
|
509
|
+
console.log("No se encontro en ese idioma, devolviendo el primero");
|
516
510
|
selectedFile = readmeFiles[0];
|
517
511
|
console.warn(`Requested README not found for lang '${lang}', using '${selectedFile}'`);
|
518
512
|
}
|
519
|
-
let foundLang = "
|
513
|
+
let foundLang = "en";
|
520
514
|
const match = selectedFile.match(/readme(?:\.([a-z]{2}))?\.md$/i);
|
521
515
|
if (match && match[1]) {
|
522
516
|
foundLang = match[1].toLowerCase();
|
@@ -574,7 +568,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
574
568
|
.json({ error: "Missing title or readme content" });
|
575
569
|
}
|
576
570
|
const courseSlug = query.slug;
|
577
|
-
const fileName = `courses/${courseSlug}/exercises/${title}/README${
|
571
|
+
const fileName = `courses/${courseSlug}/exercises/${title}/README${(0, creatorUtilities_1.getReadmeExtension)(language)}`;
|
578
572
|
const file = bucket.file(fileName);
|
579
573
|
await file.save(readme);
|
580
574
|
const created = await file.exists();
|
@@ -613,9 +607,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
613
607
|
const languageCodes = new Set();
|
614
608
|
try {
|
615
609
|
await Promise.all(exerciseSlugs.map(async (slug) => {
|
616
|
-
const readmePath = `courses/${courseSlug}/exercises/${slug}/README${
|
617
|
-
"" :
|
618
|
-
`.${currentLanguage}`}.md`;
|
610
|
+
const readmePath = `courses/${courseSlug}/exercises/${slug}/README${(0, creatorUtilities_1.getReadmeExtension)(currentLanguage)}`;
|
619
611
|
const readme = await bucket.file(readmePath).download();
|
620
612
|
await Promise.all(languagesToTranslate.map(async (language) => {
|
621
613
|
const response = await (0, rigoActions_1.translateExercise)(rigoToken, {
|
@@ -623,18 +615,11 @@ class ServeCommand extends SessionCommand_1.default {
|
|
623
615
|
output_language: language,
|
624
616
|
exercise_slug: slug,
|
625
617
|
});
|
626
|
-
const translatedReadme = await bucket.file(`courses/${courseSlug}/exercises/${slug}/README${response.parsed.output_language_code
|
627
|
-
response.parsed.output_language_code === "en" ?
|
628
|
-
"" :
|
629
|
-
`.${response.parsed.output_language_code}`}.md`);
|
618
|
+
const translatedReadme = await bucket.file(`courses/${courseSlug}/exercises/${slug}/README${(0, creatorUtilities_1.getReadmeExtension)(response.parsed.output_language_code)}`);
|
630
619
|
await translatedReadme.save(response.parsed.translation);
|
631
620
|
languageCodes.add(response.parsed.output_language_code);
|
632
621
|
}));
|
633
622
|
}));
|
634
|
-
if (languageCodes.has("en")) {
|
635
|
-
languageCodes.delete("en");
|
636
|
-
languageCodes.add("us");
|
637
|
-
}
|
638
623
|
const currentLanguages = Object.keys(courseJson.title);
|
639
624
|
for (const languageCode of currentLanguages) {
|
640
625
|
if (languageCodes.has(languageCode)) {
|
@@ -642,7 +627,6 @@ class ServeCommand extends SessionCommand_1.default {
|
|
642
627
|
}
|
643
628
|
}
|
644
629
|
if ([...languageCodes].length > 0) {
|
645
|
-
console.log("TRANSLATING COURSE METADATA", languageCodes);
|
646
630
|
const translatedCourseMetadata = await Promise.all([...languageCodes].map(async (languageCode) => {
|
647
631
|
const result = await (0, rigoActions_1.translateCourseMetadata)(rigoToken, {
|
648
632
|
title: courseJson.title[currentLanguage],
|
@@ -661,9 +645,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
661
645
|
metadata.description;
|
662
646
|
}
|
663
647
|
await uploadFileToBucket(bucket, JSON.stringify(courseJson), `courses/${courseSlug}/learn.json`);
|
664
|
-
const previewReadme = await bucket.file(`courses/${courseSlug}/README${
|
665
|
-
"" :
|
666
|
-
`.${currentLanguage}`}.md`);
|
648
|
+
const previewReadme = await bucket.file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(currentLanguage)}`);
|
667
649
|
const [previewReadmeContent] = await previewReadme.download();
|
668
650
|
const previewReadmeContentString = previewReadmeContent.toString();
|
669
651
|
await Promise.all([...languageCodes].map(async (languageCode) => {
|
@@ -673,9 +655,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
673
655
|
exercise_slug: "preview-readme",
|
674
656
|
});
|
675
657
|
await bucket
|
676
|
-
.file(`courses/${courseSlug}/README${
|
677
|
-
"" :
|
678
|
-
`.${languageCode}`}.md`)
|
658
|
+
.file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(languageCode)}`)
|
679
659
|
.save(translatedPreviewReadme.parsed.translation);
|
680
660
|
}));
|
681
661
|
}
|
@@ -918,10 +898,10 @@ class ServeCommand extends SessionCommand_1.default {
|
|
918
898
|
};
|
919
899
|
copyDir(uiSrc, buildRoot);
|
920
900
|
const availableLangs = Object.keys(config.title);
|
921
|
-
let selectedLang = "
|
901
|
+
let selectedLang = "en";
|
922
902
|
let title = "";
|
923
|
-
if (availableLangs.includes("
|
924
|
-
title = config.title.
|
903
|
+
if (availableLangs.includes("en")) {
|
904
|
+
title = config.title.en;
|
925
905
|
}
|
926
906
|
else {
|
927
907
|
// Select the first available lang
|
@@ -18251,28 +18251,31 @@ const d2 = async (e) => {
|
|
18251
18251
|
try {
|
18252
18252
|
const l = Ku(15),
|
18253
18253
|
u = `https://9cw5zmww-3000.use2.devtunnels.ms/notifications/${l}`
|
18254
|
-
return
|
18255
|
-
|
18256
|
-
|
18257
|
-
|
18258
|
-
|
18259
|
-
|
18260
|
-
|
18261
|
-
|
18262
|
-
|
18263
|
-
|
18264
|
-
|
18265
|
-
|
18266
|
-
|
18267
|
-
headers: {
|
18268
|
-
"Content-Type": "application/json",
|
18269
|
-
Authorization: `Token ${t}`,
|
18254
|
+
return (
|
18255
|
+
console.log("WEBHOOK URL to send to Rigo", u),
|
18256
|
+
{
|
18257
|
+
res: (
|
18258
|
+
await Pe.post(
|
18259
|
+
`${Ds}/v1/prompting${r ? "/public" : ""}/completion/${
|
18260
|
+
L1 ? "39" : "390"
|
18261
|
+
}/`,
|
18262
|
+
{
|
18263
|
+
inputs: e,
|
18264
|
+
include_purpose_objective: !0,
|
18265
|
+
purpose_slug: n,
|
18266
|
+
webhook_url: u,
|
18270
18267
|
},
|
18271
|
-
|
18272
|
-
|
18273
|
-
|
18274
|
-
|
18275
|
-
|
18268
|
+
{
|
18269
|
+
headers: {
|
18270
|
+
"Content-Type": "application/json",
|
18271
|
+
Authorization: `Token ${t}`,
|
18272
|
+
},
|
18273
|
+
}
|
18274
|
+
)
|
18275
|
+
).data,
|
18276
|
+
notificationId: l,
|
18277
|
+
}
|
18278
|
+
)
|
18276
18279
|
} catch (l) {
|
18277
18280
|
const u = l
|
18278
18281
|
return (
|
@@ -21192,7 +21195,7 @@ function K7() {
|
|
21192
21195
|
y.rigoToken &&
|
21193
21196
|
l({ ...y, rigoToken: "", bcToken: "", userId: "", user: null })
|
21194
21197
|
let $ = T.filter((ee) => ee.lang === r.language)
|
21195
|
-
$.length === 0 && ($ = T.filter((ee) => ee.lang === "
|
21198
|
+
$.length === 0 && ($ = T.filter((ee) => ee.lang === "en"))
|
21196
21199
|
const Q = await p2(
|
21197
21200
|
{
|
21198
21201
|
courseInfo: `${JSON.stringify(
|
@@ -10,7 +10,7 @@
|
|
10
10
|
/>
|
11
11
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-CFM_Ypyi.js"></script>
|
14
14
|
<link rel="stylesheet" crossorigin href="/creator/assets/index-DmpsXknz.css">
|
15
15
|
</head>
|
16
16
|
<body>
|
@@ -89,7 +89,7 @@ const exercise = (path, position, configObject) => {
|
|
89
89
|
exercises[position].done :
|
90
90
|
false,
|
91
91
|
getReadme: function (lang = null) {
|
92
|
-
if (lang === "us")
|
92
|
+
if (lang === "en" || lang === "us")
|
93
93
|
lang = null; // <-- english is default, no need to append it to the file name
|
94
94
|
if (!fs.existsSync(`${this.path}/README${lang ? "." + lang : ""}.md`)) {
|
95
95
|
console_1.default.error(`Language ${lang} not found for exercise ${slug}, switching to default language`);
|
package/lib/utils/api.d.ts
CHANGED
@@ -35,6 +35,7 @@ type TTechnology = {
|
|
35
35
|
lang: string;
|
36
36
|
};
|
37
37
|
export declare const fetchTechnologies: () => Promise<any[]>;
|
38
|
+
declare function updateTechnologiesPeriodically(): Promise<void>;
|
38
39
|
export declare const getCurrentTechnologies: () => TTechnology[];
|
39
40
|
declare const _default: {
|
40
41
|
login: (identification: string, password: string) => Promise<any>;
|
@@ -60,5 +61,6 @@ declare const _default: {
|
|
60
61
|
updateRigoAssetID: (token: string, slug: string, asset_id: number) => Promise<any>;
|
61
62
|
createRigoPackage: (token: string, slug: string, config: any) => Promise<any>;
|
62
63
|
getCurrentTechnologies: () => TTechnology[];
|
64
|
+
updateTechnologiesPeriodically: typeof updateTechnologiesPeriodically;
|
63
65
|
};
|
64
66
|
export default _default;
|
package/lib/utils/api.js
CHANGED
@@ -420,7 +420,7 @@ const getCategories = async (token) => {
|
|
420
420
|
const updateRigoAssetID = async (token, slug, asset_id) => {
|
421
421
|
const url = `${exports.RIGOBOT_HOST}/v1/learnpack/package/${slug}/`;
|
422
422
|
const headers = {
|
423
|
-
Authorization:
|
423
|
+
Authorization: "Token " + token.trim(),
|
424
424
|
};
|
425
425
|
try {
|
426
426
|
const response = await axios_1.default.put(url, { asset_id }, { headers });
|
@@ -434,7 +434,7 @@ const updateRigoAssetID = async (token, slug, asset_id) => {
|
|
434
434
|
const createRigoPackage = async (token, slug, config) => {
|
435
435
|
const url = `${exports.RIGOBOT_HOST}/v1/learnpack/package`;
|
436
436
|
const headers = {
|
437
|
-
Authorization:
|
437
|
+
Authorization: "Token " + token.trim(),
|
438
438
|
};
|
439
439
|
try {
|
440
440
|
const response = await axios_1.default.post(url, { slug, config }, { headers });
|
@@ -448,7 +448,7 @@ const createRigoPackage = async (token, slug, config) => {
|
|
448
448
|
let technologiesCache = [];
|
449
449
|
const fetchTechnologies = async () => {
|
450
450
|
const BREATHECODE_PERMANENT_TOKEN = process.env.BREATHECODE_PERMANENT_TOKEN;
|
451
|
-
const LANGS = ["en", "es"
|
451
|
+
const LANGS = ["en", "es"];
|
452
452
|
if (!BREATHECODE_PERMANENT_TOKEN) {
|
453
453
|
throw new Error("BREATHECODE_PERMANENT_TOKEN is not defined in environment variables");
|
454
454
|
}
|
@@ -492,7 +492,6 @@ async function updateTechnologiesPeriodically() {
|
|
492
492
|
setTimeout(updateTechnologiesPeriodically, 24 * 60 * 60 * 1000);
|
493
493
|
}
|
494
494
|
}
|
495
|
-
updateTechnologiesPeriodically();
|
496
495
|
const getCurrentTechnologies = () => technologiesCache;
|
497
496
|
exports.getCurrentTechnologies = getCurrentTechnologies;
|
498
497
|
exports.default = {
|
@@ -513,4 +512,5 @@ exports.default = {
|
|
513
512
|
updateRigoAssetID,
|
514
513
|
createRigoPackage,
|
515
514
|
getCurrentTechnologies: exports.getCurrentTechnologies,
|
515
|
+
updateTechnologiesPeriodically,
|
516
516
|
};
|
@@ -34,7 +34,7 @@ async function buildConfig(bucket, courseSlug) {
|
|
34
34
|
const fname = parts.pop();
|
35
35
|
const m = fname.match(/^readme(?:\.([a-z]{2}))?\.md$/i);
|
36
36
|
if (m) {
|
37
|
-
const lang = m[1] || "
|
37
|
+
const lang = m[1] || "en";
|
38
38
|
map[slug].translations[lang] = fname;
|
39
39
|
}
|
40
40
|
else {
|
@@ -96,4 +96,5 @@ export declare function countSentences(text: string): number;
|
|
96
96
|
export declare function howManyDifficultParagraphs(paragraphs: TFKGLResult[], maxFKGL: number): number;
|
97
97
|
export declare const appendContentIndex: () => Promise<string | null>;
|
98
98
|
export declare const appendAIRules: () => Promise<string | null>;
|
99
|
+
export declare const getReadmeExtension: (language: string) => string;
|
99
100
|
export {};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.appendAIRules = exports.appendContentIndex = exports.saveTranslatedReadme = exports.makePackageInfo = exports.getExInfo = exports.slugify = exports.estimateReadingTime = void 0;
|
3
|
+
exports.getReadmeExtension = exports.appendAIRules = exports.appendContentIndex = exports.saveTranslatedReadme = exports.makePackageInfo = exports.getExInfo = exports.slugify = exports.estimateReadingTime = void 0;
|
4
4
|
exports.checkReadability = checkReadability;
|
5
5
|
exports.extractImagesFromMarkdown = extractImagesFromMarkdown;
|
6
6
|
exports.getFilenameFromUrl = getFilenameFromUrl;
|
@@ -405,3 +405,7 @@ const appendAIRules = async () => {
|
|
405
405
|
return null;
|
406
406
|
};
|
407
407
|
exports.appendAIRules = appendAIRules;
|
408
|
+
const getReadmeExtension = (language) => {
|
409
|
+
return language === "en" || language === "us" ? ".md" : `.${language}.md`;
|
410
|
+
};
|
411
|
+
exports.getReadmeExtension = getReadmeExtension;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@learnpack/learnpack",
|
3
3
|
"description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
|
4
|
-
"version": "5.0.
|
4
|
+
"version": "5.0.252",
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
6
6
|
"contributors": [
|
7
7
|
{
|
package/src/commands/audit.ts
CHANGED
@@ -178,8 +178,7 @@ class AuditCommand extends SessionCommand {
|
|
178
178
|
exercise: undefined,
|
179
179
|
msg: "The repository property is not in the configuration object",
|
180
180
|
})
|
181
|
-
} else
|
182
|
-
Audit.isUrl(config!.config?.repository, errors, counter)
|
181
|
+
} else Audit.isUrl(config!.config?.repository, errors, counter)
|
183
182
|
|
184
183
|
// These two lines check if the 'description' property is inside the configuration object.
|
185
184
|
Console.debug(
|
@@ -196,8 +195,7 @@ Audit.isUrl(config!.config?.repository, errors, counter)
|
|
196
195
|
msg: "The projectType property is mandatory in the configuration object",
|
197
196
|
})
|
198
197
|
|
199
|
-
if (errors.length === 0)
|
200
|
-
Console.log("The config file is ok")
|
198
|
+
if (errors.length === 0) Console.log("The config file is ok")
|
201
199
|
|
202
200
|
// Validates if images and links are working at every README file.
|
203
201
|
const exercises = config!.exercises
|
@@ -314,13 +312,11 @@ Console.log("The config file is ok")
|
|
314
312
|
const files: string[] = []
|
315
313
|
let count = 0
|
316
314
|
for (const item of readmeFiles) {
|
317
|
-
if (count < item.count)
|
318
|
-
count = item.count
|
315
|
+
if (count < item.count) count = item.count
|
319
316
|
}
|
320
317
|
|
321
318
|
for (const item of readmeFiles) {
|
322
|
-
if (item.count !== count)
|
323
|
-
files.push(` ${item.exercise}`)
|
319
|
+
if (item.count !== count) files.push(` ${item.exercise}`)
|
324
320
|
}
|
325
321
|
|
326
322
|
if (files.length > 0) {
|
@@ -390,12 +386,10 @@ files.push(` ${item.exercise}`)
|
|
390
386
|
|
391
387
|
for (const readmeFile of readmeFiles) {
|
392
388
|
// Checking the language of each README file.
|
393
|
-
if (readmeFile === "README.md")
|
394
|
-
translations.push("us")
|
389
|
+
if (readmeFile === "README.md") translations.push("en")
|
395
390
|
else {
|
396
391
|
const regexGroups = translationRegex.exec(readmeFile)
|
397
|
-
if (regexGroups)
|
398
|
-
translations.push(regexGroups[1])
|
392
|
+
if (regexGroups) translations.push(regexGroups[1])
|
399
393
|
}
|
400
394
|
|
401
395
|
const readme = fs.readFileSync(path.resolve(readmeFile)).toString()
|
@@ -450,12 +444,9 @@ translations.push(regexGroups[1])
|
|
450
444
|
const date = new Date()
|
451
445
|
learnjson.validationAt = date.getTime()
|
452
446
|
|
453
|
-
if (errors.length > 0)
|
454
|
-
learnjson.validationStatus = "
|
455
|
-
else
|
456
|
-
learnjson.validationStatus = "warning"
|
457
|
-
else
|
458
|
-
learnjson.validationStatus = "success"
|
447
|
+
if (errors.length > 0) learnjson.validationStatus = "error"
|
448
|
+
else if (warnings.length > 0) learnjson.validationStatus = "warning"
|
449
|
+
else learnjson.validationStatus = "success"
|
459
450
|
|
460
451
|
// Writes the "learn.json" file with all the new properties
|
461
452
|
await fs.promises.writeFile("./learn.json", JSON.stringify(learnjson))
|
package/src/commands/publish.ts
CHANGED
@@ -32,6 +32,7 @@ export const handleAssetCreation = async (
|
|
32
32
|
all_translations: string[] = []
|
33
33
|
) => {
|
34
34
|
const categories: Record<string, number> = {
|
35
|
+
en: 9,
|
35
36
|
us: 9,
|
36
37
|
es: 10,
|
37
38
|
}
|
@@ -346,9 +347,9 @@ class BuildCommand extends SessionCommand {
|
|
346
347
|
if (fs.existsSync(indexHtmlPath)) {
|
347
348
|
let indexHtmlContent = fs.readFileSync(indexHtmlPath, "utf-8")
|
348
349
|
|
349
|
-
const description = learnJson.description.
|
350
|
+
const description = learnJson.description.en || "LearnPack is awesome!"
|
350
351
|
const title =
|
351
|
-
learnJson.title.
|
352
|
+
learnJson.title.en || "LearnPack: Interactive Learning as a Service"
|
352
353
|
|
353
354
|
const previewUrl =
|
354
355
|
learnJson.preview ||
|
@@ -441,7 +442,7 @@ class BuildCommand extends SessionCommand {
|
|
441
442
|
await handleAssetCreation(
|
442
443
|
sessionPayload,
|
443
444
|
learnJson,
|
444
|
-
"
|
445
|
+
"en",
|
445
446
|
res.data.url,
|
446
447
|
"",
|
447
448
|
[]
|
package/src/commands/serve.ts
CHANGED
@@ -36,6 +36,7 @@ import * as dotenv from "dotenv"
|
|
36
36
|
import {
|
37
37
|
extractImagesFromMarkdown,
|
38
38
|
getFilenameFromUrl,
|
39
|
+
getReadmeExtension,
|
39
40
|
} from "../utils/creatorUtilities"
|
40
41
|
// import { handleAssetCreation } from "./publish"
|
41
42
|
import axios from "axios"
|
@@ -66,25 +67,18 @@ export const createLearnJson = (courseInfo: FormState) => {
|
|
66
67
|
// console.log("courseInfo to create learn json", courseInfo)
|
67
68
|
|
68
69
|
const expectedPreviewUrl = `https://${courseInfo.slug}.learn-pack.com/preview.png`
|
69
|
-
console.log("Preview url in generated learn.json", expectedPreviewUrl)
|
70
70
|
|
71
71
|
const language = courseInfo.language || "en"
|
72
72
|
|
73
73
|
const learnJson = {
|
74
74
|
slug: courseInfo.slug,
|
75
|
-
title:
|
76
|
-
language
|
77
|
-
|
78
|
-
us: courseInfo.title,
|
79
|
-
} :
|
80
|
-
{
|
81
|
-
[language]: courseInfo.title,
|
82
|
-
},
|
75
|
+
title: {
|
76
|
+
[language]: courseInfo.title,
|
77
|
+
},
|
83
78
|
technologies: courseInfo.technologies || [],
|
84
79
|
difficulty: "beginner",
|
85
80
|
description: {
|
86
|
-
[language
|
87
|
-
courseInfo.description,
|
81
|
+
[language]: courseInfo.description,
|
88
82
|
},
|
89
83
|
grading: "isolated",
|
90
84
|
telemetry: {
|
@@ -140,12 +134,10 @@ const createInitialSidebar = async (
|
|
140
134
|
slugs: string[],
|
141
135
|
initialLanguage = "en"
|
142
136
|
) => {
|
143
|
-
const language = initialLanguage === "en" ? "us" : initialLanguage
|
144
|
-
|
145
137
|
const sidebar: Record<string, Record<string, string>> = {}
|
146
138
|
for (const slug of slugs) {
|
147
139
|
sidebar[slug] = {
|
148
|
-
[
|
140
|
+
[initialLanguage]: slug,
|
149
141
|
}
|
150
142
|
}
|
151
143
|
|
@@ -208,9 +200,7 @@ const createMultiLangAsset = async (
|
|
208
200
|
for (const lang of availableLangs) {
|
209
201
|
// eslint-disable-next-line no-await-in-loop
|
210
202
|
const indexReadme = await bucket.file(
|
211
|
-
`courses/${courseSlug}/README
|
212
|
-
lang === "us" || lang === "en" ? "md" : `${lang}.md`
|
213
|
-
}`
|
203
|
+
`courses/${courseSlug}/README${getReadmeExtension(lang)}`
|
214
204
|
)
|
215
205
|
// eslint-disable-next-line no-await-in-loop
|
216
206
|
const [indexReadmeContent] = await indexReadme.download()
|
@@ -227,6 +217,11 @@ const createMultiLangAsset = async (
|
|
227
217
|
all_translations
|
228
218
|
)
|
229
219
|
|
220
|
+
if (!asset) {
|
221
|
+
console.log("No se pudo crear el asset, saltando idioma", lang)
|
222
|
+
continue
|
223
|
+
}
|
224
|
+
|
230
225
|
all_translations.push(asset.slug)
|
231
226
|
}
|
232
227
|
}
|
@@ -334,6 +329,8 @@ export default class ServeCommand extends SessionCommand {
|
|
334
329
|
process.exit(1)
|
335
330
|
}
|
336
331
|
|
332
|
+
await api.updateTechnologiesPeriodically()
|
333
|
+
|
337
334
|
const credentials = JSON.parse(crendsEnv)
|
338
335
|
const bucketStorage = new Storage({
|
339
336
|
credentials,
|
@@ -524,15 +521,10 @@ export default class ServeCommand extends SessionCommand {
|
|
524
521
|
const body = req.body
|
525
522
|
|
526
523
|
// Save the file as courses/courseSlug/README.md
|
527
|
-
const filePath = `courses/${courseSlug}/README
|
528
|
-
body.parsed.language_code
|
529
|
-
|
530
|
-
"md" :
|
531
|
-
`${body.parsed.language_code}.md`
|
532
|
-
}`
|
533
|
-
console.log("Saving initial readme to", filePath)
|
524
|
+
const filePath = `courses/${courseSlug}/README${getReadmeExtension(
|
525
|
+
body.parsed.language_code
|
526
|
+
)}`
|
534
527
|
await uploadFileToBucket(bucket, body.parsed.content, filePath)
|
535
|
-
console.log("Initial readme saved to", filePath)
|
536
528
|
|
537
529
|
res.json({ status: "SUCCESS" })
|
538
530
|
}
|
@@ -776,7 +768,9 @@ export default class ServeCommand extends SessionCommand {
|
|
776
768
|
|
777
769
|
const { slug } = req.params
|
778
770
|
const courseSlug = req.query.slug
|
779
|
-
const lang = req.query.lang || "
|
771
|
+
const lang = req.query.lang || "en"
|
772
|
+
|
773
|
+
console.log("LANG", lang)
|
780
774
|
|
781
775
|
if (!courseSlug) {
|
782
776
|
return res.status(400).json({ error: "Missing courseSlug" })
|
@@ -794,21 +788,21 @@ export default class ServeCommand extends SessionCommand {
|
|
794
788
|
return res.status(404).json({ error: "No README files found" })
|
795
789
|
}
|
796
790
|
|
797
|
-
const requestedFilename =
|
798
|
-
lang
|
799
|
-
|
800
|
-
`${basePath}README.${lang}.md`
|
791
|
+
const requestedFilename = `${basePath}README${getReadmeExtension(
|
792
|
+
lang as string
|
793
|
+
)}`
|
801
794
|
|
802
795
|
let selectedFile = readmeFiles.find(f => f === requestedFilename)
|
803
796
|
|
804
797
|
if (!selectedFile) {
|
798
|
+
console.log("No se encontro en ese idioma, devolviendo el primero")
|
805
799
|
selectedFile = readmeFiles[0]
|
806
800
|
console.warn(
|
807
801
|
`Requested README not found for lang '${lang}', using '${selectedFile}'`
|
808
802
|
)
|
809
803
|
}
|
810
804
|
|
811
|
-
let foundLang = "
|
805
|
+
let foundLang = "en"
|
812
806
|
const match = selectedFile.match(/readme(?:\.([a-z]{2}))?\.md$/i)
|
813
807
|
if (match && match[1]) {
|
814
808
|
foundLang = match[1].toLowerCase()
|
@@ -883,9 +877,9 @@ export default class ServeCommand extends SessionCommand {
|
|
883
877
|
|
884
878
|
const courseSlug = query.slug
|
885
879
|
|
886
|
-
const fileName = `courses/${courseSlug}/exercises/${title}/README${
|
887
|
-
language
|
888
|
-
}
|
880
|
+
const fileName = `courses/${courseSlug}/exercises/${title}/README${getReadmeExtension(
|
881
|
+
language
|
882
|
+
)}`
|
889
883
|
const file = bucket.file(fileName)
|
890
884
|
await file.save(readme)
|
891
885
|
const created = await file.exists()
|
@@ -933,11 +927,9 @@ export default class ServeCommand extends SessionCommand {
|
|
933
927
|
try {
|
934
928
|
await Promise.all(
|
935
929
|
exerciseSlugs.map(async (slug: string) => {
|
936
|
-
const readmePath = `courses/${courseSlug}/exercises/${slug}/README${
|
937
|
-
currentLanguage
|
938
|
-
|
939
|
-
`.${currentLanguage}`
|
940
|
-
}.md`
|
930
|
+
const readmePath = `courses/${courseSlug}/exercises/${slug}/README${getReadmeExtension(
|
931
|
+
currentLanguage
|
932
|
+
)}`
|
941
933
|
|
942
934
|
const readme = await bucket.file(readmePath).download()
|
943
935
|
|
@@ -950,12 +942,9 @@ export default class ServeCommand extends SessionCommand {
|
|
950
942
|
})
|
951
943
|
|
952
944
|
const translatedReadme = await bucket.file(
|
953
|
-
`courses/${courseSlug}/exercises/${slug}/README${
|
954
|
-
response.parsed.output_language_code
|
955
|
-
|
956
|
-
"" :
|
957
|
-
`.${response.parsed.output_language_code}`
|
958
|
-
}.md`
|
945
|
+
`courses/${courseSlug}/exercises/${slug}/README${getReadmeExtension(
|
946
|
+
response.parsed.output_language_code
|
947
|
+
)}`
|
959
948
|
)
|
960
949
|
await translatedReadme.save(response.parsed.translation)
|
961
950
|
|
@@ -965,11 +954,6 @@ export default class ServeCommand extends SessionCommand {
|
|
965
954
|
})
|
966
955
|
)
|
967
956
|
|
968
|
-
if (languageCodes.has("en")) {
|
969
|
-
languageCodes.delete("en")
|
970
|
-
languageCodes.add("us")
|
971
|
-
}
|
972
|
-
|
973
957
|
const currentLanguages = Object.keys(courseJson.title)
|
974
958
|
for (const languageCode of currentLanguages) {
|
975
959
|
if (languageCodes.has(languageCode)) {
|
@@ -978,8 +962,6 @@ export default class ServeCommand extends SessionCommand {
|
|
978
962
|
}
|
979
963
|
|
980
964
|
if ([...languageCodes].length > 0) {
|
981
|
-
console.log("TRANSLATING COURSE METADATA", languageCodes)
|
982
|
-
|
983
965
|
const translatedCourseMetadata = await Promise.all(
|
984
966
|
[...languageCodes].map(async languageCode => {
|
985
967
|
const result = await translateCourseMetadata(rigoToken, {
|
@@ -1009,11 +991,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1009
991
|
)
|
1010
992
|
|
1011
993
|
const previewReadme = await bucket.file(
|
1012
|
-
`courses/${courseSlug}/README${
|
1013
|
-
currentLanguage === "us" || currentLanguage === "en" ?
|
1014
|
-
"" :
|
1015
|
-
`.${currentLanguage}`
|
1016
|
-
}.md`
|
994
|
+
`courses/${courseSlug}/README${getReadmeExtension(currentLanguage)}`
|
1017
995
|
)
|
1018
996
|
const [previewReadmeContent] = await previewReadme.download()
|
1019
997
|
const previewReadmeContentString = previewReadmeContent.toString()
|
@@ -1031,11 +1009,9 @@ export default class ServeCommand extends SessionCommand {
|
|
1031
1009
|
|
1032
1010
|
await bucket
|
1033
1011
|
.file(
|
1034
|
-
`courses/${courseSlug}/README${
|
1035
|
-
languageCode
|
1036
|
-
|
1037
|
-
`.${languageCode}`
|
1038
|
-
}.md`
|
1012
|
+
`courses/${courseSlug}/README${getReadmeExtension(
|
1013
|
+
languageCode as string
|
1014
|
+
)}`
|
1039
1015
|
)
|
1040
1016
|
.save(translatedPreviewReadme.parsed.translation)
|
1041
1017
|
})
|
@@ -1434,10 +1410,10 @@ export default class ServeCommand extends SessionCommand {
|
|
1434
1410
|
|
1435
1411
|
const availableLangs = Object.keys(config.title)
|
1436
1412
|
|
1437
|
-
let selectedLang = "
|
1413
|
+
let selectedLang = "en"
|
1438
1414
|
let title = ""
|
1439
|
-
if (availableLangs.includes("
|
1440
|
-
title = config.title.
|
1415
|
+
if (availableLangs.includes("en")) {
|
1416
|
+
title = config.title.en
|
1441
1417
|
} else {
|
1442
1418
|
// Select the first available lang
|
1443
1419
|
title = config.title[availableLangs[0]]
|
package/src/creator/src/App.tsx
CHANGED
@@ -174,7 +174,7 @@ function App() {
|
|
174
174
|
let techs = technologies.filter((t) => t.lang === formState.language)
|
175
175
|
|
176
176
|
if (techs.length === 0) {
|
177
|
-
techs = technologies.filter((t) => t.lang === "
|
177
|
+
techs = technologies.filter((t) => t.lang === "en")
|
178
178
|
}
|
179
179
|
|
180
180
|
const res = await publicInteractiveCreation(
|
@@ -25,7 +25,7 @@ import { Sidebar } from "./Sidebar"
|
|
25
25
|
import Login from "../Login"
|
26
26
|
import { useNavigate } from "react-router"
|
27
27
|
import { ParamsChecker } from "../ParamsChecker"
|
28
|
-
import { randomUUID
|
28
|
+
import { randomUUID } from "../../utils/creatorUtils"
|
29
29
|
import { RIGO_FLOAT_GIF } from "../../utils/constants"
|
30
30
|
import { useTranslation } from "react-i18next"
|
31
31
|
import NotificationListener from "../NotificationListener"
|
@@ -24,6 +24,8 @@ export const publicInteractiveCreation = async (
|
|
24
24
|
"https://9cw5zmww-3000.use2.devtunnels.ms"
|
25
25
|
}/notifications/${randomUID}`
|
26
26
|
|
27
|
+
console.log("WEBHOOK URL to send to Rigo", webhookUrl)
|
28
|
+
|
27
29
|
const response = await axios.post(
|
28
30
|
`${RIGOBOT_HOST}/v1/prompting${
|
29
31
|
publicRequest ? "/public" : ""
|
@@ -18251,28 +18251,31 @@ const d2 = async (e) => {
|
|
18251
18251
|
try {
|
18252
18252
|
const l = Ku(15),
|
18253
18253
|
u = `https://9cw5zmww-3000.use2.devtunnels.ms/notifications/${l}`
|
18254
|
-
return
|
18255
|
-
|
18256
|
-
|
18257
|
-
|
18258
|
-
|
18259
|
-
|
18260
|
-
|
18261
|
-
|
18262
|
-
|
18263
|
-
|
18264
|
-
|
18265
|
-
|
18266
|
-
|
18267
|
-
headers: {
|
18268
|
-
"Content-Type": "application/json",
|
18269
|
-
Authorization: `Token ${t}`,
|
18254
|
+
return (
|
18255
|
+
console.log("WEBHOOK URL to send to Rigo", u),
|
18256
|
+
{
|
18257
|
+
res: (
|
18258
|
+
await Pe.post(
|
18259
|
+
`${Ds}/v1/prompting${r ? "/public" : ""}/completion/${
|
18260
|
+
L1 ? "39" : "390"
|
18261
|
+
}/`,
|
18262
|
+
{
|
18263
|
+
inputs: e,
|
18264
|
+
include_purpose_objective: !0,
|
18265
|
+
purpose_slug: n,
|
18266
|
+
webhook_url: u,
|
18270
18267
|
},
|
18271
|
-
|
18272
|
-
|
18273
|
-
|
18274
|
-
|
18275
|
-
|
18268
|
+
{
|
18269
|
+
headers: {
|
18270
|
+
"Content-Type": "application/json",
|
18271
|
+
Authorization: `Token ${t}`,
|
18272
|
+
},
|
18273
|
+
}
|
18274
|
+
)
|
18275
|
+
).data,
|
18276
|
+
notificationId: l,
|
18277
|
+
}
|
18278
|
+
)
|
18276
18279
|
} catch (l) {
|
18277
18280
|
const u = l
|
18278
18281
|
return (
|
@@ -21192,7 +21195,7 @@ function K7() {
|
|
21192
21195
|
y.rigoToken &&
|
21193
21196
|
l({ ...y, rigoToken: "", bcToken: "", userId: "", user: null })
|
21194
21197
|
let $ = T.filter((ee) => ee.lang === r.language)
|
21195
|
-
$.length === 0 && ($ = T.filter((ee) => ee.lang === "
|
21198
|
+
$.length === 0 && ($ = T.filter((ee) => ee.lang === "en"))
|
21196
21199
|
const Q = await p2(
|
21197
21200
|
{
|
21198
21201
|
courseInfo: `${JSON.stringify(
|
@@ -10,7 +10,7 @@
|
|
10
10
|
/>
|
11
11
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-CFM_Ypyi.js"></script>
|
14
14
|
<link rel="stylesheet" crossorigin href="/creator/assets/index-DmpsXknz.css">
|
15
15
|
</head>
|
16
16
|
<body>
|
@@ -85,15 +85,12 @@ export const exercise = (
|
|
85
85
|
// fs.writeFileSync(path + "/" + file, updatedMarkdown, "utf8")
|
86
86
|
// }
|
87
87
|
|
88
|
-
if (parts.length === 3)
|
89
|
-
translations
|
90
|
-
else
|
91
|
-
translations.us = file
|
88
|
+
if (parts.length === 3) translations[parts[1]] = file
|
89
|
+
else translations.us = file
|
92
90
|
}
|
93
91
|
|
94
92
|
// if the slug is a dot, it means there is not "exercises" folder, and its just a single README.md
|
95
|
-
if (slug === ".")
|
96
|
-
slug = "default-index"
|
93
|
+
if (slug === ".") slug = "default-index"
|
97
94
|
|
98
95
|
const detected = detect(configObject, files)
|
99
96
|
|
@@ -120,16 +117,14 @@ slug = "default-index"
|
|
120
117
|
exercises[position].done :
|
121
118
|
false,
|
122
119
|
getReadme: function (lang = null) {
|
123
|
-
if (lang === "us")
|
124
|
-
lang = null // <-- english is default, no need to append it to the file name
|
120
|
+
if (lang === "en" || lang === "us") lang = null // <-- english is default, no need to append it to the file name
|
125
121
|
|
126
122
|
if (!fs.existsSync(`${this.path}/README${lang ? "." + lang : ""}.md`)) {
|
127
123
|
Console.error(
|
128
124
|
`Language ${lang} not found for exercise ${slug}, switching to default language`
|
129
125
|
)
|
130
126
|
|
131
|
-
if (lang)
|
132
|
-
lang = null
|
127
|
+
if (lang) lang = null
|
133
128
|
|
134
129
|
if (!fs.existsSync(`${this.path}/README${lang ? "." + lang : ""}.md`))
|
135
130
|
throw new Error(
|
@@ -169,8 +164,7 @@ lang = null
|
|
169
164
|
|
170
165
|
for (const _file of this.files) {
|
171
166
|
const stats = fs.statSync(_file.path)
|
172
|
-
if (stats.isDirectory() || _file.hidden)
|
173
|
-
continue
|
167
|
+
if (stats.isDirectory() || _file.hidden) continue
|
174
168
|
const fileContent = fs.readFileSync(_file.path)
|
175
169
|
if (
|
176
170
|
!fs.existsSync(`${config?.dirPath}/resets/${this.slug}/${_file.name}`)
|
@@ -217,8 +211,7 @@ continue
|
|
217
211
|
getTestReport: function () {
|
218
212
|
const _path = `${configObject?.confPath?.base}/reports/${this.slug}.json`
|
219
213
|
|
220
|
-
if (!fs.existsSync(_path))
|
221
|
-
return {}
|
214
|
+
if (!fs.existsSync(_path)) return {}
|
222
215
|
|
223
216
|
const content = fs.readFileSync(_path)
|
224
217
|
const data = JSON.parse(`${content}`)
|
@@ -230,8 +223,7 @@ return {}
|
|
230
223
|
}
|
231
224
|
|
232
225
|
export const validateExerciseDirectoryName = (str: string) => {
|
233
|
-
if (str === "./")
|
234
|
-
return true
|
226
|
+
if (str === "./") return true
|
235
227
|
// TODO: Add nameValidationREgex from the config
|
236
228
|
const regex = /^(\d{2,3}(\.\d{1,2})?-([\dA-Za-z]+(-|_)?)+)$/
|
237
229
|
return regex.test(str)
|
package/src/utils/api.ts
CHANGED
@@ -536,7 +536,7 @@ const updateRigoAssetID = async (
|
|
536
536
|
) => {
|
537
537
|
const url = `${RIGOBOT_HOST}/v1/learnpack/package/${slug}/`
|
538
538
|
const headers = {
|
539
|
-
Authorization:
|
539
|
+
Authorization: "Token " + token.trim(),
|
540
540
|
}
|
541
541
|
try {
|
542
542
|
const response = await axios.put(url, { asset_id }, { headers })
|
@@ -550,7 +550,7 @@ const updateRigoAssetID = async (
|
|
550
550
|
const createRigoPackage = async (token: string, slug: string, config: any) => {
|
551
551
|
const url = `${RIGOBOT_HOST}/v1/learnpack/package`
|
552
552
|
const headers = {
|
553
|
-
Authorization:
|
553
|
+
Authorization: "Token " + token.trim(),
|
554
554
|
}
|
555
555
|
try {
|
556
556
|
const response = await axios.post(url, { slug, config }, { headers })
|
@@ -570,7 +570,7 @@ let technologiesCache: TTechnology[] = []
|
|
570
570
|
|
571
571
|
export const fetchTechnologies = async () => {
|
572
572
|
const BREATHECODE_PERMANENT_TOKEN = process.env.BREATHECODE_PERMANENT_TOKEN
|
573
|
-
const LANGS = ["en", "es"
|
573
|
+
const LANGS = ["en", "es"]
|
574
574
|
|
575
575
|
if (!BREATHECODE_PERMANENT_TOKEN) {
|
576
576
|
throw new Error(
|
@@ -627,8 +627,6 @@ async function updateTechnologiesPeriodically() {
|
|
627
627
|
}
|
628
628
|
}
|
629
629
|
|
630
|
-
updateTechnologiesPeriodically()
|
631
|
-
|
632
630
|
export const getCurrentTechnologies = () => technologiesCache
|
633
631
|
|
634
632
|
export default {
|
@@ -649,4 +647,5 @@ export default {
|
|
649
647
|
updateRigoAssetID,
|
650
648
|
createRigoPackage,
|
651
649
|
getCurrentTechnologies,
|
650
|
+
updateTechnologiesPeriodically,
|
652
651
|
}
|
@@ -59,7 +59,7 @@ export async function buildConfig(
|
|
59
59
|
const fname = parts.pop()!
|
60
60
|
const m = fname.match(/^readme(?:\.([a-z]{2}))?\.md$/i)
|
61
61
|
if (m) {
|
62
|
-
const lang = m[1] || "
|
62
|
+
const lang = m[1] || "en"
|
63
63
|
map[slug].translations[lang] = fname
|
64
64
|
} else {
|
65
65
|
map[slug].files.push({
|
@@ -12,14 +12,14 @@
|
|
12
12
|
"title": {
|
13
13
|
"type": "object",
|
14
14
|
"properties": {
|
15
|
-
"
|
15
|
+
"en": {
|
16
16
|
"type": "string"
|
17
17
|
},
|
18
18
|
"es": {
|
19
19
|
"type": "string"
|
20
20
|
}
|
21
21
|
},
|
22
|
-
"required": ["
|
22
|
+
"required": ["en"]
|
23
23
|
},
|
24
24
|
"repository": {
|
25
25
|
"type": "string",
|
@@ -32,14 +32,14 @@
|
|
32
32
|
"description": {
|
33
33
|
"type": "object",
|
34
34
|
"properties": {
|
35
|
-
"
|
35
|
+
"en": {
|
36
36
|
"type": "string"
|
37
37
|
},
|
38
38
|
"es": {
|
39
39
|
"type": "string"
|
40
40
|
}
|
41
41
|
},
|
42
|
-
"required": ["
|
42
|
+
"required": ["en"]
|
43
43
|
},
|
44
44
|
"duration": {
|
45
45
|
"type": "integer"
|
@@ -96,7 +96,7 @@
|
|
96
96
|
"intro": {
|
97
97
|
"type": "object",
|
98
98
|
"properties": {
|
99
|
-
"
|
99
|
+
"en": {
|
100
100
|
"type": "string",
|
101
101
|
"format": "uri"
|
102
102
|
},
|
@@ -12,14 +12,14 @@
|
|
12
12
|
"title": {
|
13
13
|
"type": "object",
|
14
14
|
"properties": {
|
15
|
-
"
|
15
|
+
"en": {
|
16
16
|
"type": "string"
|
17
17
|
},
|
18
18
|
"es": {
|
19
19
|
"type": "string"
|
20
20
|
}
|
21
21
|
},
|
22
|
-
"required": ["
|
22
|
+
"required": ["en"]
|
23
23
|
},
|
24
24
|
"repository": {
|
25
25
|
"type": "string",
|
@@ -32,14 +32,14 @@
|
|
32
32
|
"description": {
|
33
33
|
"type": "object",
|
34
34
|
"properties": {
|
35
|
-
"
|
35
|
+
"en": {
|
36
36
|
"type": "string"
|
37
37
|
},
|
38
38
|
"es": {
|
39
39
|
"type": "string"
|
40
40
|
}
|
41
41
|
},
|
42
|
-
"required": ["
|
42
|
+
"required": ["en"]
|
43
43
|
},
|
44
44
|
"duration": {
|
45
45
|
"type": "integer"
|
@@ -96,7 +96,7 @@
|
|
96
96
|
"intro": {
|
97
97
|
"type": "object",
|
98
98
|
"properties": {
|
99
|
-
"
|
99
|
+
"en": {
|
100
100
|
"type": "string",
|
101
101
|
"format": "uri"
|
102
102
|
},
|