lens-content-processor 0.44.0 → 0.45.0

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.
@@ -1,92 +1,97 @@
1
1
  // src/skill-tree.ts — assembles the skill-tree structure from parsed content.
2
2
  //
3
- // The processor emits relationships (LO ↔ module ↔ course); presentation
4
- // decisions live in the frontend. Cards reference each other by LO id and
5
- // reference domains by slug.
6
- import { parseFrontmatter } from "./parser/frontmatter.js";
3
+ // The processor emits relationships (LO ↔ topic ↔ domain, LO ↔ module ↔
4
+ // course); presentation decisions live in the frontend. Cards reference each
5
+ // other by LO id, topics by slug, and domains by slug.
6
+ import { DOMAIN_METADATA_FILE, fileStem, } from "./parser/domain.js";
7
7
  import { findFileWithExtension } from "./parser/wikilink.js";
8
+ /**
9
+ * Frontmatter tag that lets a course or module show up in the skill tree's
10
+ * "Included in" links. A module inherits it from any course that has it
11
+ * (shown inside that course); a module tagged on its own shows standalone.
12
+ * Untagged modules and courses are left out of `taughtBy` entirely.
13
+ */
14
+ export const SKILL_TREE_VISIBLE_TAG = "visible-in-skilltree";
15
+ /** Kebab-case: apostrophes vanish ("You don't" → "you-dont"), every other
16
+ * non-alphanumeric run becomes one hyphen. */
8
17
  export function slugifyTitle(title) {
9
18
  return title
10
19
  .toLowerCase()
20
+ .replace(/['’]/g, "")
11
21
  .replace(/[^a-z0-9]+/g, "-")
12
22
  .replace(/^-+|-+$/g, "");
13
23
  }
14
- function fileStem(path) {
15
- const base = path.split("/").pop() ?? path;
16
- return base.replace(/\.md$/, "");
17
- }
18
- /** Parse a Domains/ placeholder file: `domain-number:` frontmatter is the
19
- * only content that matters; the title is the filename. */
20
- export function parseDomainFile(content, file) {
24
+ export function buildSkillTree(input) {
21
25
  const errors = [];
22
- const frontmatterResult = parseFrontmatter(content, file);
23
- if (frontmatterResult.error) {
24
- errors.push(frontmatterResult.error);
25
- return { domain: null, errors };
26
- }
27
- const rawNumber = frontmatterResult.frontmatter["domain-number"];
28
- if (typeof rawNumber !== "number" || !Number.isInteger(rawNumber)) {
29
- errors.push({
30
- file,
31
- line: 2,
32
- message: `Domain file must have an integer 'domain-number' field, got: ${JSON.stringify(rawNumber)}`,
33
- suggestion: "Add domain-number: <n> to the frontmatter",
34
- severity: "error",
35
- });
36
- return { domain: null, errors };
37
- }
38
- const rawStart = frontmatterResult.frontmatter["start-stage"];
39
- let startStage;
40
- if (rawStart !== undefined && rawStart !== null) {
41
- if (typeof rawStart === "string" &&
42
- ["beginner", "intermediate", "advanced"].includes(rawStart)) {
43
- startStage = rawStart;
44
- }
45
- else {
26
+ // --- Domains ---
27
+ const numberToDir = new Map();
28
+ const slugToDir = new Map();
29
+ const dirToDomain = new Map();
30
+ const folders = [...input.domainFolders].sort(([a], [b]) => a.localeCompare(b));
31
+ for (const [dir, folder] of folders) {
32
+ const slug = slugifyTitle(folder.title);
33
+ const sameNumber = numberToDir.get(folder.number);
34
+ const sameSlug = slugToDir.get(slug);
35
+ if (sameNumber || sameSlug) {
46
36
  errors.push({
47
- file,
48
- line: 2,
49
- message: `Field 'start-stage' must be beginner, intermediate or advanced, got: ${JSON.stringify(rawStart)}`,
50
- suggestion: "Use start-stage: beginner | intermediate | advanced",
37
+ file: folder.declaredBy,
38
+ line: 1,
39
+ message: sameNumber
40
+ ? `Duplicate domain number ${folder.number}: '${dir}' and '${sameNumber}'`
41
+ : `Duplicate domain '${slug}': '${dir}' and '${sameSlug}' have the same title`,
42
+ suggestion: "Give each domain folder a unique number and title",
51
43
  severity: "error",
52
44
  });
45
+ continue;
53
46
  }
47
+ numberToDir.set(folder.number, dir);
48
+ slugToDir.set(slug, dir);
49
+ dirToDomain.set(dir, {
50
+ slug,
51
+ title: folder.title,
52
+ number: folder.number,
53
+ ...(folder.metadata?.startStage
54
+ ? { startStage: folder.metadata.startStage }
55
+ : {}),
56
+ ...(folder.metadata?.description
57
+ ? { description: folder.metadata.description }
58
+ : {}),
59
+ });
54
60
  }
55
- return {
56
- domain: {
57
- title: fileStem(file),
58
- number: rawNumber,
59
- ...(startStage ? { startStage } : {}),
60
- },
61
- errors,
62
- };
63
- }
64
- export function buildSkillTree(input) {
65
- const errors = [];
66
- // --- Domains ---
67
- const numberToPath = new Map();
68
- const pathToDomain = new Map();
69
- for (const [path, parsed] of input.domainFiles) {
70
- const existing = numberToPath.get(parsed.number);
61
+ const domains = [...dirToDomain.values()].sort((a, b) => a.number - b.number);
62
+ // --- Topics ---
63
+ const pathToTopic = new Map();
64
+ const slugToTopicPath = new Map();
65
+ const topicEntries = [...input.topicFiles].sort(([a], [b]) => a.localeCompare(b));
66
+ for (const [path, parsed] of topicEntries) {
67
+ const domain = dirToDomain.get(parsed.domainDir);
68
+ if (!domain)
69
+ continue; // the folder itself was rejected above
70
+ const slug = slugifyTitle(parsed.title);
71
+ const existing = slugToTopicPath.get(slug);
71
72
  if (existing) {
72
73
  errors.push({
73
74
  file: path,
74
- line: 2,
75
- message: `Duplicate domain-number ${parsed.number} — already used by ${existing}`,
76
- suggestion: "Give each domain file a unique domain-number",
75
+ line: 1,
76
+ message: `Duplicate topic slug '${slug}': '${path}' and '${existing}' have the same title`,
77
+ suggestion: "Topic titles must be unique across all domains — rename one of the files",
77
78
  severity: "error",
78
79
  });
79
80
  continue;
80
81
  }
81
- numberToPath.set(parsed.number, path);
82
- pathToDomain.set(path, {
83
- slug: slugifyTitle(parsed.title),
82
+ slugToTopicPath.set(slug, path);
83
+ pathToTopic.set(path, {
84
+ id: parsed.id,
85
+ slug,
84
86
  title: parsed.title,
85
- number: parsed.number,
86
- ...(parsed.startStage ? { startStage: parsed.startStage } : {}),
87
+ domain: domain.slug,
88
+ ...(parsed.order !== undefined ? { order: parsed.order } : {}),
89
+ ...(parsed.description ? { description: parsed.description } : {}),
87
90
  });
88
91
  }
89
- const domains = [...pathToDomain.values()].sort((a, b) => a.number - b.number);
92
+ const domainNumber = new Map(domains.map((d) => [d.slug, d.number]));
93
+ const topics = [...pathToTopic.values()].sort((a, b) => domainNumber.get(a.domain) - domainNumber.get(b.domain) ||
94
+ compareTopicOrder(a, b));
90
95
  // --- Cards ---
91
96
  // First pass: which LO paths become cards (needed to validate requires
92
97
  // edges — an edge must point at another card, not at an excluded or
@@ -94,38 +99,56 @@ export function buildSkillTree(input) {
94
99
  const cardPaths = new Map();
95
100
  const untriaged = [];
96
101
  for (const [path, lo] of input.learningOutcomes) {
97
- if (lo.domains === undefined) {
102
+ if (lo.topics === undefined) {
98
103
  // Not yet triaged. Reported via skillTree.untriaged (a TODO list for
99
104
  // editors), not as a per-file warning — most LOs were written before
100
105
  // the skill tree existed and blanket warnings would drown /validate.
101
106
  untriaged.push(path);
102
107
  continue;
103
108
  }
104
- if (lo.domains === "none")
109
+ if (lo.topics === "none")
105
110
  continue;
106
111
  cardPaths.set(path, lo);
107
112
  }
108
113
  untriaged.sort();
109
114
  const cards = [];
110
115
  for (const [path, lo] of cardPaths) {
111
- const domainRefs = lo.domains;
116
+ const topicRefs = lo.topics;
117
+ const topicSlugs = [];
112
118
  const domainSlugs = [];
113
- for (const domainRef of domainRefs) {
114
- const domainPath = findFileWithExtension(domainRef.resolvedPath, input.files);
115
- const domain = domainPath ? pathToDomain.get(domainPath) : undefined;
116
- if (!domain) {
119
+ for (const ref of topicRefs) {
120
+ const topicPath = findFileWithExtension(ref.resolvedPath, input.files);
121
+ const topic = topicPath ? pathToTopic.get(topicPath) : undefined;
122
+ if (!topic) {
123
+ const reason = topicPath && fileStem(topicPath) === fileStem(DOMAIN_METADATA_FILE)
124
+ ? "points at a domain's metadata file, not a topic"
125
+ : topicPath
126
+ ? "does not resolve to a topic file inside a numbered domain folder"
127
+ : "does not resolve to a file";
117
128
  errors.push({
118
129
  file: path,
119
130
  line: 2,
120
- message: `Domain link does not resolve to a domain file: ${domainRef.resolvedPath}`,
121
- suggestion: "Check the file name under Domains/",
131
+ message: `'topic' link ${reason}: ${ref.resolvedPath}`,
132
+ suggestion: 'Point at a topic file: topic: "[[../Domains and Topics/<N> <Domain title>/<Topic title>]]"',
122
133
  severity: "error",
123
134
  });
124
135
  continue;
125
136
  }
126
- domainSlugs.push(domain.slug);
137
+ if (topicSlugs.includes(topic.slug)) {
138
+ errors.push({
139
+ file: path,
140
+ line: 2,
141
+ message: `Duplicate 'topic' entry: ${ref.source}`,
142
+ suggestion: "List each topic once",
143
+ severity: "error",
144
+ });
145
+ continue;
146
+ }
147
+ topicSlugs.push(topic.slug);
148
+ if (!domainSlugs.includes(topic.domain))
149
+ domainSlugs.push(topic.domain);
127
150
  }
128
- if (domainSlugs.length === 0)
151
+ if (topicSlugs.length === 0)
129
152
  continue;
130
153
  if (lo.stage === undefined)
131
154
  continue; // already reported by the parser
@@ -149,14 +172,22 @@ export function buildSkillTree(input) {
149
172
  requires.push(target.id);
150
173
  }
151
174
  const taughtBy = [];
152
- for (const modulePath of input.moduleLoRefs.get(path) ?? []) {
175
+ for (const [modulePath, submodules] of input.moduleLoRefs.get(path) ?? []) {
153
176
  const info = input.moduleInfo.get(modulePath);
154
177
  if (!info)
155
178
  continue;
179
+ // moduleCourses already holds only tagged courses.
180
+ const courses = input.moduleCourses.get(info.slug) ?? [];
181
+ if (courses.length === 0 && !info.visible)
182
+ continue;
156
183
  taughtBy.push({
157
184
  moduleSlug: info.slug,
158
185
  moduleTitle: info.title,
159
- courses: input.moduleCourses.get(info.slug) ?? [],
186
+ courses,
187
+ submodules: [...submodules].map(([slug, title]) => ({
188
+ slug: `${info.slug}/${slug}`,
189
+ title,
190
+ })),
160
191
  });
161
192
  }
162
193
  taughtBy.sort((a, b) => a.moduleSlug.localeCompare(b.moduleSlug));
@@ -164,6 +195,8 @@ export function buildSkillTree(input) {
164
195
  id: lo.id,
165
196
  title: fileStem(path),
166
197
  domains: domainSlugs,
198
+ topic: topicSlugs[0],
199
+ topics: topicSlugs,
167
200
  stage: lo.stage,
168
201
  requires,
169
202
  ...(lo.outcomeStatement ? { outcome: lo.outcomeStatement } : {}),
@@ -172,6 +205,11 @@ export function buildSkillTree(input) {
172
205
  });
173
206
  }
174
207
  cards.sort((a, b) => a.title.localeCompare(b.title));
175
- return { skillTree: { domains, cards, untriaged }, errors };
208
+ return { skillTree: { domains, topics, cards, untriaged }, errors };
209
+ }
210
+ /** `order` first (lower wins, absent last), then title. */
211
+ export function compareTopicOrder(a, b) {
212
+ return ((a.order ?? Number.POSITIVE_INFINITY) -
213
+ (b.order ?? Number.POSITIVE_INFINITY) || a.title.localeCompare(b.title));
176
214
  }
177
215
  //# sourceMappingURL=skill-tree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill-tree.js","sourceRoot":"","sources":["../src/skill-tree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-tree.js","sourceRoot":"","sources":["../src/skill-tree.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lens-content-processor",
3
- "version": "0.44.0",
3
+ "version": "0.45.0",
4
4
  "description": "Parser and validator for Lens educational content (Markdown modules, lenses, learning outcomes)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",