@markup-carve/carve-lsp 0.1.2 → 0.1.3
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.
- package/README.md +11 -3
- package/dist/analyze.d.ts +9 -1
- package/dist/analyze.js +175 -14
- package/dist/analyze.js.map +1 -1
- package/dist/analyze.test.js +22 -1
- package/dist/analyze.test.js.map +1 -1
- package/dist/captions.d.ts +49 -0
- package/dist/captions.js +124 -0
- package/dist/captions.js.map +1 -0
- package/dist/completion.d.ts +1 -1
- package/dist/completion.js +49 -3
- package/dist/completion.js.map +1 -1
- package/dist/composite-figure-crossref.test.d.ts +1 -0
- package/dist/composite-figure-crossref.test.js +265 -0
- package/dist/composite-figure-crossref.test.js.map +1 -0
- package/dist/composite-figure.test.d.ts +1 -0
- package/dist/composite-figure.test.js +76 -0
- package/dist/composite-figure.test.js.map +1 -0
- package/dist/definition.d.ts +4 -2
- package/dist/definition.js +28 -5
- package/dist/definition.js.map +1 -1
- package/dist/dependencies.d.ts +15 -0
- package/dist/dependencies.js +59 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/diagnostic-scheduler.d.ts +58 -0
- package/dist/diagnostic-scheduler.js +70 -0
- package/dist/diagnostic-scheduler.js.map +1 -0
- package/dist/diagnostic-scheduler.test.d.ts +1 -0
- package/dist/diagnostic-scheduler.test.js +75 -0
- package/dist/diagnostic-scheduler.test.js.map +1 -0
- package/dist/folding.d.ts +1 -0
- package/dist/folding.js +36 -1
- package/dist/folding.js.map +1 -1
- package/dist/folding.test.js +6 -1
- package/dist/folding.test.js.map +1 -1
- package/dist/hover.js +58 -19
- package/dist/hover.js.map +1 -1
- package/dist/include-cache.d.ts +26 -0
- package/dist/include-cache.js +74 -0
- package/dist/include-cache.js.map +1 -0
- package/dist/include-definition-denial.test.d.ts +1 -0
- package/dist/include-definition-denial.test.js +86 -0
- package/dist/include-definition-denial.test.js.map +1 -0
- package/dist/include-definition.d.ts +3 -0
- package/dist/include-definition.js +37 -0
- package/dist/include-definition.js.map +1 -0
- package/dist/include-features.test.d.ts +1 -0
- package/dist/include-features.test.js +133 -0
- package/dist/include-features.test.js.map +1 -0
- package/dist/include-path.d.ts +6 -0
- package/dist/include-path.js +31 -2
- package/dist/include-path.js.map +1 -1
- package/dist/include-settings.d.ts +2 -0
- package/dist/include-settings.js +1 -0
- package/dist/include-settings.js.map +1 -1
- package/dist/includes.d.ts +8 -0
- package/dist/includes.js +28 -7
- package/dist/includes.js.map +1 -1
- package/dist/references.d.ts +2 -0
- package/dist/references.js +113 -21
- package/dist/references.js.map +1 -1
- package/dist/semantic.js +14 -0
- package/dist/semantic.js.map +1 -1
- package/dist/semantic.test.js +6 -0
- package/dist/semantic.test.js.map +1 -1
- package/dist/server.js +128 -15
- package/dist/server.js.map +1 -1
- package/dist/versioned-cache.d.ts +8 -0
- package/dist/versioned-cache.js +17 -0
- package/dist/versioned-cache.js.map +1 -0
- package/dist/versioned-cache.test.d.ts +1 -0
- package/dist/versioned-cache.test.js +13 -0
- package/dist/versioned-cache.test.js.map +1 -0
- package/package.json +2 -2
package/dist/hover.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MarkupKind } from 'vscode-languageserver/node.js';
|
|
2
2
|
import { parse, resolve, } from '@markup-carve/carve';
|
|
3
3
|
import { astColumnToCharacter, characterToAstColumn, sourceLines } from './position.js';
|
|
4
|
+
import { captionTargetById } from './captions.js';
|
|
4
5
|
const rules = [
|
|
5
6
|
{
|
|
6
7
|
pattern: /#{1,6}/g,
|
|
@@ -82,8 +83,12 @@ function astHoverAt(doc, position, lines) {
|
|
|
82
83
|
character: characterToAstColumn(lines[position.line] ?? '', position.character) - 1,
|
|
83
84
|
};
|
|
84
85
|
const matches = [];
|
|
86
|
+
// A crossref's help depends on what the id NAMES, so the whole document is in
|
|
87
|
+
// scope for it while every other rule reads one node. It is looked up through
|
|
88
|
+
// this resolver rather than from inside the inline walk.
|
|
89
|
+
const resolveRef = (id) => captionTargetById(doc, id);
|
|
85
90
|
for (const node of doc.children)
|
|
86
|
-
collectBlock(matches, node, cursor);
|
|
91
|
+
collectBlock(matches, node, cursor, resolveRef);
|
|
87
92
|
matches.sort((a, b) => spanSize(a.pos) - spanSize(b.pos));
|
|
88
93
|
const match = matches[0];
|
|
89
94
|
if (!match)
|
|
@@ -96,53 +101,58 @@ function astHoverAt(doc, position, lines) {
|
|
|
96
101
|
range: toRange(match.pos, lines),
|
|
97
102
|
};
|
|
98
103
|
}
|
|
99
|
-
function collectBlock(matches, node, position) {
|
|
104
|
+
function collectBlock(matches, node, position, resolveRef) {
|
|
100
105
|
addMatch(matches, node.pos, position, blockContents(node));
|
|
101
106
|
switch (node.type) {
|
|
102
107
|
case 'heading':
|
|
103
|
-
collectInline(matches, node.children, position);
|
|
108
|
+
collectInline(matches, node.children, position, resolveRef);
|
|
104
109
|
break;
|
|
105
110
|
case 'paragraph':
|
|
106
|
-
collectInline(matches, node.children, position);
|
|
111
|
+
collectInline(matches, node.children, position, resolveRef);
|
|
107
112
|
break;
|
|
108
113
|
case 'block_quote':
|
|
109
|
-
node.children.forEach((child) => collectBlock(matches, child, position));
|
|
114
|
+
node.children.forEach((child) => collectBlock(matches, child, position, resolveRef));
|
|
110
115
|
break;
|
|
111
116
|
case 'list':
|
|
112
|
-
node.items.forEach((item) => item.children.forEach((child) => collectBlock(matches, child, position)));
|
|
117
|
+
node.items.forEach((item) => item.children.forEach((child) => collectBlock(matches, child, position, resolveRef)));
|
|
113
118
|
break;
|
|
114
119
|
case 'admonition':
|
|
115
120
|
case 'div':
|
|
116
|
-
node.children.forEach((child) => collectBlock(matches, child, position));
|
|
121
|
+
node.children.forEach((child) => collectBlock(matches, child, position, resolveRef));
|
|
117
122
|
if (node.type === 'admonition' && node.title)
|
|
118
|
-
collectInline(matches, node.title, position);
|
|
123
|
+
collectInline(matches, node.title, position, resolveRef);
|
|
119
124
|
break;
|
|
120
125
|
case 'definition_list':
|
|
121
126
|
node.items.forEach((item) => {
|
|
122
|
-
item.terms.forEach((term) => collectInline(matches, term, position));
|
|
123
|
-
item.definitions.forEach((definition) => definition.forEach((child) => collectBlock(matches, child, position)));
|
|
127
|
+
item.terms.forEach((term) => collectInline(matches, term, position, resolveRef));
|
|
128
|
+
item.definitions.forEach((definition) => definition.forEach((child) => collectBlock(matches, child, position, resolveRef)));
|
|
124
129
|
});
|
|
125
130
|
break;
|
|
126
131
|
case 'figure':
|
|
127
|
-
collectBlock(matches, node.target, position);
|
|
128
|
-
collectInline(matches, node.caption, position);
|
|
132
|
+
collectBlock(matches, node.target, position, resolveRef);
|
|
133
|
+
collectInline(matches, node.caption, position, resolveRef);
|
|
134
|
+
break;
|
|
135
|
+
case 'figure_group':
|
|
136
|
+
node.children.forEach((child) => collectBlock(matches, child, position, resolveRef));
|
|
137
|
+
if (node.caption)
|
|
138
|
+
collectInline(matches, node.caption, position, resolveRef);
|
|
129
139
|
break;
|
|
130
140
|
case 'table':
|
|
131
141
|
if (node.caption)
|
|
132
|
-
collectInline(matches, node.caption, position);
|
|
133
|
-
node.rows.forEach((row) => row.cells.forEach((cell) => collectInline(matches, cell.children, position)));
|
|
142
|
+
collectInline(matches, node.caption, position, resolveRef);
|
|
143
|
+
node.rows.forEach((row) => row.cells.forEach((cell) => collectInline(matches, cell.children, position, resolveRef)));
|
|
134
144
|
break;
|
|
135
145
|
}
|
|
136
146
|
}
|
|
137
|
-
function collectInline(matches, nodes, position) {
|
|
147
|
+
function collectInline(matches, nodes, position, resolveRef) {
|
|
138
148
|
for (const node of nodes) {
|
|
139
|
-
addMatch(matches, node.pos, position, inlineContents(node));
|
|
149
|
+
addMatch(matches, node.pos, position, inlineContents(node, resolveRef));
|
|
140
150
|
const children = node.children;
|
|
141
151
|
if (Array.isArray(children))
|
|
142
|
-
collectInline(matches, children, position);
|
|
152
|
+
collectInline(matches, children, position, resolveRef);
|
|
143
153
|
const content = node.content;
|
|
144
154
|
if (Array.isArray(content))
|
|
145
|
-
collectInline(matches, content, position);
|
|
155
|
+
collectInline(matches, content, position, resolveRef);
|
|
146
156
|
}
|
|
147
157
|
}
|
|
148
158
|
function addMatch(matches, pos, position, contents) {
|
|
@@ -168,11 +178,15 @@ function blockContents(node) {
|
|
|
168
178
|
return '**Admonition**\n\nTyped `:::` fences create admonition blocks.';
|
|
169
179
|
case 'div':
|
|
170
180
|
return '**Div**\n\nBare `:::` fences create generic container blocks.';
|
|
181
|
+
case 'figure_group':
|
|
182
|
+
return ('**Composite Figure**\n\nA bare `::: figure` fence is one figure of ordered panels. ' +
|
|
183
|
+
'The `^ ` line after the closing fence captions the whole group. ' +
|
|
184
|
+
'An opener carrying a title or a `[label]` stays a generic container instead.');
|
|
171
185
|
default:
|
|
172
186
|
return null;
|
|
173
187
|
}
|
|
174
188
|
}
|
|
175
|
-
function inlineContents(node) {
|
|
189
|
+
function inlineContents(node, resolveRef) {
|
|
176
190
|
switch (node.type) {
|
|
177
191
|
case 'strong':
|
|
178
192
|
return '**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`.';
|
|
@@ -202,10 +216,35 @@ function inlineContents(node) {
|
|
|
202
216
|
return '**Tag**\n\nTags use `#name`.';
|
|
203
217
|
case 'span':
|
|
204
218
|
return '**Span**\n\nInline spans use `[text]{attrs}`.';
|
|
219
|
+
case 'heading_ref':
|
|
220
|
+
return crossrefContents(node, resolveRef);
|
|
205
221
|
default:
|
|
206
222
|
return null;
|
|
207
223
|
}
|
|
208
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* A `</#id>` used to fall through this switch entirely, so the LEXICAL rules
|
|
227
|
+
* above took it and reported the `#` inside the reference as a heading marker.
|
|
228
|
+
* It now says what the reference resolves to, which for a composite figure's
|
|
229
|
+
* panel is the group's number plus its letter (PART 9 §4c).
|
|
230
|
+
*
|
|
231
|
+
* A heading target keeps the generic wording: the heading's own text is what
|
|
232
|
+
* the reference renders, and it is already on screen.
|
|
233
|
+
*/
|
|
234
|
+
function crossrefContents(node, resolveRef) {
|
|
235
|
+
const generic = '**Cross-reference**\n\nA `</#id>` reference links to the heading or captioned host carrying that id.';
|
|
236
|
+
const id = node.target;
|
|
237
|
+
if (typeof id !== 'string')
|
|
238
|
+
return generic;
|
|
239
|
+
const target = resolveRef(id);
|
|
240
|
+
if (!target)
|
|
241
|
+
return generic;
|
|
242
|
+
if (target.text === null) {
|
|
243
|
+
return ('**Cross-reference**\n\nAn unnumbered ' + target.kind + '. It is an anchor, but it drew no ' +
|
|
244
|
+
'number, so this reference has no caption text to render.');
|
|
245
|
+
}
|
|
246
|
+
return '**Cross-reference**\n\nResolves to **' + target.text + '** (' + target.kind + ').';
|
|
247
|
+
}
|
|
209
248
|
function contains(pos, position) {
|
|
210
249
|
if (pos.startColumn === undefined ||
|
|
211
250
|
pos.endColumn === undefined ||
|
package/dist/hover.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover.js","sourceRoot":"","sources":["../src/hover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA6B,MAAM,+BAA+B,CAAA;AACrF,OAAO,EACL,KAAK,EACL,OAAO,GAKR,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"hover.js","sourceRoot":"","sources":["../src/hover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA6B,MAAM,+BAA+B,CAAA;AACrF,OAAO,EACL,KAAK,EACL,OAAO,GAKR,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AACvF,OAAO,EAAE,iBAAiB,EAAsB,MAAM,eAAe,CAAA;AAOrE,MAAM,KAAK,GAAgB;IACzB;QACE,OAAO,EAAE,SAAS;QAClB,QAAQ,EAAE,8DAA8D;KACzE;IACD;QACE,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,kEAAkE;KAC7E;IACD;QACE,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,+DAA+D;KAC1E;IACD;QACE,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,wEAAwE;KACnF;IACD;QACE,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,wEAAwE;KACnF;IACD;QACE,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,2FAA2F;KACtG;IACD;QACE,OAAO,EAAE,yCAAyC;QAClD,QAAQ,EAAE,8CAA8C;KACzD;IACD;QACE,OAAO,EAAE,0CAA0C;QACnD,QAAQ,EAAE,wEAAwE;KACnF;IACD;QACE,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,sDAAsD;KACjE;CACF,CAAA;AAED,MAAM,UAAU,OAAO,CAAC,MAAc,EAAE,QAAkB;IACxD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAEjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QACjE,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;IACrE,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAA;QAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAA;YAC9B,MAAM,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;YACnC,IAAI,QAAQ,CAAC,SAAS,GAAG,KAAK,IAAI,QAAQ,CAAC,SAAS,GAAG,GAAG;gBAAE,SAAQ;YACpE,OAAO;gBACL,QAAQ,EAAE;oBACR,IAAI,EAAE,UAAU,CAAC,QAAQ;oBACzB,KAAK,EAAE,IAAI,CAAC,QAAQ;iBACrB;gBACD,KAAK,EAAE;oBACL,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE;oBAChD,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE;iBAC7C;aACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,UAAU,CAAC,GAAa,EAAE,QAAkB,EAAE,KAAe;IACpE,4EAA4E;IAC5E,wEAAwE;IACxE,yDAAyD;IACzD,MAAM,MAAM,GAAa;QACvB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC;KACpF,CAAA;IACD,MAAM,OAAO,GAAqD,EAAE,CAAA;IACpE,8EAA8E;IAC9E,8EAA8E;IAC9E,yDAAyD;IACzD,MAAM,UAAU,GAAgB,CAAC,EAAE,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAClE,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ;QAAE,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;IAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACxB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,OAAO;QACL,QAAQ,EAAE;YACR,IAAI,EAAE,UAAU,CAAC,QAAQ;YACzB,KAAK,EAAE,KAAK,CAAC,QAAQ;SACtB;QACD,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC;KACjC,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CACnB,OAAyD,EACzD,IAAe,EACf,QAAkB,EAClB,UAAuB;IAEvB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,SAAS;YACZ,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YAC3D,MAAK;QACP,KAAK,WAAW;YACd,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YAC3D,MAAK;QACP,KAAK,aAAa;YAChB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;YACpF,MAAK;QACP,KAAK,MAAM;YACT,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;YAClH,MAAK;QACP,KAAK,YAAY,CAAC;QAClB,KAAK,KAAK;YACR,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;YACpF,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,KAAK;gBAAE,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YACtG,MAAK;QACP,KAAK,iBAAiB;YACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;gBAChF,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE,CACtC,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAClF,CAAA;YACH,CAAC,CAAC,CAAA;YACF,MAAK;QACP,KAAK,QAAQ;YACX,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YACxD,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YAC1D,MAAK;QACP,KAAK,cAAc;YACjB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;YACpF,IAAI,IAAI,CAAC,OAAO;gBAAE,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YAC5E,MAAK;QACP,KAAK,OAAO;YACV,IAAI,IAAI,CAAC,OAAO;gBAAE,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;YAC5E,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;YACpH,MAAK;IACT,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CACpB,OAAyD,EACzD,KAAmB,EACnB,QAAkB,EAClB,UAAuB;IAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;QACvE,MAAM,QAAQ,GAAI,IAAoC,CAAC,QAAQ,CAAA;QAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAAE,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;QACnF,MAAM,OAAO,GAAI,IAAmC,CAAC,OAAO,CAAA;QAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;IACnF,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CACf,OAAyD,EACzD,GAA+B,EAC/B,QAAkB,EAClB,QAAuB;IAEvB,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;QAAE,OAAM;IACzD,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,SAAS,aAAa,CAAC,IAAe;IACpC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,SAAS;YACZ,OAAO,8DAA8D,CAAA;QACvE,KAAK,YAAY;YACf,OAAO,gFAAgF,CAAA;QACzF,KAAK,WAAW;YACd,OAAO,kFAAkF,CAAA;QAC3F,KAAK,aAAa;YAChB,OAAO,mEAAmE,CAAA;QAC5E,KAAK,MAAM;YACT,OAAO,sEAAsE,CAAA;QAC/E,KAAK,OAAO;YACV,OAAO,iDAAiD,CAAA;QAC1D,KAAK,YAAY;YACf,OAAO,gEAAgE,CAAA;QACzE,KAAK,KAAK;YACR,OAAO,+DAA+D,CAAA;QACxE,KAAK,cAAc;YACjB,OAAO,CACL,qFAAqF;gBACrF,kEAAkE;gBAClE,8EAA8E,CAC/E,CAAA;QACH;YACE,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAAgB,EAAE,UAAuB;IAC/D,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,kEAAkE,CAAA;QAC3E,KAAK,UAAU;YACb,OAAO,+DAA+D,CAAA;QACxE,KAAK,WAAW;YACd,OAAO,wEAAwE,CAAA;QACjF,KAAK,QAAQ;YACX,OAAO,wEAAwE,CAAA;QACjF,KAAK,WAAW;YACd,OAAO,iHAAiH,CAAA;QAC1H,KAAK,aAAa;YAChB,OAAO,uHAAuH,CAAA;QAChI,KAAK,WAAW;YACd,OAAO,+GAA+G,CAAA;QACxH,KAAK,MAAM;YACT,OAAO,sDAAsD,CAAA;QAC/D,KAAK,gBAAgB;YACnB,OAAO,kKAAkK,CAAA;QAC3K,KAAK,MAAM;YACT,OAAO,uEAAuE,CAAA;QAChF,KAAK,OAAO;YACV,OAAO,wEAAwE,CAAA;QACjF,KAAK,SAAS;YACZ,OAAO,sCAAsC,CAAA;QAC/C,KAAK,KAAK;YACR,OAAO,8BAA8B,CAAA;QACvC,KAAK,MAAM;YACT,OAAO,+CAA+C,CAAA;QACxD,KAAK,aAAa;YAChB,OAAO,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QAC3C;YACE,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC;AAID;;;;;;;;GAQG;AACH,SAAS,gBAAgB,CAAC,IAAgB,EAAE,UAAuB;IACjE,MAAM,OAAO,GACX,sGAAsG,CAAA;IACxG,MAAM,EAAE,GAAI,IAA6B,CAAC,MAAM,CAAA;IAChD,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAA;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,CAAA;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAA;IAC3B,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO,CACL,uCAAuC,GAAG,MAAM,CAAC,IAAI,GAAG,oCAAoC;YAC5F,0DAA0D,CAC3D,CAAA;IACH,CAAC;IACD,OAAO,uCAAuC,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;AAC5F,CAAC;AAED,SAAS,QAAQ,CAAC,GAAmB,EAAE,QAAkB;IACvD,IACE,GAAG,CAAC,WAAW,KAAK,SAAS;QAC7B,GAAG,CAAC,SAAS,KAAK,SAAS;QAC3B,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,SAAS;QACjC,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,EAC/B,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,GAAG,CAAC,GAAG,GAAG,CAAC,WAAW;QAAE,OAAO,KAAK,CAAA;IACjG,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC,SAAS,GAAG,CAAC,GAAG,GAAG,CAAC,SAAS;QAAE,OAAO,KAAK,CAAA;IAC7F,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,OAAO,CAAC,GAAmB,EAAE,KAAe;IACnD,OAAO;QACL,KAAK,EAAE;YACL,IAAI,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC;YACvB,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC;SACtF;QACD,GAAG,EAAE;YACH,IAAI,EAAE,GAAG,CAAC,OAAO,GAAG,CAAC;YACrB,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC;SAClF;KACF,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAmB;IACnC,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,WAAW,CAAA;IACxG,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAA;AAC/F,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface CachedInclude {
|
|
2
|
+
source: string;
|
|
3
|
+
bytes: number;
|
|
4
|
+
}
|
|
5
|
+
/** Bounded LRU cache for include source, validated by file metadata. */
|
|
6
|
+
export declare class IncludeSourceCache {
|
|
7
|
+
#private;
|
|
8
|
+
readonly maxEntries: number;
|
|
9
|
+
constructor(maxEntries?: number);
|
|
10
|
+
get(id: string, mtimeMs: number, size: number): CachedInclude | undefined;
|
|
11
|
+
set(id: string, mtimeMs: number, size: number, value: CachedInclude): void;
|
|
12
|
+
invalidate(id: string): void;
|
|
13
|
+
clear(): void;
|
|
14
|
+
get size(): number;
|
|
15
|
+
}
|
|
16
|
+
/** Bounded LRU cache for parsed child documents. */
|
|
17
|
+
export declare class IncludeParseCache {
|
|
18
|
+
#private;
|
|
19
|
+
readonly maxEntries: number;
|
|
20
|
+
constructor(maxEntries?: number);
|
|
21
|
+
get(id: string, version: string): Document | undefined;
|
|
22
|
+
set(id: string, version: string, document: Document): void;
|
|
23
|
+
invalidate(id: string): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
}
|
|
26
|
+
import type { Document } from '@markup-carve/carve';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** Bounded LRU cache for include source, validated by file metadata. */
|
|
2
|
+
export class IncludeSourceCache {
|
|
3
|
+
maxEntries;
|
|
4
|
+
#entries = new Map();
|
|
5
|
+
constructor(maxEntries = 128) {
|
|
6
|
+
this.maxEntries = maxEntries;
|
|
7
|
+
}
|
|
8
|
+
get(id, mtimeMs, size) {
|
|
9
|
+
const entry = this.#entries.get(id);
|
|
10
|
+
if (!entry || entry.mtimeMs !== mtimeMs || entry.size !== size) {
|
|
11
|
+
if (entry)
|
|
12
|
+
this.#entries.delete(id);
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
this.#entries.delete(id);
|
|
16
|
+
this.#entries.set(id, entry);
|
|
17
|
+
return { source: entry.source, bytes: entry.bytes };
|
|
18
|
+
}
|
|
19
|
+
set(id, mtimeMs, size, value) {
|
|
20
|
+
this.#entries.delete(id);
|
|
21
|
+
this.#entries.set(id, { ...value, mtimeMs, size });
|
|
22
|
+
while (this.#entries.size > this.maxEntries) {
|
|
23
|
+
const oldest = this.#entries.keys().next().value;
|
|
24
|
+
if (oldest === undefined)
|
|
25
|
+
break;
|
|
26
|
+
this.#entries.delete(oldest);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
invalidate(id) {
|
|
30
|
+
this.#entries.delete(id);
|
|
31
|
+
}
|
|
32
|
+
clear() {
|
|
33
|
+
this.#entries.clear();
|
|
34
|
+
}
|
|
35
|
+
get size() {
|
|
36
|
+
return this.#entries.size;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Bounded LRU cache for parsed child documents. */
|
|
40
|
+
export class IncludeParseCache {
|
|
41
|
+
maxEntries;
|
|
42
|
+
#entries = new Map();
|
|
43
|
+
constructor(maxEntries = 128) {
|
|
44
|
+
this.maxEntries = maxEntries;
|
|
45
|
+
}
|
|
46
|
+
get(id, version) {
|
|
47
|
+
const entry = this.#entries.get(id);
|
|
48
|
+
if (!entry || entry.version !== version) {
|
|
49
|
+
if (entry)
|
|
50
|
+
this.#entries.delete(id);
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
this.#entries.delete(id);
|
|
54
|
+
this.#entries.set(id, entry);
|
|
55
|
+
return entry.document;
|
|
56
|
+
}
|
|
57
|
+
set(id, version, document) {
|
|
58
|
+
this.#entries.delete(id);
|
|
59
|
+
this.#entries.set(id, { version, document });
|
|
60
|
+
while (this.#entries.size > this.maxEntries) {
|
|
61
|
+
const oldest = this.#entries.keys().next().value;
|
|
62
|
+
if (oldest === undefined)
|
|
63
|
+
break;
|
|
64
|
+
this.#entries.delete(oldest);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
invalidate(id) {
|
|
68
|
+
this.#entries.delete(id);
|
|
69
|
+
}
|
|
70
|
+
clear() {
|
|
71
|
+
this.#entries.clear();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=include-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-cache.js","sourceRoot":"","sources":["../src/include-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { mkdtempSync, writeFileSync, symlinkSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { definitionAt } from './definition.js';
|
|
8
|
+
import { includeDefinitionAt } from './include-definition.js';
|
|
9
|
+
import { fileSystemResolver } from './include-path.js';
|
|
10
|
+
/*
|
|
11
|
+
* THE DENIAL HALF of include go-to-definition.
|
|
12
|
+
*
|
|
13
|
+
* `include-features.test.ts` covers the resolvable case - a directive whose
|
|
14
|
+
* target exists inside the root navigates to it. What no test covered is the
|
|
15
|
+
* other branch: a target the resolver REFUSES must not navigate at all.
|
|
16
|
+
*
|
|
17
|
+
* That branch is the whole security value of routing navigation through
|
|
18
|
+
* `include-path.ts` rather than joining the path locally. Without it,
|
|
19
|
+
* go-to-definition is a way around the containment PART 9 section 19 puts on
|
|
20
|
+
* include resolution: the editor opens a file the include pass would not read.
|
|
21
|
+
*
|
|
22
|
+
* It was verified to be uncovered before these were written. Replacing
|
|
23
|
+
* `if (!resolved.ok) return null` in include-definition.ts with a best-effort
|
|
24
|
+
* location left the whole suite green at 224 of 224 - a guard that cannot fail.
|
|
25
|
+
* Each test below fails under that mutation.
|
|
26
|
+
*/
|
|
27
|
+
function workspace() {
|
|
28
|
+
const root = mkdtempSync(path.join(tmpdir(), 'carve-lsp-incdef-'));
|
|
29
|
+
const child = path.join(root, 'chapter-1.crv');
|
|
30
|
+
writeFileSync(child, '# Chapter One\n');
|
|
31
|
+
return { root, doc: path.join(root, 'book.crv'), child };
|
|
32
|
+
}
|
|
33
|
+
const optionsFor = (root, sourcePath) => ({
|
|
34
|
+
resolver: fileSystemResolver(root, {}),
|
|
35
|
+
includeRoot: root,
|
|
36
|
+
sourcePath,
|
|
37
|
+
});
|
|
38
|
+
test('a target outside the root does not navigate', () => {
|
|
39
|
+
const { root, doc } = workspace();
|
|
40
|
+
writeFileSync(path.join(path.dirname(root), 'outside.crv'), 'secret\n');
|
|
41
|
+
const at = includeDefinitionAt('{{ ../outside.crv }}\n', { line: 0, character: 4 }, optionsFor(root, doc));
|
|
42
|
+
assert.equal(at, null);
|
|
43
|
+
});
|
|
44
|
+
test('a symlink escaping the root does not navigate', () => {
|
|
45
|
+
const { root, doc } = workspace();
|
|
46
|
+
const outsideDir = mkdtempSync(path.join(tmpdir(), 'carve-lsp-outside-'));
|
|
47
|
+
const secret = path.join(outsideDir, 'secret.crv');
|
|
48
|
+
writeFileSync(secret, 'secret\n');
|
|
49
|
+
symlinkSync(secret, path.join(root, 'link.crv'));
|
|
50
|
+
const at = includeDefinitionAt('{{ link.crv }}\n', { line: 0, character: 4 }, optionsFor(root, doc));
|
|
51
|
+
assert.equal(at, null);
|
|
52
|
+
});
|
|
53
|
+
test('an absolute path does not navigate while absolutes are denied', () => {
|
|
54
|
+
const { root, doc, child } = workspace();
|
|
55
|
+
const at = includeDefinitionAt(`{{ ${child} }}\n`, { line: 0, character: 4 }, optionsFor(root, doc));
|
|
56
|
+
assert.equal(at, null);
|
|
57
|
+
});
|
|
58
|
+
test('a missing target does not navigate', () => {
|
|
59
|
+
const { root, doc } = workspace();
|
|
60
|
+
const at = includeDefinitionAt('{{ nope.crv }}\n', { line: 0, character: 4 }, optionsFor(root, doc));
|
|
61
|
+
assert.equal(at, null);
|
|
62
|
+
});
|
|
63
|
+
/*
|
|
64
|
+
* Three properties around the branch rather than inside it. The first two are
|
|
65
|
+
* NOT killed by the denial mutation above - they are controls for different
|
|
66
|
+
* mistakes, and are labelled as such rather than presented as proof of the
|
|
67
|
+
* guard.
|
|
68
|
+
*/
|
|
69
|
+
test('with no resolver the include branch is inert (control)', () => {
|
|
70
|
+
const { root, doc } = workspace();
|
|
71
|
+
const uri = pathToFileURL(doc).toString();
|
|
72
|
+
assert.equal(includeDefinitionAt('{{ chapter-1.crv }}\n', { line: 0, character: 4 }, {}), null);
|
|
73
|
+
assert.equal(definitionAt(uri, '{{ chapter-1.crv }}\n', { line: 0, character: 4 }), null);
|
|
74
|
+
assert.ok(root);
|
|
75
|
+
});
|
|
76
|
+
test('a directive inside verbatim content is not a directive (control)', () => {
|
|
77
|
+
const { root, doc } = workspace();
|
|
78
|
+
const at = includeDefinitionAt('`{{ chapter-1.crv }}`\n', { line: 0, character: 6 }, optionsFor(root, doc));
|
|
79
|
+
assert.equal(at, null);
|
|
80
|
+
});
|
|
81
|
+
test('a CRLF document resolves the same offsets as LF', () => {
|
|
82
|
+
const { root, doc, child } = workspace();
|
|
83
|
+
const at = includeDefinitionAt('a\r\nb\r\n{{ chapter-1.crv }}\r\n', { line: 2, character: 5 }, optionsFor(root, doc));
|
|
84
|
+
assert.equal(at?.uri, pathToFileURL(child).toString());
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=include-definition-denial.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-definition-denial.test.js","sourceRoot":"","sources":["../src/include-definition-denial.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD;;;;;;;;;;;;;;;;GAgBG;AAEH,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAA;IAC9C,aAAa,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAA;IACvC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,CAAA;AAC1D,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,UAAkB,EAAE,EAAE,CAAC,CAAC;IACxD,QAAQ,EAAE,kBAAkB,CAAC,IAAI,EAAE,EAAE,CAAC;IACtC,WAAW,EAAE,IAAI;IACjB,UAAU;CACX,CAAC,CAAA;AAEF,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;IACvD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IACjC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,EAAE,UAAU,CAAC,CAAA;IACvE,MAAM,EAAE,GAAG,mBAAmB,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1G,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AACxB,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IACjC,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAA;IACzE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IAClD,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACjC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;IAChD,MAAM,EAAE,GAAG,mBAAmB,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IACpG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AACxB,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,+DAA+D,EAAE,GAAG,EAAE;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;IACxC,MAAM,EAAE,GAAG,mBAAmB,CAAC,MAAM,KAAK,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IACpG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AACxB,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAC9C,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IACjC,MAAM,EAAE,GAAG,mBAAmB,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IACpG,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AACxB,CAAC,CAAC,CAAA;AAEF;;;;;GAKG;AAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;IAClE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IACjC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAA;IACzC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;IAC/F,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,uBAAuB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;IACzF,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAC5E,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;IACjC,MAAM,EAAE,GAAG,mBAAmB,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IAC3G,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;AACxB,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC3D,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;IACxC,MAAM,EAAE,GAAG,mBAAmB,CAAC,mCAAmC,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IACrH,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;AACxD,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
import { findDirectives } from './include-directive.js';
|
|
3
|
+
export function includeDefinitionAt(source, position, options) {
|
|
4
|
+
if (!options?.resolver)
|
|
5
|
+
return null;
|
|
6
|
+
const normalized = source.replace(/\r\n?/g, '\n');
|
|
7
|
+
const offset = offsetAt(normalized, position);
|
|
8
|
+
const directive = findDirectives(normalized).find((candidate) => offset >= candidate.start && offset < candidate.end);
|
|
9
|
+
if (!directive)
|
|
10
|
+
return null;
|
|
11
|
+
const stack = options.sourcePath === undefined ? [] : [options.sourcePath];
|
|
12
|
+
const resolved = options.resolver(directive.path, {
|
|
13
|
+
stack,
|
|
14
|
+
depth: 0,
|
|
15
|
+
...(options.sourcePath === undefined ? {} : { sourcePath: options.sourcePath }),
|
|
16
|
+
});
|
|
17
|
+
if (!resolved.ok)
|
|
18
|
+
return null;
|
|
19
|
+
return {
|
|
20
|
+
uri: pathToFileURL(resolved.id).toString(),
|
|
21
|
+
range: {
|
|
22
|
+
start: { line: 0, character: 0 },
|
|
23
|
+
end: { line: 0, character: 0 },
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function offsetAt(source, position) {
|
|
28
|
+
let offset = 0;
|
|
29
|
+
for (let line = 0; line < position.line; line += 1) {
|
|
30
|
+
const newline = source.indexOf('\n', offset);
|
|
31
|
+
if (newline < 0)
|
|
32
|
+
return source.length;
|
|
33
|
+
offset = newline + 1;
|
|
34
|
+
}
|
|
35
|
+
return Math.min(source.length, offset + position.character);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=include-definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-definition.js","sourceRoot":"","sources":["../src/include-definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAGvD,MAAM,UAAU,mBAAmB,CACjC,MAAc,EACd,QAAkB,EAClB,OAAmC;IAEnC,IAAI,CAAC,OAAO,EAAE,QAAQ;QAAE,OAAO,IAAI,CAAA;IACnC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC7C,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC,IAAI,CAC/C,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,IAAI,MAAM,GAAG,SAAS,CAAC,GAAG,CACnE,CAAA;IACD,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1E,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE;QAChD,KAAK;QACL,KAAK,EAAE,CAAC;QACR,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;KAChF,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA;IAC7B,OAAO;QACL,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;QAC1C,KAAK,EAAE;YACL,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;YAChC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;SAC/B;KACF,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc,EAAE,QAAkB;IAClD,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC5C,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,MAAM,CAAA;QACrC,MAAM,GAAG,OAAO,GAAG,CAAC,CAAA;IACtB,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;AAC7D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, statSync, symlinkSync, utimesSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { analyzeCarve } from './analyze.js';
|
|
8
|
+
import { DependencyIndex, watcherFor } from './dependencies.js';
|
|
9
|
+
import { definitionAt } from './definition.js';
|
|
10
|
+
import { IncludeSourceCache } from './include-cache.js';
|
|
11
|
+
import { fileSystemResolver } from './include-path.js';
|
|
12
|
+
import { parse, resolve } from '@markup-carve/carve';
|
|
13
|
+
import { IncludeParseCache } from './include-cache.js';
|
|
14
|
+
function fixture() {
|
|
15
|
+
const dir = realpathSync(mkdtempSync(path.join(tmpdir(), 'carve-lsp-features-')));
|
|
16
|
+
test.after(() => rmSync(dir, { recursive: true, force: true }));
|
|
17
|
+
return dir;
|
|
18
|
+
}
|
|
19
|
+
test('include cache is metadata-validated and LRU-bounded', () => {
|
|
20
|
+
const cache = new IncludeSourceCache(2);
|
|
21
|
+
cache.set('/a', 1, 1, { source: 'a', bytes: 1 });
|
|
22
|
+
cache.set('/b', 1, 1, { source: 'b', bytes: 1 });
|
|
23
|
+
assert.equal(cache.get('/a', 1, 1)?.source, 'a');
|
|
24
|
+
cache.set('/c', 1, 1, { source: 'c', bytes: 1 });
|
|
25
|
+
assert.equal(cache.get('/b', 1, 1), undefined);
|
|
26
|
+
assert.equal(cache.get('/a', 2, 1), undefined);
|
|
27
|
+
assert.equal(cache.size, 1);
|
|
28
|
+
});
|
|
29
|
+
test('parsed-child cache is version-validated', () => {
|
|
30
|
+
const cache = new IncludeParseCache();
|
|
31
|
+
const document = resolve(parse('# Cached\n'));
|
|
32
|
+
cache.set('/child', '1:9', document);
|
|
33
|
+
assert.equal(cache.get('/child', '1:9'), document);
|
|
34
|
+
assert.equal(cache.get('/child', '2:9'), undefined);
|
|
35
|
+
});
|
|
36
|
+
test('filesystem cache invalidates after an included file changes', () => {
|
|
37
|
+
const dir = fixture();
|
|
38
|
+
const child = path.join(dir, 'child.crv');
|
|
39
|
+
writeFileSync(child, '# Before\n');
|
|
40
|
+
const cache = new IncludeSourceCache();
|
|
41
|
+
const resolver = fileSystemResolver(dir, { cache });
|
|
42
|
+
const context = { stack: [path.join(dir, 'main.crv')], depth: 0 };
|
|
43
|
+
const first = resolver('child.crv', context);
|
|
44
|
+
assert.match(first.ok ? first.source : '', /Before/);
|
|
45
|
+
const prior = statSync(child).mtimeMs;
|
|
46
|
+
writeFileSync(child, '# After!\n');
|
|
47
|
+
utimesSync(child, new Date(), new Date(prior + 1000));
|
|
48
|
+
const next = resolver('child.crv', context);
|
|
49
|
+
assert.equal(next.ok && next.source, '# After!\n');
|
|
50
|
+
});
|
|
51
|
+
test('missing contained targets expose an absolute watch candidate', () => {
|
|
52
|
+
const dir = fixture();
|
|
53
|
+
const result = fileSystemResolver(dir)('later.crv', {
|
|
54
|
+
stack: [path.join(dir, 'main.crv')],
|
|
55
|
+
depth: 0,
|
|
56
|
+
});
|
|
57
|
+
assert.equal(result.ok, false);
|
|
58
|
+
assert.equal(result.ok ? undefined : result.watch, path.join(dir, 'later.crv'));
|
|
59
|
+
});
|
|
60
|
+
test('same missing spelling in different child directories produces two watchers', () => {
|
|
61
|
+
const dir = fixture();
|
|
62
|
+
mkdirSync(path.join(dir, 'a'));
|
|
63
|
+
mkdirSync(path.join(dir, 'b'));
|
|
64
|
+
writeFileSync(path.join(dir, 'a', 'chapter.crv'), '{{ missing.crv }}\n');
|
|
65
|
+
writeFileSync(path.join(dir, 'b', 'chapter.crv'), '{{ missing.crv }}\n');
|
|
66
|
+
const analysis = analyzeCarve('{{ a/chapter.crv }}\n{{ b/chapter.crv }}\n', {
|
|
67
|
+
includes: {
|
|
68
|
+
resolver: fileSystemResolver(dir),
|
|
69
|
+
sourcePath: path.join(dir, 'main.crv'),
|
|
70
|
+
includeRoot: dir,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
const missing = analysis.dependencies.filter((dependency) => !dependency.resolved);
|
|
74
|
+
assert.deepEqual(missing.map((dependency) => dependency.watch).sort(), [path.join(dir, 'a', 'missing.crv'), path.join(dir, 'b', 'missing.crv')]);
|
|
75
|
+
});
|
|
76
|
+
test('a missing target below an escaping symlink is never watched', () => {
|
|
77
|
+
const dir = fixture();
|
|
78
|
+
const outside = fixture();
|
|
79
|
+
mkdirSync(path.join(dir, 'inside'));
|
|
80
|
+
symlinkSync(outside, path.join(dir, 'inside', 'escape'));
|
|
81
|
+
const result = fileSystemResolver(dir)('inside/escape/later.crv', {
|
|
82
|
+
stack: [path.join(dir, 'main.crv')],
|
|
83
|
+
depth: 0,
|
|
84
|
+
});
|
|
85
|
+
assert.equal(result.ok, false);
|
|
86
|
+
assert.equal(result.ok ? undefined : result.denial, 'outside-root');
|
|
87
|
+
assert.equal(result.ok ? undefined : result.watch, undefined);
|
|
88
|
+
});
|
|
89
|
+
test('dependency index tracks reverse edges and meaningful watch-set changes', () => {
|
|
90
|
+
const index = new DependencyIndex();
|
|
91
|
+
assert.equal(index.update('file:///a', ['/child', '/missing']), true);
|
|
92
|
+
assert.equal(index.update('file:///a', ['/missing', '/child']), false);
|
|
93
|
+
index.update('file:///b', ['/child']);
|
|
94
|
+
assert.deepEqual(index.documentsFor('/child').sort(), ['file:///a', 'file:///b']);
|
|
95
|
+
assert.equal(index.remove('file:///a'), true);
|
|
96
|
+
assert.deepEqual(index.watchedPaths(), ['/child']);
|
|
97
|
+
});
|
|
98
|
+
test('watchers for missing directory trees root at an existing ancestor', () => {
|
|
99
|
+
const dir = fixture();
|
|
100
|
+
const watcher = watcherFor(path.join(dir, 'future', 'chapter.crv'));
|
|
101
|
+
assert.equal(watcher.globPattern.baseUri, pathToFileURL(dir).toString());
|
|
102
|
+
assert.equal(watcher.globPattern.pattern, 'future/chapter.crv');
|
|
103
|
+
});
|
|
104
|
+
test('go-to-definition on an include uses the guarded resolver', () => {
|
|
105
|
+
const dir = fixture();
|
|
106
|
+
const main = path.join(dir, 'main.crv');
|
|
107
|
+
const child = path.join(dir, 'child.crv');
|
|
108
|
+
writeFileSync(main, '{{ child.crv }}\n');
|
|
109
|
+
writeFileSync(child, '# Child\n');
|
|
110
|
+
const source = readFileSync(main, 'utf8');
|
|
111
|
+
const location = definitionAt(pathToFileURL(main).toString(), source, { line: 0, character: 5 }, {
|
|
112
|
+
resolver: fileSystemResolver(dir),
|
|
113
|
+
sourcePath: main,
|
|
114
|
+
includeRoot: dir,
|
|
115
|
+
});
|
|
116
|
+
assert.equal(location?.uri, pathToFileURL(child).toString());
|
|
117
|
+
});
|
|
118
|
+
test('included headings contribute symbols attributed to the child file', () => {
|
|
119
|
+
const dir = fixture();
|
|
120
|
+
const main = path.join(dir, 'main.crv');
|
|
121
|
+
const child = path.join(dir, 'child.crv');
|
|
122
|
+
writeFileSync(child, '# Child heading\n');
|
|
123
|
+
const analysis = analyzeCarve('{{ child.crv }}\n', {
|
|
124
|
+
includes: {
|
|
125
|
+
resolver: fileSystemResolver(dir),
|
|
126
|
+
sourcePath: main,
|
|
127
|
+
includeRoot: dir,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
assert.equal(analysis.includedSymbols[0]?.name, 'Child heading');
|
|
131
|
+
assert.equal(analysis.includedSymbols[0]?.location.uri, pathToFileURL(child).toString());
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=include-features.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-features.test.js","sourceRoot":"","sources":["../src/include-features.test.ts"],"names":[],"mappings":"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"}
|
package/dist/include-path.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IncludeSourceCache } from './include-cache.js';
|
|
1
2
|
/**
|
|
2
3
|
* Why a resolver refused a target. Reported on {@link IncludeWarning.detail},
|
|
3
4
|
* never folded into the diagnostic message: §19 I7 requires a
|
|
@@ -24,10 +25,13 @@ export type IncludeResolved = {
|
|
|
24
25
|
id: string;
|
|
25
26
|
source: string;
|
|
26
27
|
bytes: number;
|
|
28
|
+
watch?: string;
|
|
29
|
+
version?: string;
|
|
27
30
|
} | {
|
|
28
31
|
ok: false;
|
|
29
32
|
id: string;
|
|
30
33
|
denial: IncludeDenial;
|
|
34
|
+
watch?: string;
|
|
31
35
|
};
|
|
32
36
|
export type IncludeResolver = (includePath: string, ctx: IncludeContext) => IncludeResolved;
|
|
33
37
|
export interface FileSystemResolverOptions {
|
|
@@ -44,6 +48,8 @@ export interface FileSystemResolverOptions {
|
|
|
44
48
|
* later gains a fetcher has the gate already in place.
|
|
45
49
|
*/
|
|
46
50
|
allowedRemoteHosts?: string[];
|
|
51
|
+
/** Process-level child-source cache, consulted only after containment. */
|
|
52
|
+
cache?: IncludeSourceCache;
|
|
47
53
|
}
|
|
48
54
|
/**
|
|
49
55
|
* Filesystem resolver with canonical root containment, for a workspace the
|