@descent-vtt/spec-graph 0.8.0 → 0.9.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/README.md +102 -17
  3. package/dist/cli.d.ts +2 -2
  4. package/dist/cli.js +38 -19
  5. package/dist/cli.js.map +1 -1
  6. package/dist/directives.d.ts +9 -2
  7. package/dist/directives.js +15 -4
  8. package/dist/directives.js.map +1 -1
  9. package/dist/extract.d.ts +1 -1
  10. package/dist/extract.js +50 -16
  11. package/dist/extract.js.map +1 -1
  12. package/dist/glob.d.ts +44 -44
  13. package/dist/glob.js +152 -116
  14. package/dist/glob.js.map +1 -1
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +4 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/lifecycle.js +10 -2
  19. package/dist/lifecycle.js.map +1 -1
  20. package/dist/markdown.d.ts +53 -161
  21. package/dist/markdown.js +42 -864
  22. package/dist/markdown.js.map +1 -1
  23. package/dist/report.d.ts +23 -0
  24. package/dist/report.js +80 -0
  25. package/dist/report.js.map +1 -1
  26. package/dist/rules.js +48 -14
  27. package/dist/rules.js.map +1 -1
  28. package/dist/sections.d.ts +1 -1
  29. package/dist/sections.js +7 -3
  30. package/dist/sections.js.map +1 -1
  31. package/dist/select.d.ts +2 -2
  32. package/dist/select.js +3 -3
  33. package/dist/select.js.map +1 -1
  34. package/dist/source.d.ts +6 -19
  35. package/dist/source.js +4 -70
  36. package/dist/source.js.map +1 -1
  37. package/dist/types.d.ts +23 -3
  38. package/dist/types.js +1 -1
  39. package/dist/types.js.map +1 -1
  40. package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
  41. package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
  42. package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
  43. package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
  44. package/dist/vendor/spec-core/markdown/headings.js +199 -0
  45. package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
  46. package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
  47. package/dist/vendor/spec-core/markdown/index.js +4 -0
  48. package/dist/vendor/spec-core/markdown/index.js.map +1 -0
  49. package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
  50. package/dist/vendor/spec-core/markdown/layout.js +28 -0
  51. package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
  52. package/dist/vendor/spec-core/markdown/links.d.ts +22 -0
  53. package/dist/vendor/spec-core/markdown/links.js +364 -0
  54. package/dist/vendor/spec-core/markdown/links.js.map +1 -0
  55. package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
  56. package/dist/vendor/spec-core/markdown/lists.js +127 -0
  57. package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
  58. package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
  59. package/dist/vendor/spec-core/markdown/scan.js +439 -0
  60. package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
  61. package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
  62. package/dist/vendor/spec-core/markdown/syntax.js +181 -0
  63. package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
  64. package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
  65. package/dist/vendor/spec-core/markdown/tables.js +86 -0
  66. package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
  67. package/dist/vendor/spec-core/markdown/types.d.ts +287 -0
  68. package/dist/vendor/spec-core/markdown/types.js +9 -0
  69. package/dist/vendor/spec-core/markdown/types.js.map +1 -0
  70. package/dist/vendor/spec-core/path/index.d.ts +1 -0
  71. package/dist/vendor/spec-core/path/index.js +2 -0
  72. package/dist/vendor/spec-core/path/index.js.map +1 -0
  73. package/dist/vendor/spec-core/path/posix.d.ts +83 -0
  74. package/dist/vendor/spec-core/path/posix.js +150 -0
  75. package/dist/vendor/spec-core/path/posix.js.map +1 -0
  76. package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
  77. package/dist/vendor/spec-core/pattern/automaton.js +340 -0
  78. package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
  79. package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
  80. package/dist/vendor/spec-core/pattern/charset.js +116 -0
  81. package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
  82. package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
  83. package/dist/vendor/spec-core/pattern/glob.js +481 -0
  84. package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
  85. package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
  86. package/dist/vendor/spec-core/pattern/index.js +4 -0
  87. package/dist/vendor/spec-core/pattern/index.js.map +1 -0
  88. package/dist/{regex.d.ts → vendor/spec-core/pattern/regex.d.ts} +20 -29
  89. package/dist/{regex.js → vendor/spec-core/pattern/regex.js} +40 -49
  90. package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
  91. package/dist/vendor/spec-core/text/index.d.ts +2 -0
  92. package/dist/vendor/spec-core/text/index.js +2 -0
  93. package/dist/vendor/spec-core/text/index.js.map +1 -0
  94. package/dist/vendor/spec-core/text/lines.d.ts +72 -0
  95. package/dist/vendor/spec-core/text/lines.js +156 -0
  96. package/dist/vendor/spec-core/text/lines.js.map +1 -0
  97. package/dist/yaml.d.ts +44 -12
  98. package/dist/yaml.js +115 -206
  99. package/dist/yaml.js.map +1 -1
  100. package/package.json +3 -2
  101. package/src/vendor/spec-core/LICENSE +21 -0
  102. package/src/vendor/spec-core/README.md +8 -0
  103. package/dist/regex.js.map +0 -1
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Lines, offsets and masks.
3
+ *
4
+ * Every finding a spec-* tool reports points at a line and a column, and every
5
+ * structure the scanner builds carries raw offsets rather than copies of the
6
+ * text. Converting between the two is on the hot path, so the line table is
7
+ * built once per file and searched by bisection.
8
+ *
9
+ * All three line terminators end a line - `\n`, `\r\n` and a lone `\r`, as
10
+ * CommonMark has it - and `\r\n` counts once. A Windows checkout of a document
11
+ * must produce the line numbers a POSIX checkout does.
12
+ */
13
+ export interface Position {
14
+ /** UTF-16 offset into the text. */
15
+ readonly offset: number;
16
+ /** 1-based. */
17
+ readonly line: number;
18
+ /** 1-based, in UTF-16 code units. */
19
+ readonly column: number;
20
+ }
21
+ export interface LineIndex {
22
+ /** Number of lines. A final terminator does not open a line of its own. */
23
+ readonly lineCount: number;
24
+ /** Offset at which a 1-based line starts. Out-of-range lines are clamped. */
25
+ lineStart(line: number): number;
26
+ /** Offset just past a 1-based line, before its terminator. */
27
+ lineEnd(line: number): number;
28
+ /** A 1-based line without its terminator. */
29
+ lineText(line: number): string;
30
+ /** The line and column of an offset. Out-of-range offsets are clamped. */
31
+ positionAt(offset: number): Position;
32
+ }
33
+ /** Offsets at which each line starts; index 0 is line 1. */
34
+ export declare function lineStarts(text: string): number[];
35
+ /** Builds the line table for a text. */
36
+ export declare function createLineIndex(text: string): LineIndex;
37
+ /**
38
+ * The line and column of an offset, by bisection over a line table.
39
+ *
40
+ * The search is half-open: `high` is one past the last candidate, and it
41
+ * narrows until one is left. There is no `- 1` to get wrong.
42
+ */
43
+ export declare function locate(starts: readonly number[], offset: number): Position;
44
+ /** A half-open range of offsets. */
45
+ export interface Range {
46
+ readonly start: number;
47
+ readonly end: number;
48
+ }
49
+ /** Sorts and merges ranges; touching ranges merge. Empty ranges vanish. */
50
+ export declare function mergeRanges(ranges: readonly Range[]): Range[];
51
+ /** Whether an offset lies in one of a list of merged, sorted ranges. */
52
+ export declare function inRanges(merged: readonly Range[], offset: number): boolean;
53
+ /**
54
+ * Blanks the given ranges with spaces, keeping every other character and
55
+ * every line terminator where it was.
56
+ *
57
+ * Offsets survive a mask, which is the point: something found at offset 400
58
+ * of the masked text is at offset 400 of the original, on the same line. The
59
+ * replacement walks UTF-16 code units, so a surrogate pair becomes two spaces
60
+ * and every later offset still lands where it did.
61
+ */
62
+ export declare function maskRanges(text: string, ranges: readonly Range[]): string;
63
+ /** A text without a leading byte-order mark. */
64
+ export declare function stripBom(text: string): string;
65
+ /** The terminator a text mostly uses; `\n` when it has none or they tie. */
66
+ export declare function lineEnding(text: string): '\n' | '\r\n';
67
+ /**
68
+ * The lines of a text, without terminators. Unlike the line table, a final
69
+ * terminator does produce a last, empty line, so that joining the lines with
70
+ * the same terminator gives the text back byte for byte.
71
+ */
72
+ export declare function splitLines(text: string): string[];
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Lines, offsets and masks.
3
+ *
4
+ * Every finding a spec-* tool reports points at a line and a column, and every
5
+ * structure the scanner builds carries raw offsets rather than copies of the
6
+ * text. Converting between the two is on the hot path, so the line table is
7
+ * built once per file and searched by bisection.
8
+ *
9
+ * All three line terminators end a line - `\n`, `\r\n` and a lone `\r`, as
10
+ * CommonMark has it - and `\r\n` counts once. A Windows checkout of a document
11
+ * must produce the line numbers a POSIX checkout does.
12
+ */
13
+ const LF = 10;
14
+ const CR = 13;
15
+ /** Offsets at which each line starts; index 0 is line 1. */
16
+ export function lineStarts(text) {
17
+ const starts = [0];
18
+ for (let i = 0; i < text.length; i += 1) {
19
+ const ch = text.charCodeAt(i);
20
+ if (ch === LF) {
21
+ starts.push(i + 1);
22
+ }
23
+ else if (ch === CR) {
24
+ if (text.charCodeAt(i + 1) === LF)
25
+ i += 1;
26
+ starts.push(i + 1);
27
+ }
28
+ }
29
+ // A terminator at the very end opens a line that holds nothing; an editor
30
+ // does not count it, and neither does this.
31
+ if (starts.length > 1 && starts[starts.length - 1] === text.length)
32
+ starts.pop();
33
+ return starts;
34
+ }
35
+ /** Builds the line table for a text. */
36
+ export function createLineIndex(text) {
37
+ const starts = lineStarts(text);
38
+ const lineCount = starts.length;
39
+ const clamp = (line) => (line < 1 ? 1 : line > lineCount ? lineCount : line);
40
+ const startOf = (line) => starts[clamp(line) - 1];
41
+ const endOf = (line) => {
42
+ const index = clamp(line);
43
+ const start = starts[index - 1];
44
+ let end = index === lineCount ? text.length : starts[index];
45
+ // At most two terminator characters, and never past the line's own start.
46
+ if (end > start && text.charCodeAt(end - 1) === LF)
47
+ end -= 1;
48
+ if (end > start && text.charCodeAt(end - 1) === CR)
49
+ end -= 1;
50
+ return end;
51
+ };
52
+ return {
53
+ lineCount,
54
+ lineStart: startOf,
55
+ lineEnd: endOf,
56
+ lineText: (line) => text.slice(startOf(line), endOf(line)),
57
+ positionAt: (offset) => locate(starts, offset < 0 ? 0 : offset > text.length ? text.length : offset),
58
+ };
59
+ }
60
+ /**
61
+ * The line and column of an offset, by bisection over a line table.
62
+ *
63
+ * The search is half-open: `high` is one past the last candidate, and it
64
+ * narrows until one is left. There is no `- 1` to get wrong.
65
+ */
66
+ export function locate(starts, offset) {
67
+ let low = 0;
68
+ let high = starts.length;
69
+ while (high - low > 1) {
70
+ const mid = (low + high) >> 1;
71
+ if (starts[mid] <= offset)
72
+ low = mid;
73
+ else
74
+ high = mid;
75
+ }
76
+ return { offset, line: low + 1, column: offset - starts[low] + 1 };
77
+ }
78
+ /** Sorts and merges ranges; touching ranges merge. Empty ranges vanish. */
79
+ export function mergeRanges(ranges) {
80
+ const sorted = ranges.filter((r) => r.end > r.start).sort((a, b) => a.start - b.start || a.end - b.end);
81
+ const out = [];
82
+ for (const range of sorted) {
83
+ const last = out[out.length - 1];
84
+ if (last !== undefined && range.start <= last.end)
85
+ last.end = Math.max(last.end, range.end);
86
+ else
87
+ out.push({ start: range.start, end: range.end });
88
+ }
89
+ return out;
90
+ }
91
+ /** Whether an offset lies in one of a list of merged, sorted ranges. */
92
+ export function inRanges(merged, offset) {
93
+ let low = 0;
94
+ let high = merged.length;
95
+ while (low < high) {
96
+ const mid = (low + high) >> 1;
97
+ const range = merged[mid];
98
+ if (offset < range.start)
99
+ high = mid;
100
+ else if (offset >= range.end)
101
+ low = mid + 1;
102
+ else
103
+ return true;
104
+ }
105
+ return false;
106
+ }
107
+ const NOT_A_TERMINATOR = /[^\n\r]/g;
108
+ /**
109
+ * Blanks the given ranges with spaces, keeping every other character and
110
+ * every line terminator where it was.
111
+ *
112
+ * Offsets survive a mask, which is the point: something found at offset 400
113
+ * of the masked text is at offset 400 of the original, on the same line. The
114
+ * replacement walks UTF-16 code units, so a surrogate pair becomes two spaces
115
+ * and every later offset still lands where it did.
116
+ */
117
+ export function maskRanges(text, ranges) {
118
+ const merged = mergeRanges(ranges);
119
+ if (merged.length === 0)
120
+ return text;
121
+ let out = '';
122
+ let cursor = 0;
123
+ for (const range of merged) {
124
+ const start = Math.min(range.start, text.length);
125
+ const end = Math.min(range.end, text.length);
126
+ out += text.slice(cursor, start);
127
+ out += text.slice(start, end).replace(NOT_A_TERMINATOR, ' ');
128
+ cursor = end;
129
+ }
130
+ return out + text.slice(cursor);
131
+ }
132
+ /** A text without a leading byte-order mark. */
133
+ export function stripBom(text) {
134
+ return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
135
+ }
136
+ /** The terminator a text mostly uses; `\n` when it has none or they tie. */
137
+ export function lineEnding(text) {
138
+ let crlf = 0;
139
+ let lf = 0;
140
+ for (let i = text.indexOf('\n'); i >= 0; i = text.indexOf('\n', i + 1)) {
141
+ if (i > 0 && text.charCodeAt(i - 1) === CR)
142
+ crlf += 1;
143
+ else
144
+ lf += 1;
145
+ }
146
+ return crlf > lf ? '\r\n' : '\n';
147
+ }
148
+ /**
149
+ * The lines of a text, without terminators. Unlike the line table, a final
150
+ * terminator does produce a last, empty line, so that joining the lines with
151
+ * the same terminator gives the text back byte for byte.
152
+ */
153
+ export function splitLines(text) {
154
+ return text.split(/\r\n|\n|\r/);
155
+ }
156
+ //# sourceMappingURL=lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/text/lines.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Lines, offsets and masks.\n *\n * Every finding a spec-* tool reports points at a line and a column, and every\n * structure the scanner builds carries raw offsets rather than copies of the\n * text. Converting between the two is on the hot path, so the line table is\n * built once per file and searched by bisection.\n *\n * All three line terminators end a line - `\\n`, `\\r\\n` and a lone `\\r`, as\n * CommonMark has it - and `\\r\\n` counts once. A Windows checkout of a document\n * must produce the line numbers a POSIX checkout does.\n */\n\nexport interface Position {\n /** UTF-16 offset into the text. */\n readonly offset: number;\n /** 1-based. */\n readonly line: number;\n /** 1-based, in UTF-16 code units. */\n readonly column: number;\n}\n\nexport interface LineIndex {\n /** Number of lines. A final terminator does not open a line of its own. */\n readonly lineCount: number;\n /** Offset at which a 1-based line starts. Out-of-range lines are clamped. */\n lineStart(line: number): number;\n /** Offset just past a 1-based line, before its terminator. */\n lineEnd(line: number): number;\n /** A 1-based line without its terminator. */\n lineText(line: number): string;\n /** The line and column of an offset. Out-of-range offsets are clamped. */\n positionAt(offset: number): Position;\n}\n\nconst LF = 10;\nconst CR = 13;\n\n/** Offsets at which each line starts; index 0 is line 1. */\nexport function lineStarts(text: string): number[] {\n const starts: number[] = [0];\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charCodeAt(i);\n if (ch === LF) {\n starts.push(i + 1);\n } else if (ch === CR) {\n if (text.charCodeAt(i + 1) === LF) i += 1;\n starts.push(i + 1);\n }\n }\n // A terminator at the very end opens a line that holds nothing; an editor\n // does not count it, and neither does this.\n if (starts.length > 1 && starts[starts.length - 1] === text.length) starts.pop();\n return starts;\n}\n\n/** Builds the line table for a text. */\nexport function createLineIndex(text: string): LineIndex {\n const starts = lineStarts(text);\n const lineCount = starts.length;\n const clamp = (line: number): number => (line < 1 ? 1 : line > lineCount ? lineCount : line);\n const startOf = (line: number): number => starts[clamp(line) - 1] as number;\n const endOf = (line: number): number => {\n const index = clamp(line);\n const start = starts[index - 1] as number;\n let end = index === lineCount ? text.length : (starts[index] as number);\n // At most two terminator characters, and never past the line's own start.\n if (end > start && text.charCodeAt(end - 1) === LF) end -= 1;\n if (end > start && text.charCodeAt(end - 1) === CR) end -= 1;\n return end;\n };\n return {\n lineCount,\n lineStart: startOf,\n lineEnd: endOf,\n lineText: (line) => text.slice(startOf(line), endOf(line)),\n positionAt: (offset) => locate(starts, offset < 0 ? 0 : offset > text.length ? text.length : offset),\n };\n}\n\n/**\n * The line and column of an offset, by bisection over a line table.\n *\n * The search is half-open: `high` is one past the last candidate, and it\n * narrows until one is left. There is no `- 1` to get wrong.\n */\nexport function locate(starts: readonly number[], offset: number): Position {\n let low = 0;\n let high = starts.length;\n while (high - low > 1) {\n const mid = (low + high) >> 1;\n if ((starts[mid] as number) <= offset) low = mid;\n else high = mid;\n }\n return { offset, line: low + 1, column: offset - (starts[low] as number) + 1 };\n}\n\n/** A half-open range of offsets. */\nexport interface Range {\n readonly start: number;\n readonly end: number;\n}\n\n/** Sorts and merges ranges; touching ranges merge. Empty ranges vanish. */\nexport function mergeRanges(ranges: readonly Range[]): Range[] {\n const sorted = ranges.filter((r) => r.end > r.start).sort((a, b) => a.start - b.start || a.end - b.end);\n const out: { start: number; end: number }[] = [];\n for (const range of sorted) {\n const last = out[out.length - 1];\n if (last !== undefined && range.start <= last.end) last.end = Math.max(last.end, range.end);\n else out.push({ start: range.start, end: range.end });\n }\n return out;\n}\n\n/** Whether an offset lies in one of a list of merged, sorted ranges. */\nexport function inRanges(merged: readonly Range[], offset: number): boolean {\n let low = 0;\n let high = merged.length;\n while (low < high) {\n const mid = (low + high) >> 1;\n const range = merged[mid] as Range;\n if (offset < range.start) high = mid;\n else if (offset >= range.end) low = mid + 1;\n else return true;\n }\n return false;\n}\n\nconst NOT_A_TERMINATOR = /[^\\n\\r]/g;\n\n/**\n * Blanks the given ranges with spaces, keeping every other character and\n * every line terminator where it was.\n *\n * Offsets survive a mask, which is the point: something found at offset 400\n * of the masked text is at offset 400 of the original, on the same line. The\n * replacement walks UTF-16 code units, so a surrogate pair becomes two spaces\n * and every later offset still lands where it did.\n */\nexport function maskRanges(text: string, ranges: readonly Range[]): string {\n const merged = mergeRanges(ranges);\n if (merged.length === 0) return text;\n let out = '';\n let cursor = 0;\n for (const range of merged) {\n const start = Math.min(range.start, text.length);\n const end = Math.min(range.end, text.length);\n out += text.slice(cursor, start);\n out += text.slice(start, end).replace(NOT_A_TERMINATOR, ' ');\n cursor = end;\n }\n return out + text.slice(cursor);\n}\n\n/** A text without a leading byte-order mark. */\nexport function stripBom(text: string): string {\n return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n}\n\n/** The terminator a text mostly uses; `\\n` when it has none or they tie. */\nexport function lineEnding(text: string): '\\n' | '\\r\\n' {\n let crlf = 0;\n let lf = 0;\n for (let i = text.indexOf('\\n'); i >= 0; i = text.indexOf('\\n', i + 1)) {\n if (i > 0 && text.charCodeAt(i - 1) === CR) crlf += 1;\n else lf += 1;\n }\n return crlf > lf ? '\\r\\n' : '\\n';\n}\n\n/**\n * The lines of a text, without terminators. Unlike the line table, a final\n * terminator does produce a last, empty line, so that joining the lines with\n * the same terminator gives the text back byte for byte.\n */\nexport function splitLines(text: string): string[] {\n return text.split(/\\r\\n|\\n|\\r/);\n}\n"]}
package/dist/yaml.d.ts CHANGED
@@ -1,17 +1,25 @@
1
1
  /**
2
- * A front-matter reader for the subset of YAML that specifications actually use.
2
+ * What spec-graph reads out of a document's front matter.
3
3
  *
4
- * Front matter in an ADR is a flat bag of scalars and lists. Pulling in a full
5
- * YAML implementation to read `status: accepted` would add a parser with its own
6
- * CVE history, and would still need wrapping to recover the byte offset of the
7
- * value - which is the whole reason we parse it ourselves: when a status is
8
- * wrong, the report has to point at the line that declares it.
4
+ * The reader is spec-core's, copied into `src/vendor/spec-core/markdown/`: the
5
+ * subset of YAML that specifications use - scalars, quoted scalars, inline and
6
+ * block sequences, `#` comments and, as spec-graph reads it, one level of nested
7
+ * mapping flattened to `parent.child` - with the offset of every key and value,
8
+ * because when a status is wrong the report has to point at the line that
9
+ * declares it.
9
10
  *
10
- * Supported: scalars, quoted scalars, inline `[a, b]` sequences, block `- item`
11
- * sequences, one level of nested mapping (flattened to `parent.child`), and `#`
12
- * comments. Anything richer is preserved as the raw scalar text rather than
13
- * being silently mangled.
11
+ * Anything richer is recognised and not guessed at: a value continued on the
12
+ * next line, a plain value holding `: `, a block scalar, an anchor. Such a value
13
+ * is not read, and the reason is a parse problem at the value, so a key that
14
+ * says nothing to the graph says why under `--verbose`. Each problem says
15
+ * whether it left something out and which key, for the count a run prints
16
+ * without `--verbose`.
17
+ *
18
+ * What stays here is the shape the rest of spec-graph reads: a key in lower
19
+ * case, which is how a relation key, a status key and `fm.<key>` in a selector
20
+ * have always been compared, and a value that is a string or a list of them.
14
21
  */
