@learnpack/learnpack 5.0.250 → 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.
@@ -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("us");
312
+ translations.push("en");
313
313
  else {
314
314
  const regexGroups = translationRegex.exec(readmeFile);
315
315
  if (regexGroups)
@@ -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.us || "LearnPack is awesome!";
236
- const title = learnJson.title.us || "LearnPack: Interactive Learning as a Service";
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, "us", res.data.url, "", []);
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)) {
@@ -3,10 +3,7 @@ import { FormState } from "../models/creator";
3
3
  export declare const createLearnJson: (courseInfo: FormState) => {
4
4
  slug: string;
5
5
  title: {
6
- us: string;
7
- } | {
8
6
  [x: string]: string;
9
- us?: undefined;
10
7
  };
11
8
  technologies: string[];
12
9
  difficulty: string;
@@ -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: language === "en" || language === "us" ?
50
- {
51
- us: courseInfo.title,
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 === "en" || language === "us" ? "us" : language]: courseInfo.description,
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
- [language]: slug,
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.${lang === "us" || lang === "en" ? "md" : `${lang}.md`}`);
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
  };
@@ -334,13 +332,8 @@ class ServeCommand extends SessionCommand_1.default {
334
332
  const { courseSlug } = req.params;
335
333
  const body = req.body;
336
334
  // Save the file as courses/courseSlug/README.md
337
- const filePath = `courses/${courseSlug}/README.${body.parsed.language_code === "us" ||
338
- body.parsed.language_code === "en" ?
339
- "md" :
340
- `${body.parsed.language_code}.md`}`;
341
- console.log("Saving initial readme to", filePath);
335
+ const filePath = `courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(body.parsed.language_code)}`;
342
336
  await uploadFileToBucket(bucket, body.parsed.content, filePath);
343
- console.log("Initial readme saved to", filePath);
344
337
  res.json({ status: "SUCCESS" });
345
338
  });
346
339
  app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
@@ -497,7 +490,8 @@ class ServeCommand extends SessionCommand_1.default {
497
490
  console.log("GET /exercise/:slug/readme");
498
491
  const { slug } = req.params;
499
492
  const courseSlug = req.query.slug;
500
- const lang = req.query.lang || "us";
493
+ const lang = req.query.lang || "en";
494
+ console.log("LANG", lang);
501
495
  if (!courseSlug) {
502
496
  return res.status(400).json({ error: "Missing courseSlug" });
503
497
  }
@@ -509,15 +503,14 @@ class ServeCommand extends SessionCommand_1.default {
509
503
  if (readmeFiles.length === 0) {
510
504
  return res.status(404).json({ error: "No README files found" });
511
505
  }
512
- const requestedFilename = lang === "us" || lang === "en" ?
513
- `${basePath}README.md` :
514
- `${basePath}README.${lang}.md`;
506
+ const requestedFilename = `${basePath}README${(0, creatorUtilities_1.getReadmeExtension)(lang)}`;
515
507
  let selectedFile = readmeFiles.find(f => f === requestedFilename);
516
508
  if (!selectedFile) {
509
+ console.log("No se encontro en ese idioma, devolviendo el primero");
517
510
  selectedFile = readmeFiles[0];
518
511
  console.warn(`Requested README not found for lang '${lang}', using '${selectedFile}'`);
519
512
  }
520
- let foundLang = "us";
513
+ let foundLang = "en";
521
514
  const match = selectedFile.match(/readme(?:\.([a-z]{2}))?\.md$/i);
522
515
  if (match && match[1]) {
523
516
  foundLang = match[1].toLowerCase();
@@ -575,7 +568,7 @@ class ServeCommand extends SessionCommand_1.default {
575
568
  .json({ error: "Missing title or readme content" });
576
569
  }
577
570
  const courseSlug = query.slug;
578
- const fileName = `courses/${courseSlug}/exercises/${title}/README${language === "us" || language === "en" ? "" : `.${language}`}.md`;
571
+ const fileName = `courses/${courseSlug}/exercises/${title}/README${(0, creatorUtilities_1.getReadmeExtension)(language)}`;
579
572
  const file = bucket.file(fileName);
580
573
  await file.save(readme);
581
574
  const created = await file.exists();
@@ -614,9 +607,7 @@ class ServeCommand extends SessionCommand_1.default {
614
607
  const languageCodes = new Set();
615
608
  try {
616
609
  await Promise.all(exerciseSlugs.map(async (slug) => {
617
- const readmePath = `courses/${courseSlug}/exercises/${slug}/README${currentLanguage === "us" || currentLanguage === "en" ?
618
- "" :
619
- `.${currentLanguage}`}.md`;
610
+ const readmePath = `courses/${courseSlug}/exercises/${slug}/README${(0, creatorUtilities_1.getReadmeExtension)(currentLanguage)}`;
620
611
  const readme = await bucket.file(readmePath).download();
621
612
  await Promise.all(languagesToTranslate.map(async (language) => {
622
613
  const response = await (0, rigoActions_1.translateExercise)(rigoToken, {
@@ -624,18 +615,11 @@ class ServeCommand extends SessionCommand_1.default {
624
615
  output_language: language,
625
616
  exercise_slug: slug,
626
617
  });
627
- const translatedReadme = await bucket.file(`courses/${courseSlug}/exercises/${slug}/README${response.parsed.output_language_code === "us" ||
628
- response.parsed.output_language_code === "en" ?
629
- "" :
630
- `.${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)}`);
631
619
  await translatedReadme.save(response.parsed.translation);
632
620
  languageCodes.add(response.parsed.output_language_code);
633
621
  }));
