@markup-carve/carve-lsp 0.1.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.
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/analyze.d.ts +6 -0
- package/dist/analyze.js +156 -0
- package/dist/analyze.js.map +1 -0
- package/dist/analyze.test.d.ts +1 -0
- package/dist/analyze.test.js +207 -0
- package/dist/analyze.test.js.map +1 -0
- package/dist/codelens.d.ts +7 -0
- package/dist/codelens.js +36 -0
- package/dist/codelens.js.map +1 -0
- package/dist/codelens.test.d.ts +1 -0
- package/dist/codelens.test.js +18 -0
- package/dist/codelens.test.js.map +1 -0
- package/dist/completion.d.ts +9 -0
- package/dist/completion.js +91 -0
- package/dist/completion.js.map +1 -0
- package/dist/completion.test.d.ts +1 -0
- package/dist/completion.test.js +35 -0
- package/dist/completion.test.js.map +1 -0
- package/dist/definition.d.ts +12 -0
- package/dist/definition.js +280 -0
- package/dist/definition.js.map +1 -0
- package/dist/definition.test.d.ts +1 -0
- package/dist/definition.test.js +136 -0
- package/dist/definition.test.js.map +1 -0
- package/dist/folding.d.ts +8 -0
- package/dist/folding.js +64 -0
- package/dist/folding.js.map +1 -0
- package/dist/folding.test.d.ts +1 -0
- package/dist/folding.test.js +20 -0
- package/dist/folding.test.js.map +1 -0
- package/dist/format.d.ts +1 -0
- package/dist/format.js +83 -0
- package/dist/format.js.map +1 -0
- package/dist/format.test.d.ts +1 -0
- package/dist/format.test.js +46 -0
- package/dist/format.test.js.map +1 -0
- package/dist/hover.d.ts +2 -0
- package/dist/hover.js +222 -0
- package/dist/hover.js.map +1 -0
- package/dist/migration-actions.d.ts +15 -0
- package/dist/migration-actions.js +79 -0
- package/dist/migration-actions.js.map +1 -0
- package/dist/references.d.ts +15 -0
- package/dist/references.js +430 -0
- package/dist/references.js.map +1 -0
- package/dist/references.test.d.ts +1 -0
- package/dist/references.test.js +159 -0
- package/dist/references.test.js.map +1 -0
- package/dist/rename.d.ts +8 -0
- package/dist/rename.js +66 -0
- package/dist/rename.js.map +1 -0
- package/dist/rename.test.d.ts +1 -0
- package/dist/rename.test.js +39 -0
- package/dist/rename.test.js.map +1 -0
- package/dist/semantic.d.ts +15 -0
- package/dist/semantic.js +458 -0
- package/dist/semantic.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +111 -0
- package/dist/server.js.map +1 -0
- package/package.json +49 -0
package/dist/folding.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { parse, resolve } from '@markup-carve/carve';
|
|
2
|
+
/** Block kinds worth offering as a collapsible region when multi-line. */
|
|
3
|
+
const FOLDABLE = new Set([
|
|
4
|
+
'code-block',
|
|
5
|
+
'raw-block',
|
|
6
|
+
'comment',
|
|
7
|
+
'blockquote',
|
|
8
|
+
'list',
|
|
9
|
+
'table',
|
|
10
|
+
'admonition',
|
|
11
|
+
'div',
|
|
12
|
+
'definition-list',
|
|
13
|
+
'figure',
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Folding regions for a Carve document:
|
|
17
|
+
* - every multi-line block (code, admonition, div, list, table, …)
|
|
18
|
+
* - each heading's section, from the heading line down to the line before
|
|
19
|
+
* the next heading of the same or shallower level (or end of document).
|
|
20
|
+
*/
|
|
21
|
+
export function foldingRanges(source) {
|
|
22
|
+
let doc;
|
|
23
|
+
try {
|
|
24
|
+
doc = resolve(parse(source, { positions: true }));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const ranges = [];
|
|
30
|
+
const headings = [];
|
|
31
|
+
const visit = (nodes) => {
|
|
32
|
+
for (const node of nodes) {
|
|
33
|
+
if (node.type === 'heading' && node.pos) {
|
|
34
|
+
headings.push({ level: node.level, startLine: node.pos.startLine });
|
|
35
|
+
}
|
|
36
|
+
if (node.pos && node.pos.endLine > node.pos.startLine && FOLDABLE.has(node.type)) {
|
|
37
|
+
ranges.push({ startLine: node.pos.startLine - 1, endLine: node.pos.endLine - 1 });
|
|
38
|
+
}
|
|
39
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
40
|
+
visit(node.children.filter(isBlockNode));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
visit(doc.children);
|
|
45
|
+
const lastLine = Math.max(0, source.split(/\r?\n/).length - 1);
|
|
46
|
+
for (let i = 0; i < headings.length; i++) {
|
|
47
|
+
const heading = headings[i];
|
|
48
|
+
let end = lastLine;
|
|
49
|
+
for (let j = i + 1; j < headings.length; j++) {
|
|
50
|
+
if (headings[j].level <= heading.level) {
|
|
51
|
+
end = headings[j].startLine - 2;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (end > heading.startLine - 1) {
|
|
56
|
+
ranges.push({ startLine: heading.startLine - 1, endLine: end, kind: 'region' });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return ranges;
|
|
60
|
+
}
|
|
61
|
+
function isBlockNode(node) {
|
|
62
|
+
return Boolean(node && typeof node === 'object' && 'type' in node);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=folding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folding.js","sourceRoot":"","sources":["../src/folding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { foldingRanges } from './folding.js';
|
|
4
|
+
const src = '# A\n\ntext\n\n## B\n\nmore\n\n```js\none\ntwo\n```\n';
|
|
5
|
+
test('folds the section under a top-level heading', () => {
|
|
6
|
+
const ranges = foldingRanges(src);
|
|
7
|
+
assert.ok(ranges.some((r) => r.startLine === 0 && r.endLine >= 11), 'H1 section fold');
|
|
8
|
+
});
|
|
9
|
+
test('folds a nested subsection', () => {
|
|
10
|
+
const ranges = foldingRanges(src);
|
|
11
|
+
assert.ok(ranges.some((r) => r.startLine === 4), 'H2 section fold');
|
|
12
|
+
});
|
|
13
|
+
test('folds a multi-line fenced code block', () => {
|
|
14
|
+
const ranges = foldingRanges(src);
|
|
15
|
+
assert.ok(ranges.some((r) => r.startLine === 8 && r.endLine === 11), 'code block fold');
|
|
16
|
+
});
|
|
17
|
+
test('returns nothing for an empty document', () => {
|
|
18
|
+
assert.deepEqual(foldingRanges(''), []);
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=folding.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folding.test.js","sourceRoot":"","sources":["../src/folding.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,MAAM,GAAG,GAAG,uDAAuD,CAAA;AAEnE,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;IACvD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IACjC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACxF,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACrC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IACjC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACrE,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;IAChD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IACjC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACzF,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACjD,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AACzC,CAAC,CAAC,CAAA"}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatDocument(source: string): string;
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Conservative Carve formatter.
|
|
3
|
+
*
|
|
4
|
+
* Carve has no canonical source serializer, so this does not reflow content.
|
|
5
|
+
* It only applies safe, idempotent normalizations OUTSIDE verbatim blocks
|
|
6
|
+
* (fenced code, raw blocks, comment blocks):
|
|
7
|
+
* - strip trailing whitespace
|
|
8
|
+
* - collapse runs of 2+ blank lines to a single blank line
|
|
9
|
+
* - trim leading/trailing blank lines
|
|
10
|
+
* - end the file with exactly one newline
|
|
11
|
+
*
|
|
12
|
+
* Verbatim block interiors are emitted byte-for-byte (only the file-final
|
|
13
|
+
* newline is enforced), so code, raw HTML, and comments are never altered.
|
|
14
|
+
*/
|
|
15
|
+
export function formatDocument(source) {
|
|
16
|
+
const eol = source.includes('\r\n') ? '\r\n' : '\n';
|
|
17
|
+
const lines = source.split(/\r?\n/);
|
|
18
|
+
const out = [];
|
|
19
|
+
let openFence = null;
|
|
20
|
+
let blankRun = 0;
|
|
21
|
+
for (const raw of lines) {
|
|
22
|
+
if (openFence !== null) {
|
|
23
|
+
out.push(raw);
|
|
24
|
+
if (closesFence(raw, openFence))
|
|
25
|
+
openFence = null;
|
|
26
|
+
blankRun = 0;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const opener = fenceOpener(raw);
|
|
30
|
+
if (opener) {
|
|
31
|
+
openFence = opener;
|
|
32
|
+
out.push(raw.replace(/[ \t]+$/, ''));
|
|
33
|
+
blankRun = 0;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const trimmed = raw.replace(/[ \t]+$/, '');
|
|
37
|
+
if (trimmed === '') {
|
|
38
|
+
blankRun++;
|
|
39
|
+
if (blankRun === 1)
|
|
40
|
+
out.push('');
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
blankRun = 0;
|
|
44
|
+
out.push(trimmed);
|
|
45
|
+
}
|
|
46
|
+
while (out.length && out[0] === '')
|
|
47
|
+
out.shift();
|
|
48
|
+
while (out.length && out[out.length - 1] === '')
|
|
49
|
+
out.pop();
|
|
50
|
+
return out.length ? out.join(eol) + eol : '';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A verbatim block opener: a fence marker indented at most three spaces.
|
|
54
|
+
* Backtick fences cannot carry a backtick in the info string, and a comment
|
|
55
|
+
* fence (`%%%`) must stand alone (no info), matching the parser.
|
|
56
|
+
*/
|
|
57
|
+
function fenceOpener(line) {
|
|
58
|
+
const match = /^( {0,3})(`{3,}|~{3,}|%{3,})(.*)$/.exec(line);
|
|
59
|
+
if (!match)
|
|
60
|
+
return null;
|
|
61
|
+
const marker = match[2];
|
|
62
|
+
const info = match[3];
|
|
63
|
+
if (marker[0] === '`' && info.includes('`'))
|
|
64
|
+
return null;
|
|
65
|
+
if (marker[0] === '%' && info.trim() !== '')
|
|
66
|
+
return null;
|
|
67
|
+
return marker;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A verbatim block closes on a lone fence (indent <= 3) of the same char.
|
|
71
|
+
* Comment blocks close only on an exact-length marker; code/raw fences close
|
|
72
|
+
* on a marker at least as long as the opener (CommonMark rule).
|
|
73
|
+
*/
|
|
74
|
+
function closesFence(line, openFence) {
|
|
75
|
+
const match = /^ {0,3}(`{3,}|~{3,}|%{3,})[ \t]*$/.exec(line);
|
|
76
|
+
if (!match)
|
|
77
|
+
return false;
|
|
78
|
+
const close = match[1];
|
|
79
|
+
if (close[0] !== openFence[0])
|
|
80
|
+
return false;
|
|
81
|
+
return openFence[0] === '%' ? close.length === openFence.length : close.length >= openFence.length;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { formatDocument } from './format.js';
|
|
4
|
+
test('strips trailing whitespace and enforces a final newline', () => {
|
|
5
|
+
assert.equal(formatDocument('# Title \n\npara\t'), '# Title\n\npara\n');
|
|
6
|
+
});
|
|
7
|
+
test('collapses runs of blank lines to a single blank line', () => {
|
|
8
|
+
assert.equal(formatDocument('a\n\n\n\nb'), 'a\n\nb\n');
|
|
9
|
+
});
|
|
10
|
+
test('trims leading and trailing blank lines', () => {
|
|
11
|
+
assert.equal(formatDocument('\n\n# Title\n\n\n'), '# Title\n');
|
|
12
|
+
});
|
|
13
|
+
test('preserves verbatim interiors of fenced code blocks', () => {
|
|
14
|
+
const src = '```js\ncode \n\n\n more\n```\n';
|
|
15
|
+
// Trailing spaces and blank runs inside the fence are untouched.
|
|
16
|
+
assert.equal(formatDocument(src), src);
|
|
17
|
+
});
|
|
18
|
+
test('still normalizes outside a closed fence', () => {
|
|
19
|
+
const src = '```\nx\n```\n\n\n\ntail \n';
|
|
20
|
+
assert.equal(formatDocument(src), '```\nx\n```\n\ntail\n');
|
|
21
|
+
});
|
|
22
|
+
test('handles nested longer fences without closing early', () => {
|
|
23
|
+
const src = '````md\n```\ninner \n```\n````\n';
|
|
24
|
+
assert.equal(formatDocument(src), src);
|
|
25
|
+
});
|
|
26
|
+
test('a 4-space-indented fence does not close a code block', () => {
|
|
27
|
+
const src = '```\ncode\n ```\n```\n\n\n\ntail \n';
|
|
28
|
+
// The indented ``` stays inside the block; the flush ``` closes it; only the
|
|
29
|
+
// prose after the block is normalized.
|
|
30
|
+
assert.equal(formatDocument(src), '```\ncode\n ```\n```\n\ntail\n');
|
|
31
|
+
});
|
|
32
|
+
test('comment block closes only on an exact-length marker', () => {
|
|
33
|
+
const src = '%%%\nhidden \n%%%%\nstill \n%%%\n';
|
|
34
|
+
// %%%% (len 4) does not close %%% (len 3); the block runs to the matching %%%.
|
|
35
|
+
assert.equal(formatDocument(src), src);
|
|
36
|
+
});
|
|
37
|
+
test('a backtick line with inline backticks is not a fence', () => {
|
|
38
|
+
// Not a real opener, so trailing whitespace after it is still trimmed.
|
|
39
|
+
const src = '``` not `a` fence \nbody \n';
|
|
40
|
+
assert.equal(formatDocument(src), '``` not `a` fence\nbody\n');
|
|
41
|
+
});
|
|
42
|
+
test('is idempotent', () => {
|
|
43
|
+
const once = formatDocument('# T \n\n\n\nbody \n');
|
|
44
|
+
assert.equal(formatDocument(once), once);
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=format.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.js","sourceRoot":"","sources":["../src/format.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;IACnE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,sBAAsB,CAAC,EAAE,mBAAmB,CAAC,CAAA;AAC3E,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;IAChE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAA;AACxD,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,mBAAmB,CAAC,EAAE,WAAW,CAAC,CAAA;AAChE,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAC9D,MAAM,GAAG,GAAG,mCAAmC,CAAA;IAC/C,iEAAiE;IACjE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;AACxC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACnD,MAAM,GAAG,GAAG,8BAA8B,CAAA;IAC1C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,uBAAuB,CAAC,CAAA;AAC5D,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAC9D,MAAM,GAAG,GAAG,oCAAoC,CAAA;IAChD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;AACxC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;IAChE,MAAM,GAAG,GAAG,0CAA0C,CAAA;IACtD,6EAA6E;IAC7E,uCAAuC;IACvC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,mCAAmC,CAAC,CAAA;AACxE,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,qDAAqD,EAAE,GAAG,EAAE;IAC/D,MAAM,GAAG,GAAG,uCAAuC,CAAA;IACnD,+EAA+E;IAC/E,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;AACxC,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;IAChE,uEAAuE;IACvE,MAAM,GAAG,GAAG,iCAAiC,CAAA;IAC7C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,2BAA2B,CAAC,CAAA;AAChE,CAAC,CAAC,CAAA;AAEF,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE;IACzB,MAAM,IAAI,GAAG,cAAc,CAAC,uBAAuB,CAAC,CAAA;IACpD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;AAC1C,CAAC,CAAC,CAAA"}
|
package/dist/hover.d.ts
ADDED
package/dist/hover.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { MarkupKind } from 'vscode-languageserver/node.js';
|
|
2
|
+
import { parse, resolve, } from '@markup-carve/carve';
|
|
3
|
+
const rules = [
|
|
4
|
+
{
|
|
5
|
+
pattern: /#{1,6}/g,
|
|
6
|
+
contents: '**Heading**\n\n`#` through `######` create section headings.',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
pattern: /\*[^*\n]+\*/g,
|
|
10
|
+
contents: '**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`.',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
pattern: /\/[^/\n]+\//g,
|
|
14
|
+
contents: '**Italic**\n\nCarve uses slashes for italic text: `/italic/`.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
pattern: /_[^_\n]+_/g,
|
|
18
|
+
contents: '**Underline**\n\nCarve uses underscores for underline: `_underlined_`.',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
pattern: /~[^~\n]+~/g,
|
|
22
|
+
contents: '**Strikethrough**\n\nCarve uses tildes for strikethrough: `~removed~`.',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: /\{[^}\n]+\}/g,
|
|
26
|
+
contents: '**Attributes**\n\nAttach IDs, classes, and key/value pairs with `{#id .class key=value}`.',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
pattern: /\[[^\]\n]+\]\([^\s)]+(?:\s+"[^"]*")?\)/g,
|
|
30
|
+
contents: '**Link**\n\nInline links use `[label](url)`.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
pattern: /!\[[^\]\n]*\]\([^\s)]+(?:\s+"[^"]*")?\)/g,
|
|
34
|
+
contents: '**Image**\n\nImages use `` and can be followed by captions.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
pattern: /`[^`\n]+`/g,
|
|
38
|
+
contents: '**Inline Code**\n\nBackticks mark inline code spans.',
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
export function hoverAt(source, position) {
|
|
42
|
+
try {
|
|
43
|
+
const hover = astHoverAt(resolve(parse(source)), position);
|
|
44
|
+
if (hover)
|
|
45
|
+
return hover;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Fall back to lexical help below for documents that do not parse.
|
|
49
|
+
}
|
|
50
|
+
const line = source.replace(/\r\n?/g, '\n').split('\n')[position.line];
|
|
51
|
+
if (line === undefined)
|
|
52
|
+
return null;
|
|
53
|
+
for (const rule of rules) {
|
|
54
|
+
rule.pattern.lastIndex = 0;
|
|
55
|
+
for (const match of line.matchAll(rule.pattern)) {
|
|
56
|
+
const start = match.index ?? 0;
|
|
57
|
+
const end = start + match[0].length;
|
|
58
|
+
if (position.character < start || position.character > end)
|
|
59
|
+
continue;
|
|
60
|
+
return {
|
|
61
|
+
contents: {
|
|
62
|
+
kind: MarkupKind.Markdown,
|
|
63
|
+
value: rule.contents,
|
|
64
|
+
},
|
|
65
|
+
range: {
|
|
66
|
+
start: { line: position.line, character: start },
|
|
67
|
+
end: { line: position.line, character: end },
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
function astHoverAt(doc, position) {
|
|
75
|
+
const matches = [];
|
|
76
|
+
for (const node of doc.children)
|
|
77
|
+
collectBlock(matches, node, position);
|
|
78
|
+
matches.sort((a, b) => spanSize(a.pos) - spanSize(b.pos));
|
|
79
|
+
const match = matches[0];
|
|
80
|
+
if (!match)
|
|
81
|
+
return null;
|
|
82
|
+
return {
|
|
83
|
+
contents: {
|
|
84
|
+
kind: MarkupKind.Markdown,
|
|
85
|
+
value: match.contents,
|
|
86
|
+
},
|
|
87
|
+
range: toRange(match.pos),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function collectBlock(matches, node, position) {
|
|
91
|
+
addMatch(matches, node.pos, position, blockContents(node));
|
|
92
|
+
switch (node.type) {
|
|
93
|
+
case 'heading':
|
|
94
|
+
collectInline(matches, node.children, position);
|
|
95
|
+
break;
|
|
96
|
+
case 'paragraph':
|
|
97
|
+
collectInline(matches, node.children, position);
|
|
98
|
+
break;
|
|
99
|
+
case 'blockquote':
|
|
100
|
+
node.children.forEach((child) => collectBlock(matches, child, position));
|
|
101
|
+
break;
|
|
102
|
+
case 'list':
|
|
103
|
+
node.items.forEach((item) => item.children.forEach((child) => collectBlock(matches, child, position)));
|
|
104
|
+
break;
|
|
105
|
+
case 'admonition':
|
|
106
|
+
case 'div':
|
|
107
|
+
node.children.forEach((child) => collectBlock(matches, child, position));
|
|
108
|
+
if (node.type === 'admonition' && node.title)
|
|
109
|
+
collectInline(matches, node.title, position);
|
|
110
|
+
break;
|
|
111
|
+
case 'definition-list':
|
|
112
|
+
node.items.forEach((item) => {
|
|
113
|
+
item.terms.forEach((term) => collectInline(matches, term, position));
|
|
114
|
+
item.definitions.forEach((definition) => definition.forEach((child) => collectBlock(matches, child, position)));
|
|
115
|
+
});
|
|
116
|
+
break;
|
|
117
|
+
case 'figure':
|
|
118
|
+
collectBlock(matches, node.target, position);
|
|
119
|
+
collectInline(matches, node.caption, position);
|
|
120
|
+
break;
|
|
121
|
+
case 'table':
|
|
122
|
+
if (node.caption)
|
|
123
|
+
collectInline(matches, node.caption, position);
|
|
124
|
+
node.rows.forEach((row) => row.cells.forEach((cell) => collectInline(matches, cell.children, position)));
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function collectInline(matches, nodes, position) {
|
|
129
|
+
for (const node of nodes) {
|
|
130
|
+
addMatch(matches, node.pos, position, inlineContents(node));
|
|
131
|
+
const children = node.children;
|
|
132
|
+
if (Array.isArray(children))
|
|
133
|
+
collectInline(matches, children, position);
|
|
134
|
+
const content = node.content;
|
|
135
|
+
if (Array.isArray(content))
|
|
136
|
+
collectInline(matches, content, position);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function addMatch(matches, pos, position, contents) {
|
|
140
|
+
if (!contents || !pos || !contains(pos, position))
|
|
141
|
+
return;
|
|
142
|
+
matches.push({ pos, contents });
|
|
143
|
+
}
|
|
144
|
+
function blockContents(node) {
|
|
145
|
+
switch (node.type) {
|
|
146
|
+
case 'heading':
|
|
147
|
+
return '**Heading**\n\n`#` through `######` create section headings.';
|
|
148
|
+
case 'code-block':
|
|
149
|
+
return '**Code Block**\n\nTriple backtick or tilde fences create verbatim code blocks.';
|
|
150
|
+
case 'raw-block':
|
|
151
|
+
return '**Raw Block**\n\nRaw passthrough blocks render only for matching output formats.';
|
|
152
|
+
case 'blockquote':
|
|
153
|
+
return '**Block Quote**\n\nLines beginning with `>` create quoted blocks.';
|
|
154
|
+
case 'list':
|
|
155
|
+
return '**List**\n\nUse bullets, task markers, or ordered markers for lists.';
|
|
156
|
+
case 'table':
|
|
157
|
+
return '**Table**\n\nPipe-delimited rows create tables.';
|
|
158
|
+
case 'admonition':
|
|
159
|
+
return '**Admonition**\n\nTyped `:::` fences create admonition blocks.';
|
|
160
|
+
case 'div':
|
|
161
|
+
return '**Div**\n\nBare `:::` fences create generic container blocks.';
|
|
162
|
+
default:
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function inlineContents(node) {
|
|
167
|
+
switch (node.type) {
|
|
168
|
+
case 'strong':
|
|
169
|
+
return '**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`.';
|
|
170
|
+
case 'italic':
|
|
171
|
+
return '**Italic**\n\nCarve uses slashes for italic text: `/italic/`.';
|
|
172
|
+
case 'underline':
|
|
173
|
+
return '**Underline**\n\nCarve uses underscores for underline: `_underlined_`.';
|
|
174
|
+
case 'strike':
|
|
175
|
+
return '**Strikethrough**\n\nCarve uses tildes for strikethrough: `~removed~`.';
|
|
176
|
+
case 'sub':
|
|
177
|
+
return '**Subscript**\n\nCarve subscript uses the braced form `{,text,}`, e.g. `H{,2,}O`. A bare comma is literal text.';
|
|
178
|
+
case 'super':
|
|
179
|
+
return '**Superscript**\n\nCarve superscript uses the braced form `{^text^}`, e.g. `E=mc{^2^}`. A bare caret is literal text.';
|
|
180
|
+
case 'highlight':
|
|
181
|
+
return '**Highlight**\n\nCarve highlight is a single equals: `=marked=` (use the forced form `{=marked=}` intraword).';
|
|
182
|
+
case 'code':
|
|
183
|
+
return '**Inline Code**\n\nBackticks mark inline code spans.';
|
|
184
|
+
case 'link':
|
|
185
|
+
return '**Link**\n\nInline links use `[label](url)` or reference-link syntax.';
|
|
186
|
+
case 'image':
|
|
187
|
+
return '**Image**\n\nImages use `` and can be followed by captions.';
|
|
188
|
+
case 'mention':
|
|
189
|
+
return '**Mention**\n\nMentions use `@name`.';
|
|
190
|
+
case 'tag':
|
|
191
|
+
return '**Tag**\n\nTags use `#name`.';
|
|
192
|
+
case 'span':
|
|
193
|
+
return '**Span**\n\nInline spans use `[text]{attrs}`.';
|
|
194
|
+
default:
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function contains(pos, position) {
|
|
199
|
+
if (pos.startColumn === undefined ||
|
|
200
|
+
pos.endColumn === undefined ||
|
|
201
|
+
position.line + 1 < pos.startLine ||
|
|
202
|
+
position.line + 1 > pos.endLine) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
if (position.line + 1 === pos.startLine && position.character + 1 < pos.startColumn)
|
|
206
|
+
return false;
|
|
207
|
+
if (position.line + 1 === pos.endLine && position.character + 1 > pos.endColumn)
|
|
208
|
+
return false;
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
function toRange(pos) {
|
|
212
|
+
return {
|
|
213
|
+
start: { line: pos.startLine - 1, character: (pos.startColumn ?? 1) - 1 },
|
|
214
|
+
end: { line: pos.endLine - 1, character: (pos.endColumn ?? 1) - 1 },
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function spanSize(pos) {
|
|
218
|
+
if (pos.startOffset !== undefined && pos.endOffset !== undefined)
|
|
219
|
+
return pos.endOffset - pos.startOffset;
|
|
220
|
+
return (pos.endLine - pos.startLine) * 1000 + ((pos.endColumn ?? 1) - (pos.startColumn ?? 1));
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=hover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hover.js","sourceRoot":"","sources":["../src/hover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CodeAction, Range, type Diagnostic } from 'vscode-languageserver/node.js';
|
|
2
|
+
export interface MigrationFix {
|
|
3
|
+
rule: string;
|
|
4
|
+
range: Range;
|
|
5
|
+
suggestion: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function migrationFixes(source: string): MigrationFix[];
|
|
8
|
+
export declare function migrationCodeActions(uri: string, source: string, diagnostics: Diagnostic[]): CodeAction[];
|
|
9
|
+
/**
|
|
10
|
+
* A single source action that rewrites every auto-fixable collision in the
|
|
11
|
+
* document via `applyMigrationFixes`. Offered only when something would
|
|
12
|
+
* change. Crossing (ambiguous) collisions are left in place; they keep their
|
|
13
|
+
* per-diagnostic warning for manual review.
|
|
14
|
+
*/
|
|
15
|
+
export declare function migrationFixAllAction(uri: string, source: string): CodeAction | null;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { CodeActionKind, Range, TextEdit, } from 'vscode-languageserver/node.js';
|
|
2
|
+
import { applyMigrationFixes, djotMigrationWarnings } from '@markup-carve/carve';
|
|
3
|
+
// `MigrationWarning.start`/`end` are offsets into the line-ending-normalized
|
|
4
|
+
// source, so positions are computed against the same normalization.
|
|
5
|
+
function normalize(source) {
|
|
6
|
+
return source.replace(/\r\n?/g, '\n');
|
|
7
|
+
}
|
|
8
|
+
export function migrationFixes(source) {
|
|
9
|
+
const norm = normalize(source);
|
|
10
|
+
return djotMigrationWarnings(source).map((warning) => ({
|
|
11
|
+
rule: warning.rule,
|
|
12
|
+
range: Range.create(positionAt(norm, warning.start), positionAt(norm, warning.end)),
|
|
13
|
+
suggestion: warning.suggestion,
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
export function migrationCodeActions(uri, source, diagnostics) {
|
|
17
|
+
const fixes = migrationFixes(source);
|
|
18
|
+
const actions = [];
|
|
19
|
+
for (const diagnostic of diagnostics) {
|
|
20
|
+
if (typeof diagnostic.code !== 'string')
|
|
21
|
+
continue;
|
|
22
|
+
const fix = fixes.find((candidate) => candidate.rule === diagnostic.code &&
|
|
23
|
+
candidate.range.start.line === diagnostic.range.start.line &&
|
|
24
|
+
candidate.range.start.character === diagnostic.range.start.character);
|
|
25
|
+
if (!fix)
|
|
26
|
+
continue;
|
|
27
|
+
actions.push({
|
|
28
|
+
title: `Convert to Carve syntax: ${fix.suggestion}`,
|
|
29
|
+
kind: CodeActionKind.QuickFix,
|
|
30
|
+
diagnostics: [diagnostic],
|
|
31
|
+
edit: {
|
|
32
|
+
changes: {
|
|
33
|
+
[uri]: [TextEdit.replace(fix.range, fix.suggestion)],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
isPreferred: true,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const fixAll = migrationFixAllAction(uri, source);
|
|
40
|
+
if (fixAll)
|
|
41
|
+
actions.push(fixAll);
|
|
42
|
+
return actions;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A single source action that rewrites every auto-fixable collision in the
|
|
46
|
+
* document via `applyMigrationFixes`. Offered only when something would
|
|
47
|
+
* change. Crossing (ambiguous) collisions are left in place; they keep their
|
|
48
|
+
* per-diagnostic warning for manual review.
|
|
49
|
+
*/
|
|
50
|
+
export function migrationFixAllAction(uri, source) {
|
|
51
|
+
const { output, applied } = applyMigrationFixes(source);
|
|
52
|
+
if (applied.length === 0)
|
|
53
|
+
return null;
|
|
54
|
+
// The whole-document range. Computed on the normalized text, whose
|
|
55
|
+
// per-line character offsets match the live document (line endings differ
|
|
56
|
+
// only at line breaks, which positionAt never indexes into).
|
|
57
|
+
const norm = normalize(source);
|
|
58
|
+
const fullRange = Range.create(positionAt(norm, 0), positionAt(norm, norm.length));
|
|
59
|
+
const n = applied.length;
|
|
60
|
+
return {
|
|
61
|
+
title: `Fix all Carve migration collisions (${n})`,
|
|
62
|
+
kind: CodeActionKind.SourceFixAll,
|
|
63
|
+
edit: {
|
|
64
|
+
changes: {
|
|
65
|
+
[uri]: [TextEdit.replace(fullRange, output)],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function positionAt(source, offset) {
|
|
71
|
+
const before = source.slice(0, offset);
|
|
72
|
+
const line = before.split('\n').length - 1;
|
|
73
|
+
const lastNewline = before.lastIndexOf('\n');
|
|
74
|
+
return {
|
|
75
|
+
line,
|
|
76
|
+
character: offset - lastNewline - 1,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=migration-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-actions.js","sourceRoot":"","sources":["../src/migration-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Location, type Position, type ReferenceContext } from 'vscode-languageserver/node.js';
|
|
2
|
+
/**
|
|
3
|
+
* Find-references for Carve constructs (same-document scope).
|
|
4
|
+
*
|
|
5
|
+
* Given the cursor position on either a definition or a usage, return ALL
|
|
6
|
+
* usages (and optionally the definition itself when `context.includeDeclaration`).
|
|
7
|
+
*
|
|
8
|
+
* Supported families, mirroring definition.ts:
|
|
9
|
+
* - Heading id (on `#` heading line or on a `</#id>` / `[text](#id)` usage)
|
|
10
|
+
* - Footnote `[^name]` references and `[^name]:` definition
|
|
11
|
+
* - Link-ref `[text][ref]` / `[ref][]` usages and `[ref]:` definition
|
|
12
|
+
* - Citation `[@key]` usages and `[@key]:` definition
|
|
13
|
+
* - Wikilink `[[Page]]` usages (same-document headings only)
|
|
14
|
+
*/
|
|
15
|
+
export declare function referencesAt(uri: string, source: string, position: Position, context: ReferenceContext): Location[] | null;
|