@learnpack/learnpack 5.0.360 → 5.0.361

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.
@@ -18492,7 +18492,7 @@ function Rae(e, t) {
18492
18492
  return e[1] - t[1];
18493
18493
  }
18494
18494
  function HU(e, t) {
18495
- const a = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(.+)\]$/,
18495
+ const a = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(?!\s*\]?\s*$)(.+?)\s*\]?\s*$/,
18496
18496
  n = e.match(a);
18497
18497
  if (!n) return null;
18498
18498
  const [, r, s, c, h] = n,
@@ -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-GYxGB_X0.js"></script>
13
+ <script type="module" crossorigin src="/creator/assets/index-CqVEKiJR.js"></script>
14
14
  <link rel="stylesheet" crossorigin href="/creator/assets/index-B7s5Nmq8.css">
15
15
  </head>
16
16
  <body>
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.360",
4
+ "version": "5.0.361",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -0,0 +1,101 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { parseLesson } from "./lib";
3
+ import { Lesson } from "../components/LessonItem";
4
+
5
+ describe("parseLesson", () => {
6
+ it("parses a complete step", () => {
7
+ const lesson = parseLesson("01.0 - Income [read: List your income.]", []);
8
+
9
+ expect(lesson).toMatchObject({
10
+ id: "01.0",
11
+ title: "Income",
12
+ type: "READ",
13
+ description: "List your income.",
14
+ });
15
+ });
16
+
17
+ it("accepts a step without the closing bracket", () => {
18
+ const lesson = parseLesson("01.0 - Income [READ: List your income.", []);
19
+
20
+ expect(lesson).toMatchObject({
21
+ id: "01.0",
22
+ title: "Income",
23
+ type: "READ",
24
+ description: "List your income.",
25
+ });
26
+ });
27
+
28
+ it("ignores spaces after the closing bracket", () => {
29
+ const lesson = parseLesson("01.0 - Income [READ: List your income.] ", []);
30
+
31
+ expect(lesson?.description).toBe("List your income.");
32
+ });
33
+
34
+ it("keeps brackets inside the description", () => {
35
+ expect(
36
+ parseLesson("01.0 - Arrays [CODE: Use arr[0] in a loop.]", [])
37
+ ?.description
38
+ ).toBe("Use arr[0] in a loop.");
39
+ expect(
40
+ parseLesson("01.0 - Arrays [CODE: Use arr[0] in a loop.", [])?.description
41
+ ).toBe("Use arr[0] in a loop.");
42
+ });
43
+
44
+ it("keeps brackets inside the title", () => {
45
+ const lesson = parseLesson(
46
+ "01.0 - Arrays [basics] [READ: Learn arrays.",
47
+ []
48
+ );
49
+
50
+ expect(lesson?.title).toBe("Arrays [basics]");
51
+ expect(lesson?.type).toBe("READ");
52
+ });
53
+
54
+ it.each([
55
+ ["01.0 - Income [READ: ]"],
56
+ ["01.0 - Income [READ: ]"],
57
+ ["01.0 - Income [READ:]"],
58
+ ["01.0 - Income [READ: "],
59
+ ["01.0 - Income [READ:"],
60
+ ["01.0 - Income"],
61
+ ["01.0 - Income [READ"],
62
+ ["Income [READ: List your income.]"],
63
+ ])("rejects %j", (input) => {
64
+ expect(parseLesson(input, [])).toBeNull();
65
+ });
66
+
67
+ it("rejects a step with a line break", () => {
68
+ expect(
69
+ parseLesson("01.0 - Income [READ: List\nyour income.]", [])
70
+ ).toBeNull();
71
+ });
72
+
73
+ it("keeps the identity of a previous lesson when the bracket is missing", () => {
74
+ const previous: Lesson[] = [
75
+ {
76
+ id: "01.0",
77
+ uid: "lesson-1",
78
+ title: "Income",
79
+ type: "READ",
80
+ description: "Old description.",
81
+ duration: 7,
82
+ locked: true,
83
+ },
84
+ ];
85
+
86
+ const lesson = parseLesson(
87
+ "01.0 - Income [READ: New description.",
88
+ previous
89
+ );
90
+
91
+ expect(lesson).toEqual({
92
+ id: "01.0",
93
+ uid: "lesson-1",
94
+ title: "Income",
95
+ type: "READ",
96
+ description: "New description.",
97
+ duration: 7,
98
+ locked: true,
99
+ });
100
+ });
101
+ });
@@ -6,7 +6,10 @@ import { randomUUID } from "./creatorUtils";
6
6
  import { Syllabus } from "./store";
7
7
 
8
8
  export function parseLesson(input: string, previous: Lesson[]): Lesson | null {
9
- const pattern = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(.+)\]$/;
9
+ // The closing bracket is optional because the model sometimes drops it, and a
10
+ // step without it would otherwise be lost. Blank descriptions are still rejected.
11
+ const pattern =
12
+ /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(?!\s*\]?\s*$)(.+?)\s*\]?\s*$/;
10
13
  const match = input.match(pattern);
11
14
 
12
15
  if (!match) return null;
@@ -18492,7 +18492,7 @@ function Rae(e, t) {
18492
18492
  return e[1] - t[1];
18493
18493
  }
18494
18494
  function HU(e, t) {
18495
- const a = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(.+)\]$/,
18495
+ const a = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(?!\s*\]?\s*$)(.+?)\s*\]?\s*$/,
18496
18496
  n = e.match(a);
18497
18497
  if (!n) return null;
18498
18498
  const [, r, s, c, h] = n,
@@ -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-GYxGB_X0.js"></script>
13
+ <script type="module" crossorigin src="/creator/assets/index-CqVEKiJR.js"></script>
14
14
  <link rel="stylesheet" crossorigin href="/creator/assets/index-B7s5Nmq8.css">
15
15
  </head>
16
16
  <body>