634
622
  }));
635
- if (languageCodes.has("en")) {
636
- languageCodes.delete("en");
637
- languageCodes.add("us");
638
- }
639
623
  const currentLanguages = Object.keys(courseJson.title);
640
624
  for (const languageCode of currentLanguages) {
641
625
  if (languageCodes.has(languageCode)) {
@@ -643,7 +627,6 @@ class ServeCommand extends SessionCommand_1.default {
643
627
  }
644
628
  }
645
629
  if ([...languageCodes].length > 0) {
646
- console.log("TRANSLATING COURSE METADATA", languageCodes);
647
630
  const translatedCourseMetadata = await Promise.all([...languageCodes].map(async (languageCode) => {
648
631
  const result = await (0, rigoActions_1.translateCourseMetadata)(rigoToken, {
649
632
  title: courseJson.title[currentLanguage],
@@ -662,9 +645,7 @@ class ServeCommand extends SessionCommand_1.default {
662
645
  metadata.description;
663
646
  }
664
647
  await uploadFileToBucket(bucket, JSON.stringify(courseJson), `courses/${courseSlug}/learn.json`);
665
- const previewReadme = await bucket.file(`courses/${courseSlug}/README${currentLanguage === "us" || currentLanguage === "en" ?
666
- "" :
667
- `.${currentLanguage}`}.md`);
648
+ const previewReadme = await bucket.file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(currentLanguage)}`);
668
649
  const [previewReadmeContent] = await previewReadme.download();
669
650
  const previewReadmeContentString = previewReadmeContent.toString();
670
651
  await Promise.all([...languageCodes].map(async (languageCode) => {
@@ -674,9 +655,7 @@ class ServeCommand extends SessionCommand_1.default {
674
655
  exercise_slug: "preview-readme",
675
656
  });
676
657
  await bucket
677
- .file(`courses/${courseSlug}/README${languageCode === "us" || languageCode === "en" ?
678
- "" :
679
- `.${languageCode}`}.md`)
658
+ .file(`courses/${courseSlug}/README${(0, creatorUtilities_1.getReadmeExtension)(languageCode)}`)
680
659
  .save(translatedPreviewReadme.parsed.translation);
681
660
  }));
682
661
  }
@@ -919,10 +898,10 @@ class ServeCommand extends SessionCommand_1.default {
919
898
  };
920
899
  copyDir(uiSrc, buildRoot);
921
900
  const availableLangs = Object.keys(config.title);
922
- let selectedLang = "us";
901
+ let selectedLang = "en";
923
902
  let title = "";
924
- if (availableLangs.includes("us")) {
925
- title = config.title.us;
903
+ if (availableLangs.includes("en")) {
904
+ title = config.title.en;
926
905
  }
927
906
  else {
928
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
- res: (
18256
- await Pe.post(
18257
- `${Ds}/v1/prompting${r ? "/public" : ""}/completion/${
18258
- L1 ? "39" : "390"
18259
- }/`,
18260
- {
18261
- inputs: e,
18262
- include_purpose_objective: !0,
18263
- purpose_slug: n,
18264
- webhook_url: u,
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
- ).data,
18274
- notificationId: l,
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 === "us"))
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-CZYzWk3G.js"></script>
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.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: `Token ${token.trim()}`,
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: `Token ${token}`,
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", "us"];
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
  }
@@ -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] || "us";
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.250",
4
+ "version": "5.0.252",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -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 = "error"
455
- else if (warnings.length > 0)
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))
@@ -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.us || "LearnPack is awesome!"
350
+ const description = learnJson.description.en || "LearnPack is awesome!"
350
351
  const title =
351
- learnJson.title.us || "LearnPack: Interactive Learning as a Service"
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
- "us",
445
+ "en",
445
446
  res.data.url,
446
447
  "",
447
448
  []
@@ -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 === "en" || language === "us" ?
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 === "en" || language === "us" ? "us" : 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
- [language]: slug,
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
  }
@@ -526,15 +521,10 @@ export default class ServeCommand extends SessionCommand {
526
521
  const body = req.body
527
522
 
528
523
  // Save the file as courses/courseSlug/README.md
529
- const filePath = `courses/${courseSlug}/README.${
530
- body.parsed.language_code === "us" ||
531
- body.parsed.language_code === "en" ?
532
- "md" :
533
- `${body.parsed.language_code}.md`
534
- }`
535
- console.log("Saving initial readme to", filePath)
524
+ const filePath = `courses/${courseSlug}/README${getReadmeExtension(
525
+ body.parsed.language_code
526
+ )}`
536
527
  await uploadFileToBucket(bucket, body.parsed.content, filePath)
537
- console.log("Initial readme saved to", filePath)
538
528
 
539
529
  res.json({ status: "SUCCESS" })
540
530
  }
@@ -778,7 +768,9 @@ export default class ServeCommand extends SessionCommand {
778
768
 
779
769
  const { slug } = req.params
780
770
  const courseSlug = req.query.slug
781
- const lang = req.query.lang || "us"
771
+ const lang = req.query.lang || "en"
772
+
773
+ console.log("LANG", lang)
782
774
 
783
775
  if (!courseSlug) {
784
776
  return res.status(400).json({ error: "Missing courseSlug" })
@@ -796,21 +788,21 @@ export default class ServeCommand extends SessionCommand {
796
788
  return res.status(404).json({ error: "No README files found" })
797
789
  }
798
790
 
799
- const requestedFilename =
800
- lang === "us" || lang === "en" ?
801
- `${basePath}README.md` :
802
- `${basePath}README.${lang}.md`
791
+ const requestedFilename = `${basePath}README${getReadmeExtension(
792
+ lang as string
793
+ )}`
803
794
 
804
795
  let selectedFile = readmeFiles.find(f => f === requestedFilename)
805
796
 
806
797
  if (!selectedFile) {
798
+ console.log("No se encontro en ese idioma, devolviendo el primero")
807
799
  selectedFile = readmeFiles[0]
808
800
  console.warn(
809
801
  `Requested README not found for lang '${lang}', using '${selectedFile}'`
810
802
  )
811
803
  }
812
804
 
813
- let foundLang = "us"
805
+ let foundLang = "en"
814
806
  const match = selectedFile.match(/readme(?:\.([a-z]{2}))?\.md$/i)
815
807
  if (match && match[1]) {
816
808
  foundLang = match[1].toLowerCase()
@@ -885,9 +877,9 @@ export default class ServeCommand extends SessionCommand {
885
877
 
886
878
  const courseSlug = query.slug
887
879
 
888
- const fileName = `courses/${courseSlug}/exercises/${title}/README${
889
- language === "us" || language === "en" ? "" : `.${language}`
890
- }.md`
880
+ const fileName = `courses/${courseSlug}/exercises/${title}/README${getReadmeExtension(
881
+ language
882
+ )}`
891
883
  const file = bucket.file(fileName)
892
884
  await file.save(readme)
893
885
  const created = await file.exists()
@@ -935,11 +927,9 @@ export default class ServeCommand extends SessionCommand {
935
927
  try {
936
928
  await Promise.all(
937
929
  exerciseSlugs.map(async (slug: string) => {
938
- const readmePath = `courses/${courseSlug}/exercises/${slug}/README${
939
- currentLanguage === "us" || currentLanguage === "en" ?
940
- "" :
941
- `.${currentLanguage}`
942
- }.md`
930
+ const readmePath = `courses/${courseSlug}/exercises/${slug}/README${getReadmeExtension(
931
+ currentLanguage
932
+ )}`
943
933
 
944
934
  const readme = await bucket.file(readmePath).download()
945
935
 
@@ -952,12 +942,9 @@ export default class ServeCommand extends SessionCommand {
952
942
  })
953
943
 
954
944
  const translatedReadme = await bucket.file(
955
- `courses/${courseSlug}/exercises/${slug}/README${
956
- response.parsed.output_language_code === "us" ||
957
- response.parsed.output_language_code === "en" ?
958
- "" :
959
- `.${response.parsed.output_language_code}`
960
- }.md`
945
+ `courses/${courseSlug}/exercises/${slug}/README${getReadmeExtension(
946
+ response.parsed.output_language_code
947
+ )}`
961
948
  )
962
949
  await translatedReadme.save(response.parsed.translation)
963
950
 
@@ -967,11 +954,6 @@ export default class ServeCommand extends SessionCommand {
967
954
  })
968
955
  )
969
956
 
970
- if (languageCodes.has("en")) {
971
- languageCodes.delete("en")
972
- languageCodes.add("us")
973
- }
974
-
975
957
  const currentLanguages = Object.keys(courseJson.title)
976
958
  for (const languageCode of currentLanguages) {
977
959
  if (languageCodes.has(languageCode)) {
@@ -980,8 +962,6 @@ export default class ServeCommand extends SessionCommand {
980
962
  }
981
963
 
982
964
  if ([...languageCodes].length > 0) {
983
- console.log("TRANSLATING COURSE METADATA", languageCodes)
984
-
985
965
  const translatedCourseMetadata = await Promise.all(
986
966
  [...languageCodes].map(async languageCode => {
987
967
  const result = await translateCourseMetadata(rigoToken, {
@@ -1011,11 +991,7 @@ export default class ServeCommand extends SessionCommand {
1011
991
  )
1012
992
 
1013
993
  const previewReadme = await bucket.file(
1014
- `courses/${courseSlug}/README${
1015
- currentLanguage === "us" || currentLanguage === "en" ?
1016
- "" :
1017
- `.${currentLanguage}`
1018
- }.md`
994
+ `courses/${courseSlug}/README${getReadmeExtension(currentLanguage)}`
1019
995
  )
1020
996
  const [previewReadmeContent] = await previewReadme.download()
1021
997
  const previewReadmeContentString = previewReadmeContent.toString()
@@ -1033,11 +1009,9 @@ export default class ServeCommand extends SessionCommand {
1033
1009
 
1034
1010
  await bucket
1035
1011
  .file(
1036
- `courses/${courseSlug}/README${
1037
- languageCode === "us" || languageCode === "en" ?
1038
- "" :
1039
- `.${languageCode}`
1040
- }.md`
1012
+ `courses/${courseSlug}/README${getReadmeExtension(
1013
+ languageCode as string
1014
+ )}`
1041
1015
  )
1042
1016
  .save(translatedPreviewReadme.parsed.translation)
1043
1017
  })
@@ -1436,10 +1410,10 @@ export default class ServeCommand extends SessionCommand {
1436
1410
 
1437
1411
  const availableLangs = Object.keys(config.title)
1438
1412
 
1439
- let selectedLang = "us"
1413
+ let selectedLang = "en"
1440
1414
  let title = ""
1441
- if (availableLangs.includes("us")) {
1442
- title = config.title.us
1415
+ if (availableLangs.includes("en")) {
1416
+ title = config.title.en
1443
1417
  } else {
1444
1418
  // Select the first available lang
1445
1419
  title = config.title[availableLangs[0]]
@@ -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 === "us")
177
+ techs = technologies.filter((t) => t.lang === "en")
178
178
  }
179
179
 
180
180
  const res = await publicInteractiveCreation(
@@ -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
- res: (
18256
- await Pe.post(
18257
- `${Ds}/v1/prompting${r ? "/public" : ""}/completion/${
18258
- L1 ? "39" : "390"
18259
- }/`,
18260
- {
18261
- inputs: e,
18262
- include_purpose_objective: !0,
18263
- purpose_slug: n,
18264
- webhook_url: u,
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
- ).data,
18274
- notificationId: l,
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 === "us"))
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-CZYzWk3G.js"></script>
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[parts[1]] = file
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: `Token ${token.trim()}`,
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: `Token ${token}`,
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", "us"]
573
+ const LANGS = ["en", "es"]
574
574
 
575
575
  if (!BREATHECODE_PERMANENT_TOKEN) {
576
576
  throw new Error(
@@ -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] || "us"
62
+ const lang = m[1] || "en"
63
63
  map[slug].translations[lang] = fname
64
64
  } else {
65
65
  map[slug].files.push({
@@ -498,3 +498,7 @@ export const appendAIRules = async () => {
498
498
 
499
499
  return null
500
500
  }
501
+
502
+ export const getReadmeExtension = (language: string) => {
503
+ return language === "en" || language === "us" ? ".md" : `.${language}.md`
504
+ }
@@ -12,14 +12,14 @@
12
12
  "title": {
13
13
  "type": "object",
14
14
  "properties": {
15
- "us": {
15
+ "en": {
16
16
  "type": "string"
17
17
  },
18
18
  "es": {
19
19
  "type": "string"
20
20
  }
21
21
  },
22
- "required": ["us"]
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
- "us": {
35
+ "en": {
36
36
  "type": "string"
37
37
  },
38
38
  "es": {
39
39
  "type": "string"
40
40
  }
41
41
  },
42
- "required": ["us"]
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
- "us": {
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
- "us": {
15
+ "en": {
16
16
  "type": "string"
17
17
  },
18
18
  "es": {
19
19
  "type": "string"
20
20
  }
21
21
  },
22
- "required": ["us"]
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
- "us": {
35
+ "en": {
36
36
  "type": "string"
37
37
  },
38
38
  "es": {
39
39
  "type": "string"
40
40
  }
41
41
  },
42
- "required": ["us"]
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
- "us": {
99
+ "en": {
100
100
  "type": "string",
101
101
  "format": "uri"
102
102
  },