@refrakt-md/runes 0.36.0 → 0.38.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 (195) hide show
  1. package/dist/config.d.ts.map +1 -1
  2. package/dist/config.js +6 -6
  3. package/dist/config.js.map +1 -1
  4. package/dist/file-ref-resolve.d.ts.map +1 -1
  5. package/dist/file-ref-resolve.js +36 -1
  6. package/dist/file-ref-resolve.js.map +1 -1
  7. package/dist/index.d.ts +14 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +14 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/lang-map.d.ts.map +1 -1
  12. package/dist/lang-map.js +8 -0
  13. package/dist/lang-map.js.map +1 -1
  14. package/dist/lib/anchor.d.ts +73 -0
  15. package/dist/lib/anchor.d.ts.map +1 -0
  16. package/dist/lib/anchor.js +521 -0
  17. package/dist/lib/anchor.js.map +1 -0
  18. package/dist/lib/component.d.ts +9 -12
  19. package/dist/lib/component.d.ts.map +1 -1
  20. package/dist/lib/component.js +17 -52
  21. package/dist/lib/component.js.map +1 -1
  22. package/dist/lib/field-metas.d.ts +34 -0
  23. package/dist/lib/field-metas.d.ts.map +1 -0
  24. package/dist/lib/field-metas.js +45 -0
  25. package/dist/lib/field-metas.js.map +1 -0
  26. package/dist/lib/index.d.ts +17 -0
  27. package/dist/lib/index.d.ts.map +1 -1
  28. package/dist/lib/index.js +22 -0
  29. package/dist/lib/index.js.map +1 -1
  30. package/dist/lib/invocation.d.ts +22 -0
  31. package/dist/lib/invocation.d.ts.map +1 -0
  32. package/dist/lib/invocation.js +67 -0
  33. package/dist/lib/invocation.js.map +1 -0
  34. package/dist/lib/languages.d.ts +163 -0
  35. package/dist/lib/languages.d.ts.map +1 -0
  36. package/dist/lib/languages.js +383 -0
  37. package/dist/lib/languages.js.map +1 -0
  38. package/dist/lib/line-diff.d.ts +35 -0
  39. package/dist/lib/line-diff.d.ts.map +1 -0
  40. package/dist/lib/line-diff.js +77 -0
  41. package/dist/lib/line-diff.js.map +1 -0
  42. package/dist/lib/mask.d.ts +116 -0
  43. package/dist/lib/mask.d.ts.map +1 -0
  44. package/dist/lib/mask.js +378 -0
  45. package/dist/lib/mask.js.map +1 -0
  46. package/dist/lib/node.d.ts +23 -1
  47. package/dist/lib/node.d.ts.map +1 -1
  48. package/dist/lib/node.js +32 -0
  49. package/dist/lib/node.js.map +1 -1
  50. package/dist/lib/present.d.ts +73 -0
  51. package/dist/lib/present.d.ts.map +1 -0
  52. package/dist/lib/present.js +127 -0
  53. package/dist/lib/present.js.map +1 -0
  54. package/dist/lib/read-file.d.ts +21 -1
  55. package/dist/lib/read-file.d.ts.map +1 -1
  56. package/dist/lib/read-file.js +46 -0
  57. package/dist/lib/read-file.js.map +1 -1
  58. package/dist/lib/renderable.d.ts +7 -3
  59. package/dist/lib/renderable.d.ts.map +1 -1
  60. package/dist/lib/renderable.js +2 -2
  61. package/dist/lib/renderable.js.map +1 -1
  62. package/dist/lib/resolver.d.ts.map +1 -1
  63. package/dist/lib/resolver.js +8 -1
  64. package/dist/lib/resolver.js.map +1 -1
  65. package/dist/lib/review-marker.d.ts +113 -0
  66. package/dist/lib/review-marker.d.ts.map +1 -0
  67. package/dist/lib/review-marker.js +173 -0
  68. package/dist/lib/review-marker.js.map +1 -0
  69. package/dist/props.d.ts +0 -2
  70. package/dist/props.d.ts.map +1 -1
  71. package/dist/reference.d.ts +19 -0
  72. package/dist/reference.d.ts.map +1 -1
  73. package/dist/reference.js +82 -1
  74. package/dist/reference.js.map +1 -1
  75. package/dist/snippet-pipeline.d.ts.map +1 -1
  76. package/dist/snippet-pipeline.js +70 -2
  77. package/dist/snippet-pipeline.js.map +1 -1
  78. package/dist/tags/accordion.d.ts.map +1 -1
  79. package/dist/tags/accordion.js +4 -7
  80. package/dist/tags/accordion.js.map +1 -1
  81. package/dist/tags/annotate.d.ts.map +1 -1
  82. package/dist/tags/annotate.js +6 -13
  83. package/dist/tags/annotate.js.map +1 -1
  84. package/dist/tags/bar.d.ts.map +1 -1
  85. package/dist/tags/bar.js +2 -5
  86. package/dist/tags/bar.js.map +1 -1
  87. package/dist/tags/blog.d.ts.map +1 -1
  88. package/dist/tags/blog.js +1 -9
  89. package/dist/tags/blog.js.map +1 -1
  90. package/dist/tags/breadcrumb.d.ts.map +1 -1
  91. package/dist/tags/breadcrumb.js +4 -5
  92. package/dist/tags/breadcrumb.js.map +1 -1
  93. package/dist/tags/budget.d.ts.map +1 -1
  94. package/dist/tags/budget.js +2 -10
  95. package/dist/tags/budget.js.map +1 -1
  96. package/dist/tags/card.d.ts.map +1 -1
  97. package/dist/tags/card.js +7 -14
  98. package/dist/tags/card.js.map +1 -1
  99. package/dist/tags/chart.d.ts.map +1 -1
  100. package/dist/tags/chart.js +5 -8
  101. package/dist/tags/chart.js.map +1 -1
  102. package/dist/tags/codegroup.d.ts.map +1 -1
  103. package/dist/tags/codegroup.js +0 -2
  104. package/dist/tags/codegroup.js.map +1 -1
  105. package/dist/tags/common.d.ts.map +1 -1
  106. package/dist/tags/common.js +2 -5
  107. package/dist/tags/common.js.map +1 -1
  108. package/dist/tags/compare.d.ts.map +1 -1
  109. package/dist/tags/compare.js +4 -8
  110. package/dist/tags/compare.js.map +1 -1
  111. package/dist/tags/conversation.d.ts.map +1 -1
  112. package/dist/tags/conversation.js +4 -7
  113. package/dist/tags/conversation.js.map +1 -1
  114. package/dist/tags/datatable.d.ts.map +1 -1
  115. package/dist/tags/datatable.js +4 -8
  116. package/dist/tags/datatable.js.map +1 -1
  117. package/dist/tags/details.d.ts.map +1 -1
  118. package/dist/tags/details.js +3 -7
  119. package/dist/tags/details.js.map +1 -1
  120. package/dist/tags/diagram.js +2 -2
  121. package/dist/tags/diagram.js.map +1 -1
  122. package/dist/tags/diff.d.ts.map +1 -1
  123. package/dist/tags/diff.js +2 -39
  124. package/dist/tags/diff.js.map +1 -1
  125. package/dist/tags/drawer.d.ts.map +1 -1
  126. package/dist/tags/drawer.js +4 -12
  127. package/dist/tags/drawer.js.map +1 -1
  128. package/dist/tags/embed.d.ts.map +1 -1
  129. package/dist/tags/embed.js +4 -5
  130. package/dist/tags/embed.js.map +1 -1
  131. package/dist/tags/figure.d.ts.map +1 -1
  132. package/dist/tags/figure.js +6 -14
  133. package/dist/tags/figure.js.map +1 -1
  134. package/dist/tags/file-ref.d.ts.map +1 -1
  135. package/dist/tags/file-ref.js +59 -1
  136. package/dist/tags/file-ref.js.map +1 -1
  137. package/dist/tags/form.d.ts.map +1 -1
  138. package/dist/tags/form.js +3 -18
  139. package/dist/tags/form.js.map +1 -1
  140. package/dist/tags/gallery.d.ts.map +1 -1
  141. package/dist/tags/gallery.js +6 -11
  142. package/dist/tags/gallery.js.map +1 -1
  143. package/dist/tags/grid.d.ts.map +1 -1
  144. package/dist/tags/grid.js +7 -17
  145. package/dist/tags/grid.js.map +1 -1
  146. package/dist/tags/hint.d.ts.map +1 -1
  147. package/dist/tags/hint.js +4 -8
  148. package/dist/tags/hint.js.map +1 -1
  149. package/dist/tags/juxtapose.js +2 -2
  150. package/dist/tags/juxtapose.js.map +1 -1
  151. package/dist/tags/layout.d.ts.map +1 -1
  152. package/dist/tags/layout.js +2 -5
  153. package/dist/tags/layout.js.map +1 -1
  154. package/dist/tags/mediatext.d.ts.map +1 -1
  155. package/dist/tags/mediatext.js +5 -13
  156. package/dist/tags/mediatext.js.map +1 -1
  157. package/dist/tags/nav.d.ts.map +1 -1
  158. package/dist/tags/nav.js +2 -5
  159. package/dist/tags/nav.js.map +1 -1
  160. package/dist/tags/progress.d.ts.map +1 -1
  161. package/dist/tags/progress.js +4 -8
  162. package/dist/tags/progress.js.map +1 -1
  163. package/dist/tags/pullquote.d.ts.map +1 -1
  164. package/dist/tags/pullquote.js +8 -15
  165. package/dist/tags/pullquote.js.map +1 -1
  166. package/dist/tags/region.d.ts.map +1 -1
  167. package/dist/tags/region.js +2 -5
  168. package/dist/tags/region.js.map +1 -1
  169. package/dist/tags/reveal.d.ts.map +1 -1
  170. package/dist/tags/reveal.js +4 -7
  171. package/dist/tags/reveal.js.map +1 -1
  172. package/dist/tags/section.d.ts.map +1 -1
  173. package/dist/tags/section.js +3 -3
  174. package/dist/tags/section.js.map +1 -1
  175. package/dist/tags/showcase.d.ts.map +1 -1
  176. package/dist/tags/showcase.js +4 -11
  177. package/dist/tags/showcase.js.map +1 -1
  178. package/dist/tags/sidenote.d.ts.map +1 -1
  179. package/dist/tags/sidenote.js +7 -12
  180. package/dist/tags/sidenote.js.map +1 -1
  181. package/dist/tags/snippet.d.ts.map +1 -1
  182. package/dist/tags/snippet.js +53 -2
  183. package/dist/tags/snippet.js.map +1 -1
  184. package/dist/tags/tabs.d.ts.map +1 -1
  185. package/dist/tags/tabs.js +3 -6
  186. package/dist/tags/tabs.js.map +1 -1
  187. package/dist/tags/textblock.d.ts.map +1 -1
  188. package/dist/tags/textblock.js +7 -19
  189. package/dist/tags/textblock.js.map +1 -1
  190. package/dist/tags/tint.d.ts.map +1 -1
  191. package/dist/tags/tint.js +17 -29
  192. package/dist/tags/tint.js.map +1 -1
  193. package/dist/tags/toc.js +1 -1
  194. package/dist/tags/toc.js.map +1 -1
  195. package/package.json +3 -3