22
+ import type { ScannedDocument } from './markdown.js';
15
23
  export interface YamlEntry {
16
24
  /** Lower-cased key. Nested keys are flattened with a dot. */
17
25
  readonly key: string;
@@ -23,10 +31,34 @@ export interface YamlEntry {
23
31
  /** Offset of the first character of the value, for precise diagnostics. */
24
32
  readonly valueStart: number;
25
33
  }
34
+ /** Something in the front matter that was not read, and where. */
35
+ export interface FrontMatterProblem {
36
+ readonly message: string;
37
+ readonly start: number;
38
+ readonly end: number;
39
+ /**
40
+ * Whether it left something out: a value, a line or the whole block. A key
41
+ * written twice is a problem that leaves nothing out, since the last is read.
42
+ */
43
+ readonly unread: boolean;
44
+ /**
45
+ * The key, lower-cased, whose value or line was left out, when the line
46
+ * names one; `null` for a line that names none and for the whole block.
47
+ */
48
+ readonly key: string | null;
49
+ }
50
+ export interface FrontMatterReading {
51
+ readonly entries: readonly YamlEntry[];
52
+ readonly problems: readonly FrontMatterProblem[];
53
+ }
54
+ /** Reads a scanned document's front matter. */
55
+ export declare function readEntries(scanned: ScannedDocument): FrontMatterReading;
26
56
  /**
27
- * Parses front-matter text.
57
+ * Parses front-matter text: what lies between the delimiters, as
58
+ * `FrontMatter.raw` holds it.
28
59
  *
29
- * @param raw The text between the delimiters.
60
+ * @param raw The text between the delimiters. It cannot hold a line that would
61
+ * close them, as text a scan read between them never does.
30
62
  * @param baseOffset Offset of `raw` within the containing file, so the returned
31
63
  * spans address the file rather than the fragment.
32
64
  */