lens-content-processor 0.82.1 → 0.84.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.
@@ -0,0 +1,45 @@
1
+ import type { ContentError } from "./index.js";
2
+ import { type UuidEntry } from "./validator/uuid.js";
3
+ export type AnswerQuoteForm = "container" | "leaf" | "text";
4
+ export declare const ANSWER_QUOTE_ATTRIBUTES: readonly ["id", "fallback"];
5
+ export interface AnswerQuoteProblem {
6
+ kind: "missing-id" | "invalid-id" | "unknown-attribute" | "malformed";
7
+ /** The attribute name (unknown-attribute), the id (invalid-id) or the attribute text (malformed). */
8
+ detail?: string;
9
+ }
10
+ export interface AnswerQuote {
11
+ form: AnswerQuoteForm;
12
+ /** The directive as written, from its colons to its closing brace. */
13
+ raw: string;
14
+ /** Offset of `raw` in the text, and its 1-based line there. */
15
+ offset: number;
16
+ line: number;
17
+ /** The id as written (a well-formed one is a UUID). */
18
+ id?: string;
19
+ fallback?: string;
20
+ problems: AnswerQuoteProblem[];
21
+ }
22
+ /** A well-formed quote's question id (lowercased) and where it is. */
23
+ export interface AnswerQuoteRef {
24
+ id: string;
25
+ file: string;
26
+ line: number;
27
+ }
28
+ /** Every answer quote in `text`, in text order. Code spans, code blocks and math are skipped. */
29
+ export declare function findAnswerQuotes(text: string): AnswerQuote[];
30
+ /**
31
+ * The per-file check of the answer quotes in `texts`, the authored text
32
+ * fields of a file whose content is `source`, and the refs of its
33
+ * well-formed quotes. A quote not found in `source` came from another file
34
+ * (an embedded question file) and is that file's to report.
35
+ */
36
+ export declare function checkAnswerQuotes(texts: string[], file: string, source: string): {
37
+ errors: ContentError[];
38
+ refs: AnswerQuoteRef[];
39
+ };
40
+ /**
41
+ * The cross-file check: every quoted id names a question, and not a survey
42
+ * question (survey answers are stored per survey, apart from question
43
+ * answers, so a quote cannot show them).
44
+ */
45
+ export declare function answerQuoteErrors(refs: AnswerQuoteRef[], uuidEntries: UuidEntry[]): ContentError[];
@@ -0,0 +1,183 @@
1
+ // src/answer-quotes.ts
2
+ //
3
+ // Answer quotes: course text that shows the learner's own earlier answer to a
4
+ // question, named by the question's id:: (question ids are global,
5
+ // validator/uuid.ts). remark-directive syntax, in three forms:
6
+ //
7
+ // ::answer{id="<uuid>"} leaf, a line of its own
8
+ // :::answer{id="<uuid>"} ... ::: container (the body is ignored)
9
+ // ... :answer{id="<uuid>"} ... text, inside a sentence
10
+ //
11
+ // `fallback="text"` is shown while the learner has no answer. A `[label]` is
12
+ // allowed and ignored. Values may be double-quoted, single-quoted or bare.
13
+ //
14
+ // One parser serves every check: the per-file syntax check here
15
+ // (checkAnswerQuotes), the cross-file "does that question exist" check
16
+ // (answerQuoteErrors, run by wholeContentStep in index.ts) and the course-order
17
+ // check (course-graph.ts).
18
+ import { maskCode } from "./same-page-links.js";
19
+ import { sourceLocator } from "./validator/same-lens-links.js";
20
+ import { isValidUuid } from "./validator/uuid.js";
21
+ export const ANSWER_QUOTE_ATTRIBUTES = ["id", "fallback"];
22
+ // `[label]` and `{attributes}` are both optional; the name must end there.
23
+ const TAIL = String.raw `(?:\[[^\]\n]*\])?(?:\{([^}\n]*)\})?(?![\w-])`;
24
+ const BLOCK = new RegExp(String.raw `^ {0,3}(:{2,})answer${TAIL}[ \t]*$`, "gm");
25
+ const TEXT = new RegExp(String.raw `(?<![\w:]):answer${TAIL}`, "g");
26
+ // One attribute: name, name=value, name="value" or name='value'.
27
+ const ATTRIBUTE = /\s*([^\s="'{}]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`{}]+)))?\s*/y;
28
+ /** id and fallback of an attribute text, and what is wrong with it. */
29
+ function readAttributes(attr) {
30
+ const out = {};
31
+ const problems = [];
32
+ let at = 0;
33
+ const text = attr ?? "";
34
+ while (at < text.length) {
35
+ ATTRIBUTE.lastIndex = at;
36
+ const m = ATTRIBUTE.exec(text);
37
+ if (!m || m[0] === "") {
38
+ problems.push({ kind: "malformed", detail: text.slice(at).trim() });
39
+ break;
40
+ }
41
+ at = ATTRIBUTE.lastIndex;
42
+ const [, key, ...values] = m;
43
+ const value = values.find((v) => v !== undefined);
44
+ if (key === "id" || key === "fallback")
45
+ out[key] = value ?? "";
46
+ else
47
+ problems.push({ kind: "unknown-attribute", detail: key });
48
+ }
49
+ if (!out.id)
50
+ problems.unshift({ kind: "missing-id" });
51
+ else if (!isValidUuid(out.id))
52
+ problems.unshift({ kind: "invalid-id", detail: out.id });
53
+ return { ...out, problems };
54
+ }
55
+ /** Every answer quote in `text`, in text order. Code spans, code blocks and math are skipped. */
56
+ export function findAnswerQuotes(text) {
57
+ if (!text.includes(":answer"))
58
+ return [];
59
+ const masked = maskCode(text);
60
+ const quotes = [];
61
+ const add = (form, m, attr) => {
62
+ const offset = m.index + m[0].indexOf(":");
63
+ const end = m.index + m[0].trimEnd().length;
64
+ quotes.push({
65
+ form,
66
+ raw: text.slice(offset, end),
67
+ offset,
68
+ line: text.slice(0, offset).split("\n").length,
69
+ ...readAttributes(attr),
70
+ });
71
+ };
72
+ for (const m of masked.matchAll(BLOCK))
73
+ add(m[1].length === 2 ? "leaf" : "container", m, m[2]);
74
+ // The lookbehind keeps `::answer` and `:::answer` out of the text form.
75
+ for (const m of masked.matchAll(TEXT))
76
+ add("text", m, m[1]);
77
+ return quotes.sort((a, b) => a.offset - b.offset);
78
+ }
79
+ /**
80
+ * The per-file check of the answer quotes in `texts`, the authored text
81
+ * fields of a file whose content is `source`, and the refs of its
82
+ * well-formed quotes. A quote not found in `source` came from another file
83
+ * (an embedded question file) and is that file's to report.
84
+ */
85
+ export function checkAnswerQuotes(texts, file, source) {
86
+ const errors = [];
87
+ const refs = [];
88
+ if (!source.includes(":answer"))
89
+ return { errors, refs };
90
+ const locate = sourceLocator(source);
91
+ for (const text of texts) {
92
+ for (const quote of findAnswerQuotes(text)) {
93
+ if (!source.includes(quote.raw))
94
+ continue;
95
+ const line = locate(quote.raw);
96
+ const at = { file, line };
97
+ for (const problem of quote.problems) {
98
+ errors.push({ ...at, ...problemError(problem, quote.raw) });
99
+ }
100
+ if (quote.id && isValidUuid(quote.id)) {
101
+ refs.push({ ...at, id: quote.id.toLowerCase() });
102
+ }
103
+ }
104
+ }
105
+ return { errors, refs };
106
+ }
107
+ function problemError(problem, raw) {
108
+ switch (problem.kind) {
109
+ case "missing-id":
110
+ return {
111
+ code: "answer-quote.id-missing",
112
+ severity: "error",
113
+ message: `Answer quote '${raw}' has no id`,
114
+ suggestion: 'Add the id:: of the question whose answer to show: :answer{id="<question id>"}',
115
+ };
116
+ case "invalid-id":
117
+ return {
118
+ code: "answer-quote.id-invalid",
119
+ severity: "error",
120
+ message: `Answer quote id '${problem.detail}' is not a UUID`,
121
+ suggestion: "Copy the id:: of the question whose answer to show",
122
+ };
123
+ case "unknown-attribute":
124
+ return {
125
+ code: "answer-quote.attribute-unknown",
126
+ severity: "warning",
127
+ message: `Unknown attribute '${problem.detail}' on answer quote '${raw}'`,
128
+ suggestion: "An answer quote takes only id and fallback",
129
+ };
130
+ case "malformed":
131
+ return {
132
+ code: "answer-quote.attributes-malformed",
133
+ severity: "warning",
134
+ message: `Cannot read the attributes '${problem.detail}' of answer quote '${raw}'`,
135
+ suggestion: 'Write attributes as name="value": id and fallback',
136
+ };
137
+ }
138
+ }
139
+ /**
140
+ * The cross-file check: every quoted id names a question, and not a survey
141
+ * question (survey answers are stored per survey, apart from question
142
+ * answers, so a quote cannot show them).
143
+ */
144
+ export function answerQuoteErrors(refs, uuidEntries) {
145
+ if (refs.length === 0)
146
+ return [];
147
+ const questions = new Map();
148
+ for (const entry of uuidEntries) {
149
+ const id = entry.uuid.toLowerCase();
150
+ if (!entry.question || questions.has(id))
151
+ continue;
152
+ questions.set(id, entry);
153
+ }
154
+ return refs.flatMap(({ id, file, line }) => {
155
+ const question = questions.get(id);
156
+ if (!question) {
157
+ return [
158
+ {
159
+ file,
160
+ line,
161
+ code: "answer-quote.question-missing",
162
+ severity: "error",
163
+ message: `Quotes an answer to question ${id}, but no question has that id`,
164
+ suggestion: "Copy the id:: of an existing question",
165
+ },
166
+ ];
167
+ }
168
+ if (question.question.context === "survey") {
169
+ return [
170
+ {
171
+ file,
172
+ line,
173
+ code: "answer-quote.survey-question",
174
+ severity: "error",
175
+ message: `Quotes an answer to question ${id}, a survey question (${question.file}): survey answers cannot be quoted`,
176
+ suggestion: "Quote a question of a lens or a test",
177
+ },
178
+ ];
179
+ }
180
+ return [];
181
+ });
182
+ }
183
+ //# sourceMappingURL=answer-quotes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answer-quotes.js","sourceRoot":"","sources":["../src/answer-quotes.ts"],"names":[],"mappings":"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"}
package/dist/cli-steps.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // the per-course checks, and the --defer-urls report. cli.ts and the engine
3
3
  // (engine/assemble.ts) both call these, so the platform's two paths emit the
4
4
  // same output.
5
- import { courseGraphIssues, partnerNameIssues } from "./course-graph.js";
5
+ import { answerQuoteOrderIssues, courseGraphIssues, partnerNameIssues, } from "./course-graph.js";
6
6
  import { dedupeErrors } from "./dedupe-errors.js";
7
7
  import { materializeUrlIssue } from "./validator/url-reachability.js";
8
8
  import { UrlCache } from "./validator/url-cache.js";
@@ -30,7 +30,11 @@ export function courseReachability(build) {
30
30
  */
31
31
  export function courseGraphChecks(files, cache) {
32
32
  try {
33
- return [...courseGraphIssues(files, cache), ...partnerNameIssues(files)];
33
+ return [
34
+ ...courseGraphIssues(files, cache),
35
+ ...partnerNameIssues(files),
36
+ ...answerQuoteOrderIssues(files),
37
+ ];
34
38
  }
35
39
  catch (error) {
36
40
  console.error("courseGraphIssues failed; serving validation without course-graph checks:", error instanceof Error ? error.message : error);
@@ -1 +1 @@
1
- {"version":3,"file":"cli-steps.js","sourceRoot":"","sources":["../src/cli-steps.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,6EAA6E;AAC7E,eAAe;AAIf,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAqC;IAErC,IAAI,CAAC;QACH,OAAO,KAAK,EAAE,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,0EAA0E,EAC1E,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAkC,EAClC,KAAuB;IAEvB,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,2EAA2E,EAC3E,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,OAAO;YACL;gBACE,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,qBAAqB;gBAC3B,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,oCAAoC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aACtG;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,KAAkC,EAClC,KAAuB;IAEvB,OAAO,YAAY,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAsB,EACtB,cAA+B,EAC/B,QAAkB,QAAQ,CAAC,IAAI,EAAE;IAEjC,MAAM,YAAY,GAAmB,EAAE,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,yEAAyE;IACzE,0EAA0E;IAC1E,4BAA4B;IAC5B,OAAO;QACL,SAAS,EAAE,YAAY,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QAC1E,aAAa,EAAE,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;KAChD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cli-steps.js","sourceRoot":"","sources":["../src/cli-steps.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,6EAA6E;AAC7E,eAAe;AAIf,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAqC;IAErC,IAAI,CAAC;QACH,OAAO,KAAK,EAAE,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,0EAA0E,EAC1E,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAkC,EAClC,KAAuB;IAEvB,IAAI,CAAC;QACH,OAAO;YACL,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC;YAClC,GAAG,iBAAiB,CAAC,KAAK,CAAC;YAC3B,GAAG,sBAAsB,CAAC,KAAK,CAAC;SACjC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,2EAA2E,EAC3E,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,OAAO;YACL;gBACE,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,qBAAqB;gBAC3B,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,oCAAoC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aACtG;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,KAAkC,EAClC,KAAuB;IAEvB,OAAO,YAAY,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAsB,EACtB,cAA+B,EAC/B,QAAkB,QAAQ,CAAC,IAAI,EAAE;IAEjC,MAAM,YAAY,GAAmB,EAAE,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,yEAAyE;IACzE,0EAA0E;IAC1E,4BAA4B;IAC5B,OAAO;QACL,SAAS,EAAE,YAAY,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QAC1E,aAAa,EAAE,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;KAChD,CAAC;AACJ,CAAC"}
@@ -4,3 +4,5 @@ import type { FileResultCache } from "./cache.js";
4
4
  * the file and the title pattern it was scanned with. */
5
5
  export declare function courseGraphIssues(input: ReadonlyMap<string, string>, cache?: FileResultCache): ContentError[];
6
6
  export declare function partnerNameIssues(input: ReadonlyMap<string, string>): ContentError[];
7
+ /** Answer quotes whose question a course reaches only later, or never. */
8
+ export declare function answerQuoteOrderIssues(input: ReadonlyMap<string, string>): ContentError[];
@@ -12,6 +12,13 @@
12
12
  // instructions) names a lens the course includes only later, so it assumes
13
13
  // a reading the student has not reached yet. Prose previews are not flagged.
14
14
  //
15
+ // course-graph.quotes-later-answer an answer quote (answer-quotes.ts) shows
16
+ // the learner's answer to a question that the course reaches only later,
17
+ // so the learner sees the fallback text there. Within one file, the
18
+ // question's segment must start above the quote.
19
+ // course-graph.quotes-unreached-answer the same, for a question the course
20
+ // never reaches. A question file embedded in a lens is where that lens is.
21
+ //
15
22
  // course-graph.partner-name-in-tutor-field a course's partner-name appears
16
23
  // in a tutor-facing field of a file the course reaches. A partner is
17
24
  // credited in the course welcome and the Works cited callouts only; a tutor
@@ -34,7 +41,9 @@ import { isContentTextFile } from "./parser/widget.js";
34
41
  import { stripAuthoringMarkup, stripAuthoringMarkupForValidation, } from "./authoring-markup.js";
35
42
  import { buildTagMap, buildTierMap } from "./validator/tier.js";
36
43
  import { inPathOrder } from "./engine/reader.js";
37
- import { ALL_STRUCTURAL_TYPES, MARKDOWN_CONTENT_FIELDS, } from "./parser/sections.js";
44
+ import { ALL_STRUCTURAL_TYPES, EMBED_LINE_PATTERN, MARKDOWN_CONTENT_FIELDS, } from "./parser/sections.js";
45
+ import { findAnswerQuotes } from "./answer-quotes.js";
46
+ import { isValidUuid } from "./validator/uuid.js";
38
47
  function frontmatterTitle(path, content) {
39
48
  const { frontmatter } = parseFrontmatter(stripAuthoringMarkup(content), path);
40
49
  const t = frontmatter.title;
@@ -140,20 +149,30 @@ function courses(files) {
140
149
  }
141
150
  return out;
142
151
  }
143
- /** Files a course reaches, in first-visit (preorder, document-order) sequence. */
144
- function walk(course, files, text) {
152
+ /** Files a course reaches, in first-visit (preorder, document-order) sequence.
153
+ * `marks`, if given, gets for each file the [line, files reached so far] after
154
+ * each of its lines that reached a file. */
155
+ function walk(course, files, text, marks) {
145
156
  const order = new Map();
146
157
  const visit = (path) => {
147
158
  order.set(path, order.size);
148
- for (const line of text(path).split("\n")) {
159
+ text(path)
160
+ .split("\n")
161
+ .forEach((line, i) => {
149
162
  if (!STRUCTURAL.test(line))
150
- continue;
163
+ return;
164
+ const before = order.size;
151
165
  for (const m of line.matchAll(WIKILINK_RE)) {
152
166
  const next = resolve(m[1], path, files);
153
167
  if (next && !order.has(next))
154
168
  visit(next);
155
169
  }
156
- }
170
+ if (marks && order.size > before) {
171
+ if (!marks.has(path))
172
+ marks.set(path, []);
173
+ marks.get(path).push([i + 1, order.size]);
174
+ }
175
+ });
157
176
  };
158
177
  visit(course);
159
178
  return order;
@@ -328,4 +347,122 @@ export function partnerNameIssues(input) {
328
347
  }))
329
348
  .sort(byPlace);
330
349
  }
350
+ // A question's id:: line, as in lenses, question files, tests and :::question blocks.
351
+ const ID_LINE = /^\s*id::\s*["']?([0-9a-f-]{36})["']?\s*$/i;
352
+ const SEGMENT_START = /^\s*(?:#{1,6}\s|:{3,}question\b)/;
353
+ /** Answer quotes whose question a course reaches only later, or never. */
354
+ export function answerQuoteOrderIssues(input) {
355
+ const files = inPathOrder(input); // as in courseGraphIssues
356
+ const quoting = [...files].filter(([p, c]) => isContentTextFile(p) && c.includes(":answer"));
357
+ if (!quoting.length)
358
+ return [];
359
+ const scanned = memoized((p) => scan(p, files.get(p) ?? ""));
360
+ const text = memoized((p) => scanned(p).lines.join("\n"));
361
+ const quotes = memoized((p) => findAnswerQuotes(text(p)).flatMap((q) => {
362
+ const id = q.id?.toLowerCase();
363
+ return id && isValidUuid(id) ? [{ id, line: q.line }] : [];
364
+ }));
365
+ const defs = new Map();
366
+ for (const [p] of quoting)
367
+ for (const q of quotes(p))
368
+ defs.set(q.id, []);
369
+ if (!defs.size)
370
+ return [];
371
+ for (const [p, content] of files) {
372
+ // Survey questions are answer-quote.survey-question's to report
373
+ if (!isContentTextFile(p) || p.startsWith("surveys/"))
374
+ continue;
375
+ const lower = content.toLowerCase();
376
+ if (![...defs.keys()].some((id) => lower.includes(id)))
377
+ continue;
378
+ let start = 1;
379
+ scanned(p).lines.forEach((line, i) => {
380
+ if (SEGMENT_START.test(line))
381
+ start = i + 1;
382
+ const id = line.match(ID_LINE)?.[1].toLowerCase();
383
+ if (id && defs.has(id))
384
+ defs.get(id).push({ file: p, start });
385
+ });
386
+ }
387
+ const found = new Map();
388
+ for (const { path: coursePath, slug } of courses(files)) {
389
+ const marks = new Map();
390
+ const order = walk(coursePath, files, text, marks);
391
+ // How many files the course has reached at a line of a file
392
+ const reachedAt = (file, line) => (marks.get(file) ?? []).filter(([l]) => l < line).at(-1)?.[1] ??
393
+ order.get(file) + 1;
394
+ // A question file embedded in a lens is met where that lens embeds it.
395
+ const embeddedAt = new Map();
396
+ for (const [file, idx] of [...order]) {
397
+ text(file)
398
+ .split("\n")
399
+ .forEach((line, i) => {
400
+ if (!EMBED_LINE_PATTERN.test(line))
401
+ return;
402
+ for (const m of line.matchAll(WIKILINK_RE)) {
403
+ const embedded = resolve(m[1], file, files);
404
+ if (!embedded || order.has(embedded))
405
+ continue;
406
+ order.set(embedded, idx);
407
+ embeddedAt.set(embedded, { file, line: i + 1 });
408
+ }
409
+ });
410
+ }
411
+ for (const file of order.keys()) {
412
+ if (!isContentTextFile(file))
413
+ continue;
414
+ for (const { id, line } of quotes(file)) {
415
+ const all = defs.get(id);
416
+ if (!all.length)
417
+ continue; // no question: answer-quote.question-missing
418
+ const reached = all.filter((d) => order.has(d.file));
419
+ const before = reached.some((d) => {
420
+ const at = embeddedAt.get(d.file) ?? { file: d.file, line: d.start };
421
+ return at.file === file
422
+ ? at.line <= line
423
+ : order.get(at.file) < reachedAt(file, line);
424
+ });
425
+ if (before)
426
+ continue;
427
+ const kind = reached.length ? "later" : "never";
428
+ const key = `${file}|${id}|${kind}`;
429
+ const rec = found.get(key) ?? {
430
+ kind,
431
+ file,
432
+ line,
433
+ id,
434
+ courses: new Set(),
435
+ };
436
+ rec.courses.add(slug);
437
+ found.set(key, rec);
438
+ }
439
+ }
440
+ }
441
+ if (!found.size)
442
+ return [];
443
+ const tier = buildTierMap(buildTagMap(files));
444
+ return [...found.values()]
445
+ .map((r) => {
446
+ const where = [...new Set(defs.get(r.id).map((d) => d.file))].join(" or ");
447
+ const courses = `course${r.courses.size > 1 ? "s" : ""} ${[...r.courses].sort().join(", ")}`;
448
+ return {
449
+ file: r.file,
450
+ line: r.line,
451
+ severity: "warning",
452
+ category: tier.get(r.file) === "wip" ? "wip" : "production",
453
+ ...(r.kind === "never"
454
+ ? {
455
+ code: "course-graph.quotes-unreached-answer",
456
+ message: `Quotes the answer to question ${r.id} (${where}), which ${courses} never include, so the student cannot have answered it`,
457
+ suggestion: "Add that question to the course, or quote a question the course includes",
458
+ }
459
+ : {
460
+ code: "course-graph.quotes-later-answer",
461
+ message: `Quotes the answer to question ${r.id} (${where}), which ${courses} only include later, so the student has not answered it yet at this point`,
462
+ suggestion: "Move the question before this text, or quote a question the student has already answered",
463
+ }),
464
+ };
465
+ })
466
+ .sort(byPlace);
467
+ }
331
468
  //# sourceMappingURL=course-graph.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"course-graph.js","sourceRoot":"","sources":["../src/course-graph.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,EAAE;AACF,iFAAiF;AACjF,6EAA6E;AAC7E,gFAAgF;AAChF,gFAAgF;AAChF,qBAAqB;AACrB,yEAAyE;AACzE,+EAA+E;AAC/E,iFAAiF;AACjF,EAAE;AACF,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,2EAA2E;AAC3E,gCAAgC;AAChC,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,uEAAuE;AACvE,0CAA0C;AAC1C,iEAAiE;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC,OAAO,EAAE,WAAW,EAAE,gBAAgB,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,iCAAiC,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAqB,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,SAAS,gBAAgB,CAAC,IAAY,EAAE,OAAe;IACrD,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAgB,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC;IAC5B,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,OAAO,IAAI;SACR,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;SAC3B,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,2FAA2F;AAC3F,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,yBAAyB;IACzB,uBAAuB;IACvB,cAAc;IACd,iBAAiB;IACjB,mBAAmB;CACpB,CAAC,CAAC;AAEH;;;;4EAI4E;AAC5E,SAAS,YAAY,CAAC,KAAe;IACnC,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,uEAAuE;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GACT,KAAK,KAAK,KAAK;QACb,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,KAAK,KAAK,qBAAqB;YAC/B,CAAC,CAAC,sBAAsB;YACxB,CAAC,CAAC,IAAI,CAAC;IACb,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACxB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/D,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM;YAAE,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACvD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACjE,MAAM,WAAW,GACf,KAAK,KAAK,IAAI;gBACd,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC;gBAClC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC;gBACtB,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,WAAW;gBAAE,KAAK,GAAG,IAAI,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;QACtD,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAID;;+DAE+D;AAC/D,SAAS,IAAI,CAAC,IAAY,EAAE,OAAe;IACzC,wEAAwE;IACxE,MAAM,GAAG,GAAG,iCAAiC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAC9B,MAAM,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAClE,CAAC;IACF,IAAI,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,GAAG,IAAI,CAAC;YAAE,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,yEAAyE;AACzE,oEAAoE;AACpE,MAAM,UAAU,GAAG,4BAA4B,CAAC;AAEhD,SAAS,QAAQ,CAAI,CAAmB;IACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAa,CAAC;IAClC,OAAO,CAAC,CAAC,EAAE,EAAE;QACX,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC;AAED,uCAAuC;AACvC,SAAS,OAAO,CAAC,CAAe,EAAE,CAAe;IAC/C,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,gEAAgE;AAChE,SAAS,OAAO,CACd,KAAkC;IAElC,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QAC3C,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAgB,CACtC,oBAAoB,CAAC,OAAO,CAAC,EAC7B,IAAI,CACL,CAAC;QACF,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;QAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;YACzC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kFAAkF;AAClF,SAAS,IAAI,CACX,MAAc,EACd,KAAmB,EACnB,IAA2B;IAE3B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE;QAC7B,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YACrC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;gBACxC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC;AAED;wCACwC;AACxC,SAAS,UAAU,CACjB,KAAkC;IAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK;QACxB,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAS;QAC7D,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QACxC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAAE,SAAS;QAChE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED;yDACyD;AACzD,MAAM,UAAU,iBAAiB,CAC/B,KAAkC,EAClC,KAAuB;IAEvB,0EAA0E;IAC1E,sDAAsD;IACtD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAChC,sEAAsE;QACtE,oEAAoE;SACnE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACnE,GAAG,CAAC,MAAM,CAAC;SACX,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,gBAAgB,OAAO,YAAY,EAAE,GAAG,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAG1D,MAAM,YAAY,GAAG,CAAC,IAAY,EAAa,EAAE;QAC/C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAC/B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC/C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACtC,IAAI,EAAE,CAAC,GAAG,CAAC;gBACX,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;gBACX,WAAW,EAAE,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aAC/C,CAAC,CAAC,CACR,CAAC;IACJ,CAAC,CAAC;IACF,+EAA+E;IAC/E,MAAM,YAAY,GAAG,yBAAyB,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1G,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAa,EAAE;QAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAY,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;QACnC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAQH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;IAEvC,KAAK,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC;YAChC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;gBAAE,SAAS;YACvE,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC;gBAClC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACpC,MAAM,OAAO,GAAG,MAAM;qBACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;qBACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;gBAClC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7D,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;oBAAE,SAAS;gBAC7D,MAAM,IAAI,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;gBAClD,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBACvC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;oBAC5B,IAAI;oBACJ,IAAI;oBACJ,KAAK;oBACL,IAAI;oBACJ,OAAO,EAAE,IAAI,GAAG,EAAU;iBAC3B,CAAC;gBACF,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC,EAAgB,EAAE;QACvB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7F,OAAO;YACL,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY;YAC3D,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO;gBACpB,CAAC,CAAC;oBACE,IAAI,EAAE,mCAAmC;oBACzC,OAAO,EAAE,aAAa,CAAC,CAAC,KAAK,MAAM,IAAI,kBAAkB,OAAO,mDAAmD;oBACnH,UAAU,EACR,6FAA6F;iBAChG;gBACH,CAAC,CAAC;oBACE,IAAI,EAAE,+BAA+B;oBACrC,OAAO,EAAE,+BAA+B,CAAC,CAAC,KAAK,MAAM,IAAI,YAAY,OAAO,uEAAuE;oBACnJ,UAAU,EACR,6EAA6E;iBAChF,CAAC;SACP,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAkC;IAElC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,0BAA0B;IAC5D,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,kEAAkE;IAClE,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE;QAChC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAC/B,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC,CAAC;gBACE;oBACE,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,iCAAiC,EAAE,IAAI,CAAC;iBAC5D;aACF;YACH,CAAC,CAAC,EAAE,CACP,CAAC;IACJ,CAAC,CAAC,CAAC;IAOH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,MAAM,GAAG,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,aAAa,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACtE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAClD,IACE,IAAI,KAAK,IAAI;gBACb,CAAC,iBAAiB,CAAC,IAAI,CAAC;gBACxB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;gBAE5B,SAAS;YACX,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;oBAAE,SAAS;gBAC/B,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;gBACvE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC,EAAgB,EAAE,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY;QAC3D,IAAI,EAAE,0CAA0C;QAChD,OAAO,EAAE,4BAA4B,CAAC,CAAC,IAAI,2BAA2B,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACzI,UAAU,EACR,kIAAkI;KACrI,CAAC,CAAC;SACF,IAAI,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"course-graph.js","sourceRoot":"","sources":["../src/course-graph.ts"],"names":[],"mappings":"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"}
@@ -425,6 +425,9 @@ export function flattenModule(modulePath, files, visitedPaths = new Set(), tierM
425
425
  errors.push(...result.errors);
426
426
  return { sections: result.sections, outcome: result.outcome };
427
427
  }
428
+ else if (section.type === "choose") {
429
+ return { sections: flattenChoose(section) };
430
+ }
428
431
  else if (section.type === "lens") {
429
432
  // Referenced lens (has source::) or inline lens
430
433
  const sectionVisitedPaths = new Set(visitedPaths);
@@ -434,6 +437,65 @@ export function flattenModule(modulePath, files, visitedPaths = new Set(), tierM
434
437
  }
435
438
  return { sections: [] };
436
439
  }
440
+ // `# Choose: k` (or `# Choose: k of n`): the path splits into the lenses
441
+ // one level down, and the learner completes k of them. Each member is an
442
+ // ordinary lens section that also carries `choice` (and optional: true, see
443
+ // Section.choice); the group ends at the next heading of its own level.
444
+ let chooseCount = 0;
445
+ function flattenChoose(section) {
446
+ const header = `${"#".repeat(section.level)} Choose: ${section.title}`;
447
+ const fail = (line, message, suggestion, severity = "error") => errors.push({ file: modulePath, line, message, suggestion, severity });
448
+ const members = [];
449
+ let size = 0;
450
+ for (const child of section.children ?? []) {
451
+ placeRefused(child.line);
452
+ if (child.type !== "lens") {
453
+ fail(child.line, child.type === "choose"
454
+ ? `'${header}' holds another Choose group; groups cannot be nested`
455
+ : `'${header}' can hold only lenses, not '${child.rawType}'`, `Put each option under '${"#".repeat(section.level + 1)} Lens:', or move it out of the group`);
456
+ continue;
457
+ }
458
+ size++;
459
+ const fields = { ...child.fields };
460
+ for (const field of ["optional", "hide"]) {
461
+ if (fields[field] === undefined)
462
+ continue;
463
+ fail(child.fieldLines?.[field] ?? child.line, `${field}:: on a lens in a Choose group is not allowed`, `Remove ${field}::; the group decides how many of its lenses the learner completes`);
464
+ delete fields[field];
465
+ }
466
+ members.push(...processSection({ ...child, fields }).sections);
467
+ }
468
+ if (size === 0) {
469
+ fail(section.line, `'${header}' holds no lenses`, `Put the options one level down, as '${"#".repeat(section.level + 1)} Lens:' sections`);
470
+ return members;
471
+ }
472
+ const match = section.title.trim().match(/^(\d+)(?:\s+of\s+(\d+))?$/i);
473
+ let pick = match ? Number(match[1]) : 1;
474
+ if (!match) {
475
+ fail(section.line, `'${header}' must say how many lenses to pick`, "Write '# Choose: 1', or '# Choose: 2 of 3'");
476
+ }
477
+ else if (match[2] !== undefined && Number(match[2]) !== size) {
478
+ fail(section.line, `'${header}' says ${match[2]} lenses, but the group holds ${size}`, `Write '${"#".repeat(section.level)} Choose: ${pick} of ${size}', or add or remove lenses`);
479
+ }
480
+ if (pick < 1 || pick > size) {
481
+ fail(section.line, `'${header}' asks for ${pick} of ${size} lenses`, `Pick at least 1 and at most ${size}`);
482
+ pick = Math.min(Math.max(pick, 1), size);
483
+ }
484
+ if (pick === size) {
485
+ if (match && Number(match[1]) === size) {
486
+ fail(section.line, `'${header}' picks every lens in the group, so all of them are required`, "Remove the Choose header and list the lenses as plain lenses", "warning");
487
+ }
488
+ return members;
489
+ }
490
+ const choice = { id: `choice-${++chooseCount}`, pick, size };
491
+ for (const member of members) {
492
+ if (!isBuilt(member))
493
+ continue;
494
+ member.optional = true;
495
+ member.choice = choice;
496
+ }
497
+ return members;
498
+ }
437
499
  // Which outcomes a lens serves is decided by the module, not the lens: a
438
500
  // lens belongs to every outcome imported in the same submodule (or at
439
501
  // module level, which spans every submodule) whose suggested lenses include
@@ -541,7 +603,7 @@ export function flattenModule(modulePath, files, visitedPaths = new Set(), tierM
541
603
  stashModuleLevelLo(section);
542
604
  }
543
605
  else {
544
- if (section.type === "lens")
606
+ if (section.type === "lens" || section.type === "choose")
545
607
  seenLens = true;
546
608
  const { sections, outcome } = processSection(section);
547
609
  recordOutcome(outcome, false);
@@ -683,6 +745,14 @@ export function declaredSections(parsedModule, modulePath, files) {
683
745
  return findFileWithExtension(resolved, files) ?? resolved;
684
746
  };
685
747
  const declare = (section, page) => {
748
+ if (section.type === "choose") {
749
+ // Only its lenses build (flattenChoose refuses anything else)
750
+ for (const child of section.children ?? []) {
751
+ if (child.type === "lens")
752
+ declare(child, page);
753
+ }
754
+ return;
755
+ }
686
756
  const sourcePath = pathOf(section.fields.source);
687
757
  const own = sourcePath === modulePath;
688
758
  if (section.type === "lens") {