@@ -0,0 +1,163 @@
1
+ /**
2
+ * The per-language lexical table (SPEC-131 D15, WORK-597).
3
+ *
4
+ * This module is **data**. The state machine that reads it lives in
5
+ * `mask.ts`, and the split is deliberate — D15 draws the line between what is
6
+ * declarative (comment prefixes, string delimiters, `symbol=` keywords, token
7
+ * pairs, heading shapes, tab width) and what stays code (the masker, the depth
8
+ * counter, continuation lookahead, the balance self-check).
9
+ *
10
+ * **Why a table and not a union regex (D10).** The obvious shortcut is to walk
11
+ * `^\s*(//|#|\*|/\*)` across every language at once. In CSS that eats
12
+ * `#header { … }` as a comment, and a head that silently swallows a preceding
13
+ * rule is exactly the failure class SPEC-131 exists to remove. There are zero
14
+ * such lines in Lumina today, so this repository would never notice — but
15
+ * refrakt ships to projects whose files we have never seen.
16
+ *
17
+ * **A language absent from this table gets no guess.** No comment prefixes
18
+ * means no head absorption and nothing masked, rather than a plausible default
19
+ * that is wrong in a format nobody checked.
20
+ *
21
+ * **No config surface ships with this (D15).** `refrakt.config.json` gains no
22
+ * `languages` or `anchors` key in this milestone. What ships is the
23
+ * {@link mergeLanguages} seam, mirroring `mergeThemeConfig()`, so that
24
+ * declaring a language later is an additive change rather than a retrofit of a
25
+ * hard-coded table.
26
+ */
27
+ /** A string delimiter and whether it may span a line break. */
28
+ export interface StringDelimiter {
29
+ /** The opening and closing character(s) — the same on both ends. */
30
+ delim: string;
31
+ /** When false (the default) an unterminated string ends at the newline. */
32
+ multiline?: boolean;
33
+ }
34
+ /**
35
+ * A template delimiter — a string that can contain interpolated code.
36
+ *
37
+ * The interpolation tokens are table data rather than a hard-coded `${`,
38
+ * because the masker must not branch per language (D15).
39
+ */
40
+ export interface TemplateDelimiter {
41
+ delim: string;
42
+ /** Token that re-enters code state, e.g. `'${'`. Omit for no interpolation. */
43
+ interpolationOpen?: string;
44
+ /** Token that returns to template state, e.g. `'}'`. */
45
+ interpolationClose?: string;
46
+ }
47
+ /**
48
+ * A paired token — WORK-588's `extent="paired"` reads these.
49
+ *
50
+ * Declared here now rather than later because retrofitting a hard-coded table
51
+ * is the expensive part, and the shape is what this module exists to get right.
52
+ */
53
+ export interface TokenPair {
54
+ open: string;
55
+ close: string;
56
+ /**
57
+ * `asymmetric` — distinct open/close, nests (`{% tabs %}` / `{% /tabs %}`).
58
+ * `symmetric` — same token both ends, cannot nest, first recurrence closes
59
+ * (a ``` fence).
60
+ * `selfClosing` — no close at all (`{% snippet /%}`, `<img>`); a `paired`
61
+ * scan anchored on one returns a single line rather than running to EOF.
62
+ */
63
+ shape: 'asymmetric' | 'symmetric' | 'selfClosing';
64
+ }
65
+ /** A heading shape — WORK-588's `extent="section"` derives its terminator here. */
66
+ export interface HeadingShape {
67
+ /**
68
+ * Matches a heading line. Capture group 1 must be the part whose **length**
69
+ * gives the nesting level (`###` → 3), so `section` can build a terminator
70
+ * for the anchor's own level without the author doing the arithmetic.
71
+ */
72
+ pattern: string;
73
+ }
74
+ /** Everything the lexical layer knows about one language. */
75
+ export interface LanguageDefinition {
76
+ /** Line-comment prefixes. Empty means the language has none. */
77
+ lineComments: string[];
78
+ /** Block-comment open/close pairs. */
79
+ blockComments: Array<[open: string, close: string]>;
80
+ /** Quote delimiters. */
81
+ strings: StringDelimiter[];
82
+ /** Template delimiters, which may contain interpolated code. */
83
+ templates: TemplateDelimiter[];
84
+ /** Escape character inside strings and templates. */
85
+ escape?: string;
86
+ /**
87
+ * Annotation prefixes that attach to a declaration (`@Component`,
88
+ * `#[derive]`, `@dataclass`). WORK-587 attaches these to the symbol always,
89
+ * independently of `doc`.
90
+ */
91
+ annotations: string[];
92
+ /** `symbol=` declaration keywords. */
93
+ keywords: string[];
94
+ /** Declaration modifiers permitted before a keyword. */
95
+ modifiers: string[];
96
+ /** Heading shapes — WORK-588 (`extent="section"`). */
97
+ headings: HeadingShape[];
98
+ /** Token pairs — WORK-588 (`extent="paired"`). */
99
+ tokenPairs: TokenPair[];
100
+ /**
101
+ * Block-fence markers (```` ``` ````, `~~~`).
102
+ *
103
+ * Declaring these switches the masker onto its **Markdown** pass, which is
104
+ * a separate budget line from the C-family state machine and not the same
105
+ * ~40 lines: on a docs site the fences frequently contain the very tokens
106
+ * being counted. `site/content/runes/tabs.md` has a `{% tab %}` in an
107
+ * inline code span, and the pages most worth quoting with `paired` are
108
+ * exactly the ones full of fenced examples of the tags.
109
+ *
110
+ * The fence *marker lines stay visible* and only the interior is blanked,
111
+ * so an author can still anchor on a fence and a symmetric `paired` scan
112
+ * can still find its close.
113
+ */
114
+ fences: string[];
115
+ /** Inline code-span delimiters. Blanked span and all. */
116
+ inlineCode: string[];
117
+ /** Columns a tab expands to — WORK-588 (`extent="dedent"`). */
118
+ tabWidth: number;
119
+ /**
120
+ * Whether the language belongs to D11's **balanced delimiters** family —
121
+ * the one `extent="auto"` is for, where a `;` or a matching `}` ends a
122
+ * construct.
123
+ *
124
+ * This is a lexical fact, not a strategy (D5): the engine still never
125
+ * guesses which extent to use. What it does is let `auto` refuse in a
126
+ * language where delimiter balance is meaningless, instead of returning a
127
+ * plausible wrong span. Python and YAML are indentation-structured, and
128
+ * Markdoc, Svelte and HTML are tag-paired — pointing `auto` at any of them
129
+ * is the silently-wrong case, so `auto` fails loudly there and the refusal
130
+ * names the strategy that does fit.
131
+ */
132
+ delimited: boolean;
133
+ }
134
+ /** A partial definition, as an override or a newly declared language. */
135
+ export type LanguageDefinitionOverrides = Partial<LanguageDefinition>;
136
+ /**
137
+ * The built-in table.
138
+ *
139
+ * Keys are the highlight-language identifiers `LANG_MAP` already produces, so
140
+ * extension → language identification is reused rather than duplicated.
141
+ */
142
+ export declare const BASE_LANGUAGES: Readonly<Record<string, LanguageDefinition>>;
143
+ /**
144
+ * Merge language overrides onto a base table, mirroring `mergeThemeConfig()`.
145
+ *
146
+ * A key with no base entry is a **newly declared language**, not an override,
147
+ * and is taken whole — so the seam supports both extension surfaces D15 names
148
+ * without either of them shipping a config key yet. A key that does exist is
149
+ * merged field by field, with a provided array replacing the base array rather
150
+ * than concatenating: a project narrowing a language's comment prefixes must
151
+ * be able to remove one, which a concatenating merge makes impossible.
152
+ */
153
+ export declare function mergeLanguages(base: Readonly<Record<string, LanguageDefinition>>, overrides: Record<string, LanguageDefinitionOverrides>): Record<string, LanguageDefinition>;
154
+ /**
155
+ * Look up the lexical definition for a file path or language identifier.
156
+ *
157
+ * Accepts what `inferLanguage` accepts (a path, an extension, or a bare
158
+ * extension) as well as a language id directly. Returns `undefined` for a
159
+ * language not in the table — the caller must treat that as "no lexical
160
+ * knowledge", never as a default.
161
+ */
162
+ export declare function resolveLanguage(pathOrLang: string, table?: Readonly<Record<string, LanguageDefinition>>): LanguageDefinition | undefined;
163
+ //# sourceMappingURL=languages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"languages.d.ts","sourceRoot":"","sources":["../../src/lib/languages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,+DAA+D;AAC/D,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,KAAK,EAAE,YAAY,GAAG,WAAW,GAAG,aAAa,CAAC;CAClD;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC5B;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IAClC,gEAAgE;IAChE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,sCAAsC;IACtC,aAAa,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,wBAAwB;IACxB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,gEAAgE;IAChE,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,wDAAwD;IACxD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,sDAAsD;IACtD,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,kDAAkD;IAClD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;;;;;;;;;;;;;OAaG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,yDAAyD;IACzD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;OAYG;IACH,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,MAAM,2BAA2B,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAuBtE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CA4QtE,CAAC;AAEH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC7B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,EAClD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,GACpD,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAgBpC;AAuBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAkB,GAClE,kBAAkB,GAAG,SAAS,CAOhC"}
@@ -0,0 +1,383 @@
1
+ /**
2
+ * The per-language lexical table (SPEC-131 D15, WORK-597).
3
+ *
4
+ * This module is **data**. The state machine that reads it lives in
5
+ * `mask.ts`, and the split is deliberate — D15 draws the line between what is
6
+ * declarative (comment prefixes, string delimiters, `symbol=` keywords, token
7
+ * pairs, heading shapes, tab width) and what stays code (the masker, the depth
8
+ * counter, continuation lookahead, the balance self-check).
9
+ *
10
+ * **Why a table and not a union regex (D10).** The obvious shortcut is to walk
11
+ * `^\s*(//|#|\*|/\*)` across every language at once. In CSS that eats
12
+ * `#header { … }` as a comment, and a head that silently swallows a preceding
13
+ * rule is exactly the failure class SPEC-131 exists to remove. There are zero
14
+ * such lines in Lumina today, so this repository would never notice — but
15
+ * refrakt ships to projects whose files we have never seen.
16
+ *
17
+ * **A language absent from this table gets no guess.** No comment prefixes
18
+ * means no head absorption and nothing masked, rather than a plausible default
19
+ * that is wrong in a format nobody checked.
20
+ *
21
+ * **No config surface ships with this (D15).** `refrakt.config.json` gains no
22
+ * `languages` or `anchors` key in this milestone. What ships is the
23
+ * {@link mergeLanguages} seam, mirroring `mergeThemeConfig()`, so that
24
+ * declaring a language later is an additive change rather than a retrofit of a
25
+ * hard-coded table.
26
+ */
27
+ import { inferLanguage } from '../lang-map.js';
28
+ /**
29
+ * The C-family lexical core, for the languages that agree on it.
30
+ *
31
+ * A function rather than a shared object so each language gets its own arrays:
32
+ * four definitions pointing at one `blockComments` array is a footgun waiting
33
+ * for the first consumer that mutates what it was handed.
34
+ */
35
+ function cFamily() {
36
+ return {
37
+ lineComments: ['//'],
38
+ blockComments: [['/*', '*/']],
39
+ strings: [{ delim: '"' }, { delim: "'" }],
40
+ escape: '\\',
41
+ tabWidth: 4,
42
+ delimited: true,
43
+ };
44
+ }
45
+ /**
46
+ * The built-in table.
47
+ *
48
+ * Keys are the highlight-language identifiers `LANG_MAP` already produces, so
49
+ * extension → language identification is reused rather than duplicated.
50
+ */
51
+ export const BASE_LANGUAGES = Object.freeze({
52
+ typescript: {
53
+ ...cFamily(),
54
+ templates: [{ delim: '`', interpolationOpen: '${', interpolationClose: '}' }],
55
+ annotations: ['@'],
56
+ keywords: [
57
+ 'interface',
58
+ 'type',
59
+ 'class',
60
+ 'const',
61
+ 'let',
62
+ 'var',
63
+ 'function',
64
+ 'enum',
65
+ 'namespace',
66
+ ],
67
+ modifiers: [
68
+ 'export',
69
+ 'default',
70
+ 'declare',
71
+ 'async',
72
+ 'abstract',
73
+ 'static',
74
+ 'public',
75
+ 'private',
76
+ 'protected',
77
+ 'readonly',
78
+ ],
79
+ headings: [],
80
+ tokenPairs: [],
81
+ fences: [],
82
+ inlineCode: [],
83
+ },
84
+ javascript: {
85
+ ...cFamily(),
86
+ templates: [{ delim: '`', interpolationOpen: '${', interpolationClose: '}' }],
87
+ annotations: ['@'],
88
+ keywords: ['class', 'const', 'let', 'var', 'function'],
89
+ modifiers: ['export', 'default', 'async', 'static'],
90
+ headings: [],
91
+ tokenPairs: [],
92
+ fences: [],
93
+ inlineCode: [],
94
+ },
95
+ json: {
96
+ // JSON has no comments. Giving it `//` would blank a URL inside a string
97
+ // value on any file that reached the masker before the string rule.
98
+ lineComments: [],
99
+ blockComments: [],
100
+ strings: [{ delim: '"' }],
101
+ templates: [],
102
+ escape: '\\',
103
+ annotations: [],
104
+ keywords: [],
105
+ modifiers: [],
106
+ headings: [],
107
+ tokenPairs: [],
108
+ fences: [],
109
+ inlineCode: [],
110
+ tabWidth: 2,
111
+ delimited: true,
112
+ },
113
+ jsonc: {
114
+ lineComments: ['//'],
115
+ blockComments: [['/*', '*/']],
116
+ strings: [{ delim: '"' }],
117
+ templates: [],
118
+ escape: '\\',
119
+ annotations: [],
120
+ keywords: [],
121
+ modifiers: [],
122
+ headings: [],
123
+ tokenPairs: [],
124
+ fences: [],
125
+ inlineCode: [],
126
+ tabWidth: 2,
127
+ delimited: true,
128
+ },
129
+ css: {
130
+ // D10's hazard lives here: CSS has **no** line comment. `#header { … }`
131
+ // is an id selector, and a `#` prefix would swallow the rule above any
132
+ // anchor that followed it.
133
+ lineComments: [],
134
+ blockComments: [['/*', '*/']],
135
+ strings: [{ delim: '"' }, { delim: "'" }],
136
+ templates: [],
137
+ escape: '\\',
138
+ // CSS at-rules are **not** annotations. `@media` and `@layer` open a
139
+ // block; absorbing one as a head would pull an enclosing wrapper into
140
+ // the slice, which is the opposite of what a head is for.
141
+ annotations: [],
142
+ keywords: [],
143
+ modifiers: [],
144
+ headings: [],
145
+ tokenPairs: [],
146
+ fences: [],
147
+ inlineCode: [],
148
+ tabWidth: 2,
149
+ delimited: true,
150
+ },
151
+ python: {
152
+ lineComments: ['#'],
153
+ blockComments: [],
154
+ strings: [
155
+ { delim: '"""', multiline: true },
156
+ { delim: "'''", multiline: true },
157
+ { delim: '"' },
158
+ { delim: "'" },
159
+ ],
160
+ templates: [],
161
+ escape: '\\',
162
+ annotations: ['@'],
163
+ keywords: ['def', 'class'],
164
+ modifiers: ['async'],
165
+ headings: [],
166
+ tokenPairs: [],
167
+ fences: [],
168
+ inlineCode: [],
169
+ tabWidth: 4,
170
+ delimited: false,
171
+ },
172
+ rust: {
173
+ ...cFamily(),
174
+ templates: [],
175
+ annotations: ['#['],
176
+ keywords: ['struct', 'impl', 'fn', 'trait', 'enum', 'type', 'const', 'mod'],
177
+ modifiers: ['pub', 'async', 'unsafe', 'default'],
178
+ headings: [],
179
+ tokenPairs: [],
180
+ fences: [],
181
+ inlineCode: [],
182
+ },
183
+ go: {
184
+ ...cFamily(),
185
+ strings: [{ delim: '"' }, { delim: "'" }],
186
+ templates: [{ delim: '`' }],
187
+ annotations: [],
188
+ keywords: ['func', 'type', 'var', 'const'],
189
+ modifiers: [],
190
+ headings: [],
191
+ tokenPairs: [],
192
+ fences: [],
193
+ inlineCode: [],
194
+ tabWidth: 8,
195
+ },
196
+ yaml: {
197
+ lineComments: ['#'],
198
+ blockComments: [],
199
+ strings: [{ delim: '"' }, { delim: "'" }],
200
+ templates: [],
201
+ escape: '\\',
202
+ annotations: [],
203
+ keywords: [],
204
+ modifiers: [],
205
+ headings: [],
206
+ tokenPairs: [],
207
+ fences: [],
208
+ inlineCode: [],
209
+ tabWidth: 2,
210
+ delimited: false,
211
+ },
212
+ toml: {
213
+ lineComments: ['#'],
214
+ blockComments: [],
215
+ strings: [{ delim: '"' }, { delim: "'" }],
216
+ templates: [],
217
+ escape: '\\',
218
+ annotations: [],
219
+ keywords: [],
220
+ modifiers: [],
221
+ // A TOML table header is sibling-terminated; every table is level 1, so
222
+ // the capture is the bracket itself.
223
+ headings: [{ pattern: '^(\\[)[^\\[\\]]+\\]\\s*$' }],
224
+ tokenPairs: [],
225
+ fences: [],
226
+ inlineCode: [],
227
+ tabWidth: 2,
228
+ delimited: false,
229
+ },
230
+ bash: {
231
+ lineComments: ['#'],
232
+ blockComments: [],
233
+ strings: [{ delim: '"' }, { delim: "'" }],
234
+ templates: [],
235
+ escape: '\\',
236
+ annotations: [],
237
+ keywords: ['function'],
238
+ modifiers: [],
239
+ headings: [],
240
+ tokenPairs: [],
241
+ fences: [],
242
+ inlineCode: [],
243
+ tabWidth: 4,
244
+ delimited: true,
245
+ },
246
+ html: {
247
+ lineComments: [],
248
+ blockComments: [['<!--', '-->']],
249
+ strings: [{ delim: '"' }, { delim: "'" }],
250
+ templates: [],
251
+ annotations: [],
252
+ keywords: [],
253
+ modifiers: [],
254
+ headings: [],
255
+ tokenPairs: [
256
+ { open: '<', close: '</', shape: 'asymmetric' },
257
+ { open: '<img', close: '', shape: 'selfClosing' },
258
+ { open: '<br', close: '', shape: 'selfClosing' },
259
+ ],
260
+ fences: [],
261
+ inlineCode: [],
262
+ tabWidth: 2,
263
+ delimited: false,
264
+ },
265
+ markdoc: {
266
+ // Markdown's masker is recursive — fenced blocks and inline code spans
267
+ // that frequently contain the very tokens being counted. SPEC-131 is
268
+ // explicit that this is "not the same ~40 lines" as the C family, so it
269
+ // is WORK-588's, alongside the strategies that need it. The shapes
270
+ // below are declared now; nothing masks them yet.
271
+ lineComments: [],
272
+ blockComments: [['<!--', '-->']],
273
+ strings: [],
274
+ templates: [],
275
+ annotations: [],
276
+ keywords: [],
277
+ modifiers: [],
278
+ headings: [{ pattern: '^(#{1,6})\\s+\\S' }],
279
+ tokenPairs: [
280
+ { open: '{%', close: '{% /', shape: 'asymmetric' },
281
+ { open: '```', close: '```', shape: 'symmetric' },
282
+ { open: '{%', close: '/%}', shape: 'selfClosing' },
283
+ ],
284
+ fences: ['```', '~~~'],
285
+ inlineCode: ['`'],
286
+ tabWidth: 2,
287
+ delimited: false,
288
+ },
289
+ svelte: {
290
+ lineComments: [],
291
+ blockComments: [['<!--', '-->']],
292
+ strings: [{ delim: '"' }, { delim: "'" }],
293
+ templates: [],
294
+ annotations: [],
295
+ keywords: [],
296
+ modifiers: [],
297
+ headings: [],
298
+ tokenPairs: [{ open: '<', close: '</', shape: 'asymmetric' }],
299
+ fences: [],
300
+ inlineCode: [],
301
+ tabWidth: 2,
302
+ delimited: false,
303
+ },
304
+ vue: {
305
+ lineComments: [],
306
+ blockComments: [['<!--', '-->']],
307
+ strings: [{ delim: '"' }, { delim: "'" }],
308
+ templates: [],
309
+ annotations: [],
310
+ keywords: [],
311
+ modifiers: [],
312
+ headings: [],
313
+ tokenPairs: [{ open: '<', close: '</', shape: 'asymmetric' }],
314
+ fences: [],
315
+ inlineCode: [],
316
+ tabWidth: 2,
317
+ delimited: false,
318
+ },
319
+ });
320
+ /**
321
+ * Merge language overrides onto a base table, mirroring `mergeThemeConfig()`.
322
+ *
323
+ * A key with no base entry is a **newly declared language**, not an override,
324
+ * and is taken whole — so the seam supports both extension surfaces D15 names
325
+ * without either of them shipping a config key yet. A key that does exist is
326
+ * merged field by field, with a provided array replacing the base array rather
327
+ * than concatenating: a project narrowing a language's comment prefixes must
328
+ * be able to remove one, which a concatenating merge makes impossible.
329
+ */
330
+ export function mergeLanguages(base, overrides) {
331
+ const merged = { ...base };
332
+ for (const [name, override] of Object.entries(overrides)) {
333
+ const existing = merged[name];
334
+ if (!existing) {
335
+ merged[name] = normalizeDefinition(override);
336
+ continue;
337
+ }
338
+ merged[name] = {
339
+ ...existing,
340
+ ...override,
341
+ };
342
+ }
343
+ return merged;
344
+ }
345
+ /** Fill a partial definition out to a complete one — an undeclared field is
346
+ * empty rather than inherited from an unrelated language. */
347
+ function normalizeDefinition(partial) {
348
+ return {
349
+ lineComments: partial.lineComments ?? [],
350
+ blockComments: partial.blockComments ?? [],
351
+ strings: partial.strings ?? [],
352
+ templates: partial.templates ?? [],
353
+ escape: partial.escape,
354
+ annotations: partial.annotations ?? [],
355
+ keywords: partial.keywords ?? [],
356
+ modifiers: partial.modifiers ?? [],
357
+ headings: partial.headings ?? [],
358
+ tokenPairs: partial.tokenPairs ?? [],
359
+ fences: partial.fences ?? [],
360
+ inlineCode: partial.inlineCode ?? [],
361
+ tabWidth: partial.tabWidth ?? 4,
362
+ delimited: partial.delimited ?? false,
363
+ };
364
+ }
365
+ /**
366
+ * Look up the lexical definition for a file path or language identifier.
367
+ *
368
+ * Accepts what `inferLanguage` accepts (a path, an extension, or a bare
369
+ * extension) as well as a language id directly. Returns `undefined` for a
370
+ * language not in the table — the caller must treat that as "no lexical
371
+ * knowledge", never as a default.
372
+ */
373
+ export function resolveLanguage(pathOrLang, table = BASE_LANGUAGES) {
374
+ if (typeof pathOrLang !== 'string' || pathOrLang.length === 0)
375
+ return undefined;
376
+ // A language id wins over extension inference, so `resolveLanguage('css')`
377
+ // works without dressing it up as a filename.
378
+ const direct = table[pathOrLang.toLowerCase()];
379
+ if (direct)
380
+ return direct;
381
+ return table[inferLanguage(pathOrLang)];
382
+ }
383
+ //# sourceMappingURL=languages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"languages.js","sourceRoot":"","sources":["../../src/lib/languages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
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
+ export interface DiffHunk {
9
+ type: 'equal' | 'add' | 'remove';
10
+ text: string;
11
+ }
12
+ /**
13
+ * Compute a line-level diff using LCS (Longest Common Subsequence).
14
+ *
15
+ * Returns hunks with type and raw text. Presentation — highlighting, gutters,
16
+ * terminal colour — is the caller's.
17
+ */
18
+ export declare function computeLineDiff(before: string, after: string): DiffHunk[];
19
+ /**
20
+ * A one-line summary of what changed between two slices.
21
+ *
22
+ * D7's example reads "+2 fields, 1 removed", which requires *interpreting* the
23
+ * diff rather than reporting it. The spec left the granularity open; this is
24
+ * the settled answer, and the reasoning is recorded because it was a real
25
+ * choice:
26
+ *
27
+ * Counting added and removed lines is cheap and honest. Naming *fields* would
28
+ * mean parsing the slice, which needs a language-aware layer this feature does
29
+ * not have and SPEC-131 D1 deliberately declined to build. A count that says
30
+ * "3 added, 1 removed" tells an author how much to expect; a count that claimed
31
+ * "2 fields" while actually counting lines would be worse than the cheap
32
+ * version, because it would sound authoritative.
33
+ */
34
+ export declare function summarizeDiff(before: string, after: string): string;
35
+ //# sourceMappingURL=line-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-diff.d.ts","sourceRoot":"","sources":["../../src/lib/line-diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAoCzE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAUnE"}