@refrakt-md/runes 0.36.0 → 0.37.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 (63) hide show
  1. package/dist/file-ref-resolve.d.ts.map +1 -1
  2. package/dist/file-ref-resolve.js +36 -1
  3. package/dist/file-ref-resolve.js.map +1 -1
  4. package/dist/index.d.ts +11 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +13 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/lang-map.d.ts.map +1 -1
  9. package/dist/lang-map.js +8 -0
  10. package/dist/lang-map.js.map +1 -1
  11. package/dist/lib/anchor.d.ts +73 -0
  12. package/dist/lib/anchor.d.ts.map +1 -0
  13. package/dist/lib/anchor.js +521 -0
  14. package/dist/lib/anchor.js.map +1 -0
  15. package/dist/lib/component.d.ts +1 -1
  16. package/dist/lib/component.d.ts.map +1 -1
  17. package/dist/lib/invocation.d.ts +22 -0
  18. package/dist/lib/invocation.d.ts.map +1 -0
  19. package/dist/lib/invocation.js +67 -0
  20. package/dist/lib/invocation.js.map +1 -0
  21. package/dist/lib/languages.d.ts +163 -0
  22. package/dist/lib/languages.d.ts.map +1 -0
  23. package/dist/lib/languages.js +383 -0
  24. package/dist/lib/languages.js.map +1 -0
  25. package/dist/lib/line-diff.d.ts +35 -0
  26. package/dist/lib/line-diff.d.ts.map +1 -0
  27. package/dist/lib/line-diff.js +77 -0
  28. package/dist/lib/line-diff.js.map +1 -0
  29. package/dist/lib/mask.d.ts +116 -0
  30. package/dist/lib/mask.d.ts.map +1 -0
  31. package/dist/lib/mask.js +378 -0
  32. package/dist/lib/mask.js.map +1 -0
  33. package/dist/lib/node.d.ts +1 -1
  34. package/dist/lib/node.d.ts.map +1 -1
  35. package/dist/lib/present.d.ts +73 -0
  36. package/dist/lib/present.d.ts.map +1 -0
  37. package/dist/lib/present.js +127 -0
  38. package/dist/lib/present.js.map +1 -0
  39. package/dist/lib/read-file.d.ts +21 -1
  40. package/dist/lib/read-file.d.ts.map +1 -1
  41. package/dist/lib/read-file.js +46 -0
  42. package/dist/lib/read-file.js.map +1 -1
  43. package/dist/lib/renderable.d.ts +7 -3
  44. package/dist/lib/renderable.d.ts.map +1 -1
  45. package/dist/lib/renderable.js +2 -2
  46. package/dist/lib/renderable.js.map +1 -1
  47. package/dist/lib/review-marker.d.ts +113 -0
  48. package/dist/lib/review-marker.d.ts.map +1 -0
  49. package/dist/lib/review-marker.js +173 -0
  50. package/dist/lib/review-marker.js.map +1 -0
  51. package/dist/snippet-pipeline.d.ts.map +1 -1
  52. package/dist/snippet-pipeline.js +70 -2
  53. package/dist/snippet-pipeline.js.map +1 -1
  54. package/dist/tags/diff.d.ts.map +1 -1
  55. package/dist/tags/diff.js +1 -38
  56. package/dist/tags/diff.js.map +1 -1
  57. package/dist/tags/file-ref.d.ts.map +1 -1
  58. package/dist/tags/file-ref.js +59 -1
  59. package/dist/tags/file-ref.js.map +1 -1
  60. package/dist/tags/snippet.d.ts.map +1 -1
  61. package/dist/tags/snippet.js +53 -2
  62. package/dist/tags/snippet.js.map +1 -1
  63. package/package.json +3 -3
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Line-level LCS diff.
3
+ *
4
+ * Extracted from `tags/diff.ts` (WORK-592), where it was module-local, so that
5
+ * both the `diff` rune and the `snippet review` terminal renderer read one
6
+ * implementation. A pure move: the algorithm is unchanged.
7
+ */
8
+ /**
9
+ * Compute a line-level diff using LCS (Longest Common Subsequence).
10
+ *
11
+ * Returns hunks with type and raw text. Presentation — highlighting, gutters,
12
+ * terminal colour — is the caller's.
13
+ */
14
+ export function computeLineDiff(before, after) {
15
+ const a = before.split('\n');
16
+ const b = after.split('\n');
17
+ // Build LCS table
18
+ const m = a.length;
19
+ const n = b.length;
20
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
21
+ for (let i = 1; i <= m; i++) {
22
+ for (let j = 1; j <= n; j++) {
23
+ dp[i][j] =
24
+ a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);
25
+ }
26
+ }
27
+ // Backtrack to produce hunks
28
+ let i = m;
29
+ let j = n;
30
+ const stack = [];
31
+ while (i > 0 || j > 0) {
32
+ if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {
33
+ stack.push({ type: 'equal', text: a[i - 1] });
34
+ i--;
35
+ j--;
36
+ }
37
+ else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
38
+ stack.push({ type: 'add', text: b[j - 1] });
39
+ j--;
40
+ }
41
+ else {
42
+ stack.push({ type: 'remove', text: a[i - 1] });
43
+ i--;
44
+ }
45
+ }
46
+ stack.reverse();
47
+ return stack;
48
+ }
49
+ /**
50
+ * A one-line summary of what changed between two slices.
51
+ *
52
+ * D7's example reads "+2 fields, 1 removed", which requires *interpreting* the
53
+ * diff rather than reporting it. The spec left the granularity open; this is
54
+ * the settled answer, and the reasoning is recorded because it was a real
55
+ * choice:
56
+ *
57
+ * Counting added and removed lines is cheap and honest. Naming *fields* would
58
+ * mean parsing the slice, which needs a language-aware layer this feature does
59
+ * not have and SPEC-131 D1 deliberately declined to build. A count that says
60
+ * "3 added, 1 removed" tells an author how much to expect; a count that claimed
61
+ * "2 fields" while actually counting lines would be worse than the cheap
62
+ * version, because it would sound authoritative.
63
+ */
64
+ export function summarizeDiff(before, after) {
65
+ const hunks = computeLineDiff(before, after);
66
+ const added = hunks.filter((h) => h.type === 'add').length;
67
+ const removed = hunks.filter((h) => h.type === 'remove').length;
68
+ if (added === 0 && removed === 0)
69
+ return 'no line changes';
70
+ const parts = [];
71
+ if (added > 0)
72
+ parts.push(`+${added} line${added === 1 ? '' : 's'}`);
73
+ if (removed > 0)
74
+ parts.push(`-${removed} line${removed === 1 ? '' : 's'}`);
75
+ return parts.join(', ');
76
+ }
77
+ //# sourceMappingURL=line-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-diff.js","sourceRoot":"","sources":["../../src/lib/line-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The masker (SPEC-131 step 1, WORK-597).
3
+ *
4
+ * Blanks comments and string/template literals so that delimiter counting is
5
+ * safe, **preserving newlines** so the masked text has the same line count and
6
+ * the same line offsets as its input. Every later stage of the resolver reads
7
+ * positions off one and applies them to the other, so that correspondence is
8
+ * the module's central invariant, not an implementation detail.
9
+ *
10
+ * This is a lexer, not a parser. It has no per-language branching: every
11
+ * prefix, delimiter and escape it recognises comes from the table in
12
+ * `languages.ts` (D15). A language absent from that table is returned
13
+ * unchanged — the conservative answer, since a guessed mask blanks real code.
14
+ *
15
+ * **Anchors match raw source; the mask only rejects.** SPEC-131 is explicit
16
+ * that matching against masked text would blank every string literal, so
17
+ * `match='"scripts"'` against `package.json` could never match. The mask's job
18
+ * at the anchor step is the other direction: an anchor landing *inside* a
19
+ * masked region is a false positive. {@link isMasked} is that test.
20
+ *
21
+ * **Regex literals are not lexed (D8).** `/…/` is left as code, so a regex
22
+ * containing an unbalanced brace throws the depth count off. This is the known
23
+ * cause of the single silent-wrong case and most of the refusals in SPEC-131's
24
+ * 1,360-symbol measurement. Fixing it is perhaps 15 more lines and is
25
+ * deliberately deferred to WORK-590, which picks it up only if the migration
26
+ * surfaces refusals that need it — the error it produces is overwhelmingly the
27
+ * safe kind. `mask.test.ts` pins the resulting behaviour rather than asserting
28
+ * it is correct.
29
+ */
30
+ import type { LanguageDefinition } from './languages.js';
31
+ /**
32
+ * Blank comments and literals, preserving every newline.
33
+ *
34
+ * The result always has the same `length` as `source`, so an index into one is
35
+ * an index into the other.
36
+ *
37
+ * @param source Raw file text.
38
+ * @param lang The language's lexical definition, or `undefined` for a language
39
+ * absent from the table — in which case the source is returned unchanged.
40
+ * @param options `only: 'comments'` lexes strings and templates exactly as
41
+ * normal but leaves them **visible**, blanking only commentary. See
42
+ * {@link maskComments} for why that distinction matters.
43
+ */
44
+ export declare function maskSource(source: string, lang: LanguageDefinition | undefined, options?: {
45
+ only?: 'comments';
46
+ }): string;
47
+ /**
48
+ * Blank **commentary only**, lexing literals normally but leaving them visible.
49
+ *
50
+ * This is the mask the anchor step rejects against, and it is deliberately not
51
+ * the same as the one the depth counter reads.
52
+ *
53
+ * The two masks answer different questions. The depth counter needs every
54
+ * literal blanked, because a `{` inside a string must not be counted. The
55
+ * anchor step needs the opposite for literals: in JSON *every key is a string*,
56
+ * so rejecting matches inside literals would make `match='"scripts"'`
57
+ * unresolvable — and a quoted attribute selector, a key, or text inside a
58
+ * template are all perfectly good things to name.
59
+ *
60
+ * What the anchor step does need to reject is **commentary**: a `.rf-hint {`
61
+ * mentioned in a comment, or a `## Install` inside a fenced block, is talking
62
+ * *about* code rather than being it, so an anchor landing there is a false
63
+ * positive.
64
+ *
65
+ * Strings are still lexed here, just not blanked — otherwise a `//` inside a
66
+ * URL would open a comment that blanked the rest of the line.
67
+ */
68
+ export declare function maskComments(source: string, lang: LanguageDefinition | undefined): string;
69
+ /**
70
+ * Whether the character at `index` falls inside a region the masker blanked.
71
+ *
72
+ * This is the anchor step's rejection test: a `.rf-hint {` mentioned in a
73
+ * comment, or a `## Install` inside a fenced block, is a false positive rather
74
+ * than a usable anchor. Compares against the raw source so that a space that
75
+ * was always a space is not mistaken for a masked one.
76
+ */
77
+ export declare function isMasked(source: string, masked: string, index: number): boolean;
78
+ /**
79
+ * Whether any character of `[start, end)` was masked.
80
+ *
81
+ * An anchor regex matches a *range*, and a match that begins in code but runs
82
+ * into a comment is still not a clean anchor.
83
+ */
84
+ export declare function isRangeMasked(source: string, masked: string, start: number, end: number): boolean;
85
+ /**
86
+ * The first line of the contiguous comment block immediately above `line`.
87
+ *
88
+ * Returns `line` itself when there is nothing to absorb — which is always the
89
+ * answer for a language absent from the table, because a definition with no
90
+ * comment prefixes recognises no comment (D10). WORK-587's `doc` attribute is
91
+ * the consumer; this is the lexical half of it and lives here because the
92
+ * decision is entirely table-driven.
93
+ *
94
+ * Blank lines break the block: a comment separated from the declaration by an
95
+ * empty line is a file header or a note about something else, not its
96
+ * documentation.
97
+ *
98
+ * @param lines The file's lines.
99
+ * @param line 0-indexed line of the declaration.
100
+ * @param lang The language definition, or `undefined` for an unknown language.
101
+ */
102
+ export declare function docHeadStart(lines: string[], line: number, lang: LanguageDefinition | undefined): number;
103
+ /**
104
+ * The regex source for a `symbol=` anchor, built from the language's keywords
105
+ * and modifiers (D15: a template with one hole).
106
+ *
107
+ * `name` is escaped before interpolation — a symbol name containing `.` or `(`
108
+ * spliced raw into a regex is injection from content.
109
+ *
110
+ * Returns `undefined` when the language declares no keywords, so the caller
111
+ * refuses rather than falling back to a guessed pattern.
112
+ */
113
+ export declare function symbolAnchorPattern(name: string, lang: LanguageDefinition | undefined): string | undefined;
114
+ /** Escape a string for literal use inside a regular expression. */
115
+ export declare function escapeRegExp(input: string): string;
116
+ //# sourceMappingURL=mask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../../src/lib/mask.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAgBzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,kBAAkB,GAAG,SAAS,EACpC,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,GAC7B,MAAM,CAyJR;AA6ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,SAAS,GAAG,MAAM,CAEzF;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG/E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAKjG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC3B,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,kBAAkB,GAAG,SAAS,GAClC,MAAM,CA6BR;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,kBAAkB,GAAG,SAAS,GAClC,MAAM,GAAG,SAAS,CAQpB;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -0,0 +1,378 @@
1
+ /**
2
+ * The masker (SPEC-131 step 1, WORK-597).
3
+ *
4
+ * Blanks comments and string/template literals so that delimiter counting is
5
+ * safe, **preserving newlines** so the masked text has the same line count and
6
+ * the same line offsets as its input. Every later stage of the resolver reads
7
+ * positions off one and applies them to the other, so that correspondence is
8
+ * the module's central invariant, not an implementation detail.
9
+ *
10
+ * This is a lexer, not a parser. It has no per-language branching: every
11
+ * prefix, delimiter and escape it recognises comes from the table in
12
+ * `languages.ts` (D15). A language absent from that table is returned
13
+ * unchanged — the conservative answer, since a guessed mask blanks real code.
14
+ *
15
+ * **Anchors match raw source; the mask only rejects.** SPEC-131 is explicit
16
+ * that matching against masked text would blank every string literal, so
17
+ * `match='"scripts"'` against `package.json` could never match. The mask's job
18
+ * at the anchor step is the other direction: an anchor landing *inside* a
19
+ * masked region is a false positive. {@link isMasked} is that test.
20
+ *
21
+ * **Regex literals are not lexed (D8).** `/…/` is left as code, so a regex
22
+ * containing an unbalanced brace throws the depth count off. This is the known
23
+ * cause of the single silent-wrong case and most of the refusals in SPEC-131's
24
+ * 1,360-symbol measurement. Fixing it is perhaps 15 more lines and is
25
+ * deliberately deferred to WORK-590, which picks it up only if the migration
26
+ * surfaces refusals that need it — the error it produces is overwhelmingly the
27
+ * safe kind. `mask.test.ts` pins the resulting behaviour rather than asserting
28
+ * it is correct.
29
+ */
30
+ /** Longest-first, so `'''` is tried before `'` and `<!--` before `<`. */
31
+ function byLengthDesc(items, len) {
32
+ return [...items].sort((a, b) => len(b) - len(a));
33
+ }
34
+ /**
35
+ * Blank comments and literals, preserving every newline.
36
+ *
37
+ * The result always has the same `length` as `source`, so an index into one is
38
+ * an index into the other.
39
+ *
40
+ * @param source Raw file text.
41
+ * @param lang The language's lexical definition, or `undefined` for a language
42
+ * absent from the table — in which case the source is returned unchanged.
43
+ * @param options `only: 'comments'` lexes strings and templates exactly as
44
+ * normal but leaves them **visible**, blanking only commentary. See
45
+ * {@link maskComments} for why that distinction matters.
46
+ */
47
+ export function maskSource(source, lang, options) {
48
+ if (!lang)
49
+ return source;
50
+ // Markdown is a different problem and gets a different pass. Declaring
51
+ // fences is what selects it — the masker still branches on table data, not
52
+ // on a language name.
53
+ if (lang.fences.length > 0 || lang.inlineCode.length > 0) {
54
+ return maskMarkdown(source, lang);
55
+ }
56
+ const commentsOnly = options?.only === 'comments';
57
+ const n = source.length;
58
+ const out = source.split('');
59
+ const escapeChar = lang.escape;
60
+ const lineComments = byLengthDesc(lang.lineComments, (c) => c.length);
61
+ const blockComments = byLengthDesc(lang.blockComments, ([open]) => open.length);
62
+ const strings = byLengthDesc(lang.strings, (s) => s.delim.length);
63
+ const templates = byLengthDesc(lang.templates, (t) => t.delim.length);
64
+ /** Blank [from, to), never touching a newline. Under `only: 'comments'`
65
+ * a literal is lexed but left visible, so an anchor naming a JSON key or a
66
+ * quoted selector still matches. */
67
+ const blank = (from, to, kind = 'comment') => {
68
+ if (commentsOnly && kind === 'literal')
69
+ return;
70
+ for (let k = from; k < to && k < n; k++) {
71
+ if (out[k] !== '\n')
72
+ out[k] = ' ';
73
+ }
74
+ };
75
+ const endOfLine = (from) => {
76
+ const nl = source.indexOf('\n', from);
77
+ return nl === -1 ? n : nl;
78
+ };
79
+ /** Scan a quoted run starting at `from` (on its opening delimiter). */
80
+ const scanString = (from, delim, multiline) => {
81
+ let k = from + delim.length;
82
+ while (k < n) {
83
+ if (escapeChar && source.startsWith(escapeChar, k)) {
84
+ k += escapeChar.length + 1;
85
+ continue;
86
+ }
87
+ if (source.startsWith(delim, k))
88
+ return k + delim.length;
89
+ // An unterminated single-line string ends at the newline rather than
90
+ // consuming the rest of the file.
91
+ if (!multiline && source[k] === '\n')
92
+ return k;
93
+ k++;
94
+ }
95
+ return n;
96
+ };
97
+ const stack = [{ type: 'code' }];
98
+ let i = 0;
99
+ while (i < n) {
100
+ const top = stack[stack.length - 1];
101
+ if (top.type === 'template') {
102
+ if (escapeChar && source.startsWith(escapeChar, i)) {
103
+ blank(i, i + escapeChar.length + 1, 'literal');
104
+ i += escapeChar.length + 1;
105
+ continue;
106
+ }
107
+ if (top.open && source.startsWith(top.open, i)) {
108
+ blank(i, i + top.open.length, 'literal');
109
+ i += top.open.length;
110
+ stack.push({ type: 'interp', close: top.close ?? '}', depth: 0 });
111
+ continue;
112
+ }
113
+ if (source.startsWith(top.delim, i)) {
114
+ blank(i, i + top.delim.length, 'literal');
115
+ i += top.delim.length;
116
+ stack.pop();
117
+ continue;
118
+ }
119
+ blank(i, i + 1, 'literal');
120
+ i++;
121
+ continue;
122
+ }
123
+ // `code` and `interp` share every lexical rule; they differ only in that
124
+ // `interp` counts braces so it knows which close token is its own.
125
+ let advanced = false;
126
+ for (const prefix of lineComments) {
127
+ if (source.startsWith(prefix, i)) {
128
+ const eol = endOfLine(i);
129
+ blank(i, eol);
130
+ i = eol;
131
+ advanced = true;
132
+ break;
133
+ }
134
+ }
135
+ if (advanced)
136
+ continue;
137
+ for (const [open, close] of blockComments) {
138
+ if (source.startsWith(open, i)) {
139
+ const found = source.indexOf(close, i + open.length);
140
+ const end = found === -1 ? n : found + close.length;
141
+ blank(i, end);
142
+ i = end;
143
+ advanced = true;
144
+ break;
145
+ }
146
+ }
147
+ if (advanced)
148
+ continue;
149
+ for (const template of templates) {
150
+ if (source.startsWith(template.delim, i)) {
151
+ blank(i, i + template.delim.length, 'literal');
152
+ i += template.delim.length;
153
+ stack.push({
154
+ type: 'template',
155
+ delim: template.delim,
156
+ open: template.interpolationOpen,
157
+ close: template.interpolationClose,
158
+ });
159
+ advanced = true;
160
+ break;
161
+ }
162
+ }
163
+ if (advanced)
164
+ continue;
165
+ for (const str of strings) {
166
+ if (source.startsWith(str.delim, i)) {
167
+ const end = scanString(i, str.delim, str.multiline === true);
168
+ blank(i, end, 'literal');
169
+ i = end;
170
+ advanced = true;
171
+ break;
172
+ }
173
+ }
174
+ if (advanced)
175
+ continue;
176
+ if (top.type === 'interp') {
177
+ if (source.startsWith(top.close, i)) {
178
+ if (top.depth === 0) {
179
+ blank(i, i + top.close.length, 'literal');
180
+ i += top.close.length;
181
+ stack.pop();
182
+ continue;
183
+ }
184
+ top.depth--;
185
+ }
186
+ else if (source[i] === '{') {
187
+ top.depth++;
188
+ }
189
+ }
190
+ i++;
191
+ }
192
+ return out.join('');
193
+ }
194
+ /** Blank a line to spaces, preserving its length. */
195
+ function blankLine(line) {
196
+ return ' '.repeat(line.length);
197
+ }
198
+ /**
199
+ * The Markdown pass — fenced blocks and inline code spans.
200
+ *
201
+ * Budgeted separately from the C-family state machine, per SPEC-131: on a docs
202
+ * site the fences frequently contain the very tokens being counted, and the
203
+ * pages most worth quoting with `paired` are exactly the ones full of fenced
204
+ * examples of the tags. Without this, a `section` anchor stops at a `## ` that
205
+ * lives inside a fence, and a `paired` count is thrown off by a tag nobody ever
206
+ * wrote as a tag.
207
+ *
208
+ * **Fence marker lines stay visible; only the interior is blanked.** An author
209
+ * can legitimately anchor on a fence, and a symmetric `paired` scan needs to
210
+ * see the closing one — blanking the markers would break both.
211
+ */
212
+ function maskMarkdown(source, lang) {
213
+ const lines = source.split('\n');
214
+ const fences = byLengthDesc(lang.fences, (f) => f.length);
215
+ const spans = byLengthDesc(lang.inlineCode, (c) => c.length);
216
+ const blockComments = byLengthDesc(lang.blockComments, ([open]) => open.length);
217
+ let openFence;
218
+ let openComment;
219
+ const out = lines.map((line) => {
220
+ const trimmed = line.trimStart();
221
+ if (openFence !== undefined) {
222
+ // Inside a fence: the closing marker line stays, everything else goes.
223
+ if (trimmed.startsWith(openFence)) {
224
+ openFence = undefined;
225
+ return line;
226
+ }
227
+ return blankLine(line);
228
+ }
229
+ if (openComment !== undefined) {
230
+ if (line.includes(openComment[1]))
231
+ openComment = undefined;
232
+ return blankLine(line);
233
+ }
234
+ const fence = fences.find((f) => trimmed.startsWith(f));
235
+ if (fence !== undefined) {
236
+ openFence = fence;
237
+ return line;
238
+ }
239
+ const comment = blockComments.find(([open]) => trimmed.startsWith(open));
240
+ if (comment !== undefined) {
241
+ if (!line.includes(comment[1]))
242
+ openComment = comment;
243
+ return blankLine(line);
244
+ }
245
+ // Inline code spans, blanked delimiters and all.
246
+ let masked = line;
247
+ for (const delim of spans) {
248
+ let from = masked.indexOf(delim);
249
+ while (from !== -1) {
250
+ const close = masked.indexOf(delim, from + delim.length);
251
+ if (close === -1)
252
+ break;
253
+ const end = close + delim.length;
254
+ masked = masked.slice(0, from) + ' '.repeat(end - from) + masked.slice(end);
255
+ from = masked.indexOf(delim, end);
256
+ }
257
+ }
258
+ return masked;
259
+ });
260
+ return out.join('\n');
261
+ }
262
+ /**
263
+ * Blank **commentary only**, lexing literals normally but leaving them visible.
264
+ *
265
+ * This is the mask the anchor step rejects against, and it is deliberately not
266
+ * the same as the one the depth counter reads.
267
+ *
268
+ * The two masks answer different questions. The depth counter needs every
269
+ * literal blanked, because a `{` inside a string must not be counted. The
270
+ * anchor step needs the opposite for literals: in JSON *every key is a string*,
271
+ * so rejecting matches inside literals would make `match='"scripts"'`
272
+ * unresolvable — and a quoted attribute selector, a key, or text inside a
273
+ * template are all perfectly good things to name.
274
+ *
275
+ * What the anchor step does need to reject is **commentary**: a `.rf-hint {`
276
+ * mentioned in a comment, or a `## Install` inside a fenced block, is talking
277
+ * *about* code rather than being it, so an anchor landing there is a false
278
+ * positive.
279
+ *
280
+ * Strings are still lexed here, just not blanked — otherwise a `//` inside a
281
+ * URL would open a comment that blanked the rest of the line.
282
+ */
283
+ export function maskComments(source, lang) {
284
+ return maskSource(source, lang, { only: 'comments' });
285
+ }
286
+ /**
287
+ * Whether the character at `index` falls inside a region the masker blanked.
288
+ *
289
+ * This is the anchor step's rejection test: a `.rf-hint {` mentioned in a
290
+ * comment, or a `## Install` inside a fenced block, is a false positive rather
291
+ * than a usable anchor. Compares against the raw source so that a space that
292
+ * was always a space is not mistaken for a masked one.
293
+ */
294
+ export function isMasked(source, masked, index) {
295
+ if (index < 0 || index >= source.length)
296
+ return false;
297
+ return masked[index] !== source[index];
298
+ }
299
+ /**
300
+ * Whether any character of `[start, end)` was masked.
301
+ *
302
+ * An anchor regex matches a *range*, and a match that begins in code but runs
303
+ * into a comment is still not a clean anchor.
304
+ */
305
+ export function isRangeMasked(source, masked, start, end) {
306
+ for (let i = start; i < end && i < source.length; i++) {
307
+ if (isMasked(source, masked, i))
308
+ return true;
309
+ }
310
+ return false;
311
+ }
312
+ /**
313
+ * The first line of the contiguous comment block immediately above `line`.
314
+ *
315
+ * Returns `line` itself when there is nothing to absorb — which is always the
316
+ * answer for a language absent from the table, because a definition with no
317
+ * comment prefixes recognises no comment (D10). WORK-587's `doc` attribute is
318
+ * the consumer; this is the lexical half of it and lives here because the
319
+ * decision is entirely table-driven.
320
+ *
321
+ * Blank lines break the block: a comment separated from the declaration by an
322
+ * empty line is a file header or a note about something else, not its
323
+ * documentation.
324
+ *
325
+ * @param lines The file's lines.
326
+ * @param line 0-indexed line of the declaration.
327
+ * @param lang The language definition, or `undefined` for an unknown language.
328
+ */
329
+ export function docHeadStart(lines, line, lang) {
330
+ if (!lang)
331
+ return line;
332
+ const prefixes = [...lang.lineComments];
333
+ const blockOpens = lang.blockComments.map(([open]) => open);
334
+ const blockCloses = lang.blockComments.map(([, close]) => close);
335
+ // A `*` continuation line inside a `/* … */` block is not a comment opener
336
+ // in its own right, so it is recognised only when the language has a block
337
+ // comment at all — never as a global fallback.
338
+ const continuations = blockOpens.length > 0 ? ['*'] : [];
339
+ if (prefixes.length === 0 && blockOpens.length === 0)
340
+ return line;
341
+ let start = line;
342
+ for (let i = line - 1; i >= 0; i--) {
343
+ const text = lines[i].trim();
344
+ if (text.length === 0)
345
+ break;
346
+ const isComment = prefixes.some((p) => text.startsWith(p)) ||
347
+ blockOpens.some((o) => text.startsWith(o)) ||
348
+ blockCloses.some((c) => text.endsWith(c)) ||
349
+ continuations.some((c) => text.startsWith(c));
350
+ if (!isComment)
351
+ break;
352
+ start = i;
353
+ }
354
+ return start;
355
+ }
356
+ /**
357
+ * The regex source for a `symbol=` anchor, built from the language's keywords
358
+ * and modifiers (D15: a template with one hole).
359
+ *
360
+ * `name` is escaped before interpolation — a symbol name containing `.` or `(`
361
+ * spliced raw into a regex is injection from content.
362
+ *
363
+ * Returns `undefined` when the language declares no keywords, so the caller
364
+ * refuses rather than falling back to a guessed pattern.
365
+ */
366
+ export function symbolAnchorPattern(name, lang) {
367
+ if (!lang || lang.keywords.length === 0)
368
+ return undefined;
369
+ const keywords = lang.keywords.map(escapeRegExp).join('|');
370
+ const modifiers = lang.modifiers.map(escapeRegExp).join('|');
371
+ const modifierPart = modifiers.length > 0 ? `((${modifiers})\\s+)*` : '';
372
+ return `^([ \\t]*)${modifierPart}(${keywords})\\s*\\*?\\s+${escapeRegExp(name)}\\b`;
373
+ }
374
+ /** Escape a string for literal use inside a regular expression. */
375
+ export function escapeRegExp(input) {
376
+ return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
377
+ }
378
+ //# sourceMappingURL=mask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.js","sourceRoot":"","sources":["../../src/lib/mask.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import type { Node } from '@markdoc/markdoc';
2
- import { NodeFilter } from '../interfaces.js';
2
+ import type { NodeFilter } from '../interfaces.js';
3
3
  export declare function isFilterMatching(n: Node, match: NodeFilter): boolean;
4
4
  //# sourceMappingURL=node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/lib/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAqB,MAAM,kBAAkB,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,WAmB1D"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/lib/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,kBAAkB,CAAC;AAEtE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,WAmB1D"}