@markup-carve/carve-lsp 0.1.1 → 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 +65 -2
- package/dist/analyze.d.ts +26 -2
- package/dist/analyze.js +227 -14
- package/dist/analyze.js.map +1 -1
- package/dist/analyze.test.js +106 -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 +50 -7
- 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 +80 -26
- 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-directive.d.ts +61 -0
- package/dist/include-directive.js +158 -0
- package/dist/include-directive.js.map +1 -0
- package/dist/include-directive.test.d.ts +1 -0
- package/dist/include-directive.test.js +83 -0
- package/dist/include-directive.test.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 +69 -0
- package/dist/include-path.js +164 -0
- package/dist/include-path.js.map +1 -0
- package/dist/include-path.test.d.ts +1 -0
- package/dist/include-path.test.js +189 -0
- package/dist/include-path.test.js.map +1 -0
- package/dist/include-security-conformance.test.d.ts +1 -0
- package/dist/include-security-conformance.test.js +100 -0
- package/dist/include-security-conformance.test.js.map +1 -0
- package/dist/include-settings.d.ts +52 -0
- package/dist/include-settings.js +136 -0
- package/dist/include-settings.js.map +1 -0
- package/dist/include-settings.test.d.ts +1 -0
- package/dist/include-settings.test.js +191 -0
- package/dist/include-settings.test.js.map +1 -0
- package/dist/includes.d.ts +86 -0
- package/dist/includes.js +179 -0
- package/dist/includes.js.map +1 -0
- package/dist/includes.test.d.ts +1 -0
- package/dist/includes.test.js +202 -0
- package/dist/includes.test.js.map +1 -0
- package/dist/inline-text.d.ts +24 -0
- package/dist/inline-text.js +34 -0
- package/dist/inline-text.js.map +1 -0
- package/dist/inline-text.test.d.ts +1 -0
- package/dist/inline-text.test.js +32 -0
- package/dist/inline-text.test.js.map +1 -0
- package/dist/position-encoding.test.d.ts +1 -0
- package/dist/position-encoding.test.js +143 -0
- package/dist/position-encoding.test.js.map +1 -0
- package/dist/position.d.ts +82 -0
- package/dist/position.js +137 -0
- package/dist/position.js.map +1 -0
- package/dist/position.test.d.ts +1 -0
- package/dist/position.test.js +61 -0
- package/dist/position.test.js.map +1 -0
- package/dist/references.d.ts +2 -0
- package/dist/references.js +116 -21
- package/dist/references.js.map +1 -1
- package/dist/semantic.d.ts +14 -0
- package/dist/semantic.js +112 -13
- package/dist/semantic.js.map +1 -1
- package/dist/semantic.test.d.ts +1 -0
- package/dist/semantic.test.js +99 -0
- package/dist/semantic.test.js.map +1 -0
- package/dist/server.js +166 -26
- 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/README.md
CHANGED
|
@@ -23,10 +23,10 @@ The server communicates over **stdio** (`--stdio` flag).
|
|
|
23
23
|
| Capability | Details |
|
|
24
24
|
|---|---|
|
|
25
25
|
| Diagnostics | Syntax errors from the Carve parser; advisory warnings for Djot/Markdown delimiter collisions |
|
|
26
|
-
| Document symbols | Headings as an outline tree |
|
|
26
|
+
| Document symbols | Headings as an outline tree, including headings attributed to included files |
|
|
27
27
|
| Hover | Contextual information on hover |
|
|
28
28
|
| Completion | Trigger characters `:` `#` `^` `[` |
|
|
29
|
-
| Go to definition | Jump to heading / reference targets |
|
|
29
|
+
| Go to definition | Jump to heading / reference targets and included files |
|
|
30
30
|
| Find references | All uses of a heading id or reference label |
|
|
31
31
|
| Rename | Prepare + apply renames across the document |
|
|
32
32
|
| Code actions | Migration quick-fixes for deprecated Carve syntax |
|
|
@@ -34,6 +34,69 @@ The server communicates over **stdio** (`--stdio` flag).
|
|
|
34
34
|
| Folding ranges | Fold sections and block containers |
|
|
35
35
|
| Formatting | Format the whole document |
|
|
36
36
|
| Semantic tokens | Token-based syntax highlighting |
|
|
37
|
+
| File inclusion | Resolves `{{ path }}` directives, watches dependencies, and reports failures as diagnostics - **off by default**, see below |
|
|
38
|
+
|
|
39
|
+
## File inclusion
|
|
40
|
+
|
|
41
|
+
Carve's `{{ path }}` directive is a processor-level feature (PART 9 §19 of the
|
|
42
|
+
grammar), not part of the parser. This server resolves it so that the thin
|
|
43
|
+
editor clients - `helix-carve`, `emacs-carve`, `vim-carve`, `zed-carve`,
|
|
44
|
+
`sublime-carve` - get inclusion support without each implementing it.
|
|
45
|
+
|
|
46
|
+
Resolution reads files from disk, so it is **opt-in and off by default**. The
|
|
47
|
+
server enables it only when it is asked to, and only inside a containment root.
|
|
48
|
+
|
|
49
|
+
### Settings
|
|
50
|
+
|
|
51
|
+
Pass these under `carve.includes`, either in `initializationOptions` at
|
|
52
|
+
initialize time or through `workspace/didChangeConfiguration`. Changing them
|
|
53
|
+
re-publishes diagnostics for every open document.
|
|
54
|
+
|
|
55
|
+
| Setting | Default | Meaning |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `enabled` | `"auto"` | `"auto"` enables inclusion only for a workspace the client reports as trusted; `"on"` always; `"off"` never. A client that reports no trust gets inclusion off. |
|
|
58
|
+
| `includeRoot` | workspace root | Containment root override. With no workspace, the document's own directory is used - never the server's working directory. |
|
|
59
|
+
| `allowAbsolute` | `false` | Allow absolute include paths. They still have to canonicalize inside the root. |
|
|
60
|
+
| `allowedRemoteHosts` | `[]` | Hosts a remote include may name. This server has no fetcher, so a remote target is refused either way; the list exists so the gate is explicit. |
|
|
61
|
+
| `maxDepth` | `16` | Maximum transitive include depth. |
|
|
62
|
+
| `maxBytes` | `max(1 MiB, 8x document)` | Total byte budget across the whole include graph, charged per occurrence. |
|
|
63
|
+
|
|
64
|
+
Client trust is read from `initializationOptions.workspaceTrusted`.
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"carve": {
|
|
69
|
+
"includes": {
|
|
70
|
+
"enabled": "auto",
|
|
71
|
+
"maxDepth": 8
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"workspaceTrusted": true
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### What is enforced
|
|
79
|
+
|
|
80
|
+
Every target has to canonicalize (symlinks resolved) to a file inside the
|
|
81
|
+
containment root. A symlink pointing out of the root, a `..` path that leaves
|
|
82
|
+
it, and an absolute path outside it are all refused. A `..` path whose real
|
|
83
|
+
target stays inside the root is fine - a chapter reaching a shared glossary is
|
|
84
|
+
ordinary layout. Remote URLs are never fetched. Recursion depth and total
|
|
85
|
+
expanded bytes are both bounded, so a file that includes another many times
|
|
86
|
+
cannot amplify without limit.
|
|
87
|
+
|
|
88
|
+
A refused target produces an `include-unresolved` diagnostic on the directive,
|
|
89
|
+
and the directive stays literal. The diagnostic deliberately does not say WHICH
|
|
90
|
+
check refused it: a distinguishable denial is a way to probe the layout of the
|
|
91
|
+
machine the server runs on.
|
|
92
|
+
|
|
93
|
+
The server watches every legal include target, including a missing target that
|
|
94
|
+
may be created later. A child change invalidates its cached source and parsed
|
|
95
|
+
tree, then revalidates every open document that includes it. Go to definition
|
|
96
|
+
on a directive opens the resolved child, and child headings appear in the
|
|
97
|
+
including document's symbol result with locations in the child file. All three
|
|
98
|
+
features use the same contained resolver as diagnostics; refused paths are
|
|
99
|
+
never registered as watchers or navigation targets.
|
|
37
100
|
|
|
38
101
|
## Editor setup
|
|
39
102
|
|
package/dist/analyze.d.ts
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
|
-
import { DocumentSymbol, type Diagnostic } from 'vscode-languageserver/node.js';
|
|
1
|
+
import { DocumentSymbol, SymbolInformation, type Diagnostic, type Range } from 'vscode-languageserver/node.js';
|
|
2
|
+
import { type IncludeDependency, type IncludeOptions } from './includes.js';
|
|
3
|
+
import type { IncludeParseCache } from './include-cache.js';
|
|
4
|
+
export interface AnalyzeOptions {
|
|
5
|
+
/** URI used for diagnostic related-information locations. */
|
|
6
|
+
uri?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Include resolution settings (PART 9 §19). ABSENT MEANS OFF: with no
|
|
9
|
+
* options - or with options carrying no resolver - no include directive is
|
|
10
|
+
* acted on and no file is read. §19 requires includes to be opt-in, so the
|
|
11
|
+
* capability has to be handed in rather than defaulted into existence.
|
|
12
|
+
*/
|
|
13
|
+
includes?: IncludeOptions;
|
|
14
|
+
includedParseCache?: IncludeParseCache;
|
|
15
|
+
}
|
|
2
16
|
export interface Analysis {
|
|
3
17
|
diagnostics: Diagnostic[];
|
|
4
18
|
symbols: DocumentSymbol[];
|
|
19
|
+
/**
|
|
20
|
+
* Include targets touched while analyzing, resolved or not. Empty unless
|
|
21
|
+
* include resolution was enabled. Hosts watch these so a change in an
|
|
22
|
+
* INCLUDED document can re-publish diagnostics for the INCLUDING one.
|
|
23
|
+
*/
|
|
24
|
+
dependencies: IncludeDependency[];
|
|
25
|
+
/** Outline entries from included files, carrying their child-file URI. */
|
|
26
|
+
includedSymbols: SymbolInformation[];
|
|
5
27
|
}
|
|
6
|
-
export declare function analyzeCarve(source: string): Analysis;
|
|
28
|
+
export declare function analyzeCarve(source: string, options?: AnalyzeOptions): Analysis;
|
|
29
|
+
export declare function parseErrorRange(source: string, message: string): Range;
|
|
30
|
+
export declare function tolerantHeadingSymbols(source: string): DocumentSymbol[];
|
package/dist/analyze.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { DiagnosticSeverity, SymbolKind, } from 'vscode-languageserver/node.js';
|
|
2
2
|
import { djotMigrationWarnings, lintCarve, parse, resolve, } from '@markup-carve/carve';
|
|
3
|
-
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { smartPunctuationText } from './inline-text.js';
|
|
6
|
+
import { panelLetter } from './captions.js';
|
|
7
|
+
import { resolveIncludes } from './includes.js';
|
|
8
|
+
export function analyzeCarve(source, options = {}) {
|
|
4
9
|
const diagnostics = [];
|
|
5
10
|
let doc = null;
|
|
6
11
|
try {
|
|
7
12
|
doc = resolve(parse(source));
|
|
8
13
|
}
|
|
9
14
|
catch (error) {
|
|
15
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
10
16
|
diagnostics.push({
|
|
11
17
|
severity: DiagnosticSeverity.Error,
|
|
12
|
-
range:
|
|
18
|
+
range: parseErrorRange(source, message),
|
|
13
19
|
source: 'carve',
|
|
14
|
-
message
|
|
20
|
+
message,
|
|
15
21
|
});
|
|
16
22
|
}
|
|
17
23
|
// warning.start/end are offsets into the line-ending-normalized source;
|
|
@@ -44,7 +50,7 @@ export function analyzeCarve(source) {
|
|
|
44
50
|
// attributes, legacy raw fences, leaked block markers).
|
|
45
51
|
for (const warning of lintCarve(source)) {
|
|
46
52
|
const len = Math.max(1, warning.end - warning.start);
|
|
47
|
-
|
|
53
|
+
const diagnostic = {
|
|
48
54
|
severity: DiagnosticSeverity.Warning,
|
|
49
55
|
range: {
|
|
50
56
|
start: { line: warning.line - 1, character: warning.column - 1 },
|
|
@@ -53,21 +59,148 @@ export function analyzeCarve(source) {
|
|
|
53
59
|
source: 'carve',
|
|
54
60
|
code: warning.rule,
|
|
55
61
|
message: warning.message,
|
|
62
|
+
};
|
|
63
|
+
const related = options.uri ? firstDuplicateDeclaration(source, warning.rule, warning.message, warning.line - 1) : null;
|
|
64
|
+
if (options.uri && related)
|
|
65
|
+
diagnostic.relatedInformation = [{
|
|
66
|
+
location: { uri: options.uri, range: related },
|
|
67
|
+
message: 'First declaration is here.',
|
|
68
|
+
}];
|
|
69
|
+
diagnostics.push(diagnostic);
|
|
70
|
+
}
|
|
71
|
+
// Include resolution (PART 9 §19). Inert without a resolver, so a document
|
|
72
|
+
// in an untrusted or unconfigured workspace keeps its `{{ … }}` literal and
|
|
73
|
+
// nothing on disk is touched.
|
|
74
|
+
const includes = resolveIncludes(norm, options.includes ?? {});
|
|
75
|
+
for (const warning of includes.warnings) {
|
|
76
|
+
diagnostics.push({
|
|
77
|
+
severity: DiagnosticSeverity.Warning,
|
|
78
|
+
range: {
|
|
79
|
+
start: positionAt(norm, warning.start),
|
|
80
|
+
end: positionAt(norm, warning.end),
|
|
81
|
+
},
|
|
82
|
+
source: 'carve',
|
|
83
|
+
code: warning.rule,
|
|
84
|
+
// `warning.detail` is deliberately not folded in: §19 I7 keeps the
|
|
85
|
+
// failure class out of author-visible text so a denial cannot be used
|
|
86
|
+
// to probe host layout. The attributed child is named relative to the
|
|
87
|
+
// include root for the same reason - never as an absolute path.
|
|
88
|
+
message: attributeToChild(warning.message, warning.file, options.includes),
|
|
56
89
|
});
|
|
57
90
|
}
|
|
58
91
|
return {
|
|
59
92
|
diagnostics,
|
|
60
|
-
symbols: doc ? documentSymbols(doc) :
|
|
93
|
+
symbols: doc ? documentSymbols(doc) : tolerantHeadingSymbols(source),
|
|
94
|
+
dependencies: includes.dependencies,
|
|
95
|
+
includedSymbols: includedSymbols(includes.documents, options.includedParseCache),
|
|
61
96
|
};
|
|
62
97
|
}
|
|
98
|
+
export function parseErrorRange(source, message) {
|
|
99
|
+
const located = /(?:line|at)\s+(\d+)(?::|,\s*column\s+)(\d+)/i.exec(message);
|
|
100
|
+
if (!located)
|
|
101
|
+
return rangeAt(source, 0, 1);
|
|
102
|
+
const line = Math.max(0, Number(located[1]) - 1);
|
|
103
|
+
const character = Math.max(0, Number(located[2]) - 1);
|
|
104
|
+
return { start: { line, character }, end: { line, character: character + 1 } };
|
|
105
|
+
}
|
|
106
|
+
export function tolerantHeadingSymbols(source) {
|
|
107
|
+
const symbols = [];
|
|
108
|
+
for (const [line, text] of source.replace(/\r\n?/g, '\n').split('\n').entries()) {
|
|
109
|
+
const match = /^(#{1,6}) (.+)$/.exec(text);
|
|
110
|
+
if (!match)
|
|
111
|
+
continue;
|
|
112
|
+
const range = { start: { line, character: 0 }, end: { line, character: text.length } };
|
|
113
|
+
symbols.push({ name: match[2], kind: SymbolKind.String, range, selectionRange: range });
|
|
114
|
+
}
|
|
115
|
+
return symbols;
|
|
116
|
+
}
|
|
117
|
+
function firstDuplicateDeclaration(source, rule, message, repeatedLine) {
|
|
118
|
+
const headingKey = rule === 'duplicate-heading-id' ? /heading id "([^"]+)"/.exec(message)?.[1] : undefined;
|
|
119
|
+
const footnoteKey = rule === 'duplicate-footnote-definition' ? /\[\^([^\]]+)\]/.exec(message)?.[1] : undefined;
|
|
120
|
+
const key = headingKey ?? footnoteKey;
|
|
121
|
+
if (!key)
|
|
122
|
+
return null;
|
|
123
|
+
const lines = source.replace(/\r\n?/g, '\n').split('\n');
|
|
124
|
+
const declarations = [];
|
|
125
|
+
for (let line = 0; line < lines.length; line += 1) {
|
|
126
|
+
const text = lines[line];
|
|
127
|
+
const match = headingKey
|
|
128
|
+
? /^\{[^}]*#([^\s}]+)[^}]*\}\s*$/.exec(text)
|
|
129
|
+
: /^(?: {0,3})\[\^([^\]]+)\]:/.exec(text);
|
|
130
|
+
if (!match || match[1].toLocaleLowerCase() !== key.toLocaleLowerCase())
|
|
131
|
+
continue;
|
|
132
|
+
const character = text.indexOf(match[1]);
|
|
133
|
+
if (line >= repeatedLine - 1)
|
|
134
|
+
break;
|
|
135
|
+
declarations.push({
|
|
136
|
+
start: { line, character },
|
|
137
|
+
end: { line, character: character + match[1].length },
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return declarations[0] ?? null;
|
|
141
|
+
}
|
|
142
|
+
function includedSymbols(documents, cache) {
|
|
143
|
+
const symbols = [];
|
|
144
|
+
for (const child of documents) {
|
|
145
|
+
let document = child.version === undefined ? undefined : cache?.get(child.id, child.version);
|
|
146
|
+
if (!document) {
|
|
147
|
+
try {
|
|
148
|
+
document = resolve(parse(child.source));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (child.version !== undefined)
|
|
154
|
+
cache?.set(child.id, child.version, document);
|
|
155
|
+
}
|
|
156
|
+
const uri = pathToFileURL(child.id).toString();
|
|
157
|
+
for (const entry of walkOutline(document.children)) {
|
|
158
|
+
// An INCLUDED file contributes its headings, flat. A composite figure is
|
|
159
|
+
// a landmark inside its own file rather than a navigable entry in
|
|
160
|
+
// another one, so it stays out of this list.
|
|
161
|
+
if (entry.type !== 'heading')
|
|
162
|
+
continue;
|
|
163
|
+
const symbol = headingSymbol(entry);
|
|
164
|
+
symbols.push({
|
|
165
|
+
name: symbol.name,
|
|
166
|
+
kind: symbol.kind,
|
|
167
|
+
location: { uri, range: symbol.range },
|
|
168
|
+
containerName: path.basename(child.id),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return symbols;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Name the file a nested include warning arose in, relative to the include
|
|
176
|
+
* root. A warning raised in the document the client already has open adds
|
|
177
|
+
* nothing and is left alone.
|
|
178
|
+
*/
|
|
179
|
+
function attributeToChild(message, file, includes) {
|
|
180
|
+
if (file === undefined || file === includes?.sourcePath)
|
|
181
|
+
return message;
|
|
182
|
+
return `${message} (in ${relativeToRoot(file, includes?.includeRoot)})`;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* A child's identity as the author wrote it: relative to the include root,
|
|
186
|
+
* segment-wise, so a sibling directory named `..foo` is not mistaken for an
|
|
187
|
+
* escape. A file that is not under the root at all is named as it came, since
|
|
188
|
+
* inventing a relative form for it would be a lie.
|
|
189
|
+
*/
|
|
190
|
+
function relativeToRoot(file, root) {
|
|
191
|
+
if (root === undefined)
|
|
192
|
+
return file;
|
|
193
|
+
const relative = path.relative(root, file);
|
|
194
|
+
if (!relative || path.isAbsolute(relative))
|
|
195
|
+
return file;
|
|
196
|
+
if (relative.split(path.sep)[0] === '..')
|
|
197
|
+
return file;
|
|
198
|
+
return relative;
|
|
199
|
+
}
|
|
63
200
|
function documentSymbols(doc) {
|
|
64
201
|
const stack = [];
|
|
65
202
|
const roots = [];
|
|
66
|
-
|
|
67
|
-
const symbol = headingSymbol(heading);
|
|
68
|
-
while (stack.length && stack[stack.length - 1].level >= heading.level) {
|
|
69
|
-
stack.pop();
|
|
70
|
-
}
|
|
203
|
+
const place = (symbol) => {
|
|
71
204
|
const parent = stack[stack.length - 1];
|
|
72
205
|
if (parent) {
|
|
73
206
|
parent.symbol.children ??= [];
|
|
@@ -76,24 +209,97 @@ function documentSymbols(doc) {
|
|
|
76
209
|
else {
|
|
77
210
|
roots.push(symbol);
|
|
78
211
|
}
|
|
79
|
-
|
|
212
|
+
};
|
|
213
|
+
for (const entry of walkOutline(doc.children)) {
|
|
214
|
+
if (entry.type === 'figure_group') {
|
|
215
|
+
// A composite figure is a structural landmark: one figure holding
|
|
216
|
+
// ordered panels (PART 9 §4c). It takes NO level, so it never pops the
|
|
217
|
+
// heading stack - it hangs under the section it appears in, the way a
|
|
218
|
+
// heading's own children do.
|
|
219
|
+
place(figureGroupSymbol(entry));
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
while (stack.length && stack[stack.length - 1].level >= entry.level) {
|
|
223
|
+
stack.pop();
|
|
224
|
+
}
|
|
225
|
+
const symbol = headingSymbol(entry);
|
|
226
|
+
place(symbol);
|
|
227
|
+
stack.push({ level: entry.level, symbol });
|
|
80
228
|
}
|
|
81
229
|
return roots;
|
|
82
230
|
}
|
|
83
|
-
|
|
231
|
+
/**
|
|
232
|
+
* The outline's entries in source order: headings, and composite figures.
|
|
233
|
+
*
|
|
234
|
+
* A group is worth an entry where a plain figure is not, because it is a
|
|
235
|
+
* CONTAINER an author folds, navigates and loses their place inside - the same
|
|
236
|
+
* reason it folds. Its panels come with it, so the outline says how many there
|
|
237
|
+
* are without scrolling the fence.
|
|
238
|
+
*/
|
|
239
|
+
function* walkOutline(nodes) {
|
|
84
240
|
for (const node of nodes) {
|
|
85
241
|
if (node.type === 'heading')
|
|
86
242
|
yield node;
|
|
243
|
+
if (node.type === 'figure_group') {
|
|
244
|
+
yield node;
|
|
245
|
+
// Its panels ride on the group's own symbol - a `figure` or `table`
|
|
246
|
+
// yields no entry of its own here - but the walk still DESCENDS through
|
|
247
|
+
// them. A panel can wrap a quote holding headings, and skipping the panel
|
|
248
|
+
// node dropped those headings out of the outline entirely.
|
|
249
|
+
yield* walkOutline(node.children);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
87
252
|
if ('children' in node && Array.isArray(node.children)) {
|
|
88
|
-
yield*
|
|
253
|
+
yield* walkOutline(node.children.filter(isBlockNode));
|
|
89
254
|
}
|
|
90
255
|
if (node.type === 'figure') {
|
|
91
256
|
if ('children' in node.target && Array.isArray(node.target.children)) {
|
|
92
|
-
yield*
|
|
257
|
+
yield* walkOutline(node.target.children.filter(isBlockNode));
|
|
93
258
|
}
|
|
94
259
|
}
|
|
95
260
|
}
|
|
96
261
|
}
|
|
262
|
+
/** A group's panels are its direct `figure` and `table` children (§4c). */
|
|
263
|
+
function isPanel(node) {
|
|
264
|
+
return node.type === 'figure' || node.type === 'table';
|
|
265
|
+
}
|
|
266
|
+
function figureGroupSymbol(group) {
|
|
267
|
+
const range = blockRange(group);
|
|
268
|
+
const panels = group.children.filter(isPanel);
|
|
269
|
+
return {
|
|
270
|
+
name: (group.caption ? plainText(group.caption) : '') || 'Composite figure',
|
|
271
|
+
detail: panels.length === 1 ? '1 panel' : `${panels.length} panels`,
|
|
272
|
+
kind: SymbolKind.Struct,
|
|
273
|
+
range,
|
|
274
|
+
selectionRange: range,
|
|
275
|
+
children: panels.map((panel, index) => panelSymbol(panel, index)),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* A panel is named by its own caption, and falls back to the LETTER a crossref
|
|
280
|
+
* would use for it (§4c) - not to a number, which would read as a figure number
|
|
281
|
+
* the panel does not have.
|
|
282
|
+
*/
|
|
283
|
+
function panelSymbol(panel, index) {
|
|
284
|
+
const caption = panel.caption;
|
|
285
|
+
const range = blockRange(panel);
|
|
286
|
+
return {
|
|
287
|
+
name: (caption ? plainText(caption) : '') || `Panel ${panelLetter(index)}`,
|
|
288
|
+
kind: panel.type === 'table' ? SymbolKind.Array : SymbolKind.Object,
|
|
289
|
+
range,
|
|
290
|
+
selectionRange: range,
|
|
291
|
+
children: [],
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function blockRange(node) {
|
|
295
|
+
if (!node.pos) {
|
|
296
|
+
return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
start: { line: node.pos.startLine - 1, character: 0 },
|
|
300
|
+
end: { line: node.pos.endLine - 1, character: 200 },
|
|
301
|
+
};
|
|
302
|
+
}
|
|
97
303
|
function isBlockNode(node) {
|
|
98
304
|
return Boolean(node && typeof node === 'object' && 'type' in node);
|
|
99
305
|
}
|
|
@@ -129,12 +335,19 @@ function plainText(nodes) {
|
|
|
129
335
|
// verbatim content to the outline symbol name just as a code span does.
|
|
130
336
|
else if (node.type === 'literal_inline')
|
|
131
337
|
out += node.content;
|
|
338
|
+
// A caption's resolved number. Without it a composite figure appeared in
|
|
339
|
+
// the outline as "Figure : Group caption", with the gap where the number
|
|
340
|
+
// the reader is looking for should be.
|
|
341
|
+
else if (node.type === 'caption_number')
|
|
342
|
+
out += String(node.n);
|
|
132
343
|
else if (node.type === 'symbol')
|
|
133
344
|
out += `:${node.name}:`;
|
|
134
345
|
else if (node.type === 'mention')
|
|
135
346
|
out += `@${node.user}`;
|
|
136
347
|
else if (node.type === 'tag')
|
|
137
348
|
out += `#${node.name}`;
|
|
349
|
+
else
|
|
350
|
+
out += smartPunctuationText(node);
|
|
138
351
|
}
|
|
139
352
|
return out.trim();
|
|
140
353
|
}
|
package/dist/analyze.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAElB,UAAU,GAGX,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,KAAK,EACL,OAAO,GAKR,MAAM,qBAAqB,CAAA;AAO5B,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,WAAW,GAAiB,EAAE,CAAA;IACpC,IAAI,GAAG,GAAoB,IAAI,CAAA;IAE/B,IAAI,CAAC;QACH,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,WAAW,CAAC,IAAI,CAAC;YACf,QAAQ,EAAE,kBAAkB,CAAC,KAAK;YAClC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC5B,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAA;IACJ,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,wEAAwE;IACxE,oBAAoB;IACpB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC3C,uEAAuE;IACvE,wEAAwE;IACxE,kEAAkE;IAClE,6EAA6E;IAC7E,sEAAsE;IACtE,2EAA2E;IAC3E,KAAK,MAAM,OAAO,IAAI,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,IAAI,OAAO,CAAC,QAAQ,KAAK,gBAAgB;YAAE,SAAQ;QACnD,WAAW,CAAC,IAAI,CAAC;YACf,QAAQ,EAAE,kBAAkB,CAAC,OAAO;YACpC,KAAK,EAAE;gBACL,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;gBACtC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;aACnC;YACD,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,gBAAgB,OAAO,CAAC,UAAU,EAAE;SAChE,CAAC,CAAA;IACJ,CAAC;IAED,yEAAyE;IACzE,oEAAoE;IACpE,wDAAwD;IACxD,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QACpD,WAAW,CAAC,IAAI,CAAC;YACf,QAAQ,EAAE,kBAAkB,CAAC,OAAO;YACpC,KAAK,EAAE;gBACL,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;gBAChE,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,EAAE;aACrE;YACD,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,WAAW;QACX,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;KACzC,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAa;IACpC,MAAM,KAAK,GAAqD,EAAE,CAAA;IAClE,MAAM,KAAK,GAAqB,EAAE,CAAA;IAElC,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QACrC,OAAO,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACvE,KAAK,CAAC,GAAG,EAAE,CAAA;QACb,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAA;YAC7B,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACrC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAC9C,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,QAAQ,CAAC,CAAC,YAAY,CAAC,KAAkB;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,CAAA;QACvC,IAAI,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvD,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrE,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,OAAO,OAAO,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,IAAI,IAAI,CAAC,CAAA;AACpE,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG;QACvB,CAAC,CAAC;YACE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;YACxD,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;SACvD;QACH,CAAC,CAAC;YACE,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,CAAA;IACL,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,WAAW,OAAO,CAAC,KAAK,EAAE;QAC/D,IAAI,EAAE,UAAU,CAAC,MAAM;QACvB,KAAK;QACL,cAAc,EAAE,KAAK;QACrB,QAAQ,EAAE,EAAE;KACb,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAmB;IACpC,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAA;aACtC,IAAI,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5D,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,QAAwB,CAAC,CAAA;QACjD,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAA;QAClD,0EAA0E;QAC1E,wEAAwE;aACnE,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB;YAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAA;aACvD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YAAE,GAAG,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,CAAA;aACnD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,GAAG,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;aACnD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,GAAG,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;IACtD,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,MAAc,EAAE,MAAc;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC5C,OAAO;QACL,IAAI;QACJ,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,CAAC;KACpC,CAAA;AACH,CAAC;AAED,SAAS,OAAO,CAAC,MAAc,EAAE,KAAa,EAAE,MAAc;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,CAAC,CAAA;IACzC,OAAO;QACL,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC1B,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,EAAE;KAC7C,CAAA;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"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"}
|
package/dist/analyze.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import test from 'node:test';
|
|
3
|
-
import { analyzeCarve } from './analyze.js';
|
|
3
|
+
import { analyzeCarve, parseErrorRange, tolerantHeadingSymbols } from './analyze.js';
|
|
4
4
|
import { hoverAt } from './hover.js';
|
|
5
5
|
import { migrationCodeActions, migrationFixes } from './migration-actions.js';
|
|
6
6
|
import { semanticTokens } from './semantic.js';
|
|
@@ -21,6 +21,21 @@ test('inline literal gets a string semantic token spanning the whole construct',
|
|
|
21
21
|
const result = semanticTokens('Say !`/kaet/` now.\n');
|
|
22
22
|
assert.deepEqual(result.map((token) => [token.line, token.character, token.length, token.type]), [[0, 4, 9, 'string']]);
|
|
23
23
|
});
|
|
24
|
+
test('both footnote forms get a variable token across the AST split', () => {
|
|
25
|
+
// carve-js split `footnote` into `footnote_ref` and `inline_footnote`
|
|
26
|
+
// (markup-carve/carve#405). Asserted through source text rather than the type
|
|
27
|
+
// name, so it holds against the pinned engine and after the pin is raised -
|
|
28
|
+
// which is what makes the split safe to release in either order.
|
|
29
|
+
const tokens = semanticTokens('a[^r] and ^[n]\n\n[^r]: d\n').filter((t) => t.type === 'variable');
|
|
30
|
+
assert.equal(tokens.length, 2);
|
|
31
|
+
});
|
|
32
|
+
test('a critic comment gets a comment token under either AST spelling', () => {
|
|
33
|
+
// carve-js renamed this AST type from `critic-comment` to `critic_comment`
|
|
34
|
+
// (carve#401). This asserts through the source text rather than the type
|
|
35
|
+
// name, so it holds both against the currently pinned engine and after the
|
|
36
|
+
// pin is raised - which is what makes the rename safe to land out of order.
|
|
37
|
+
assert.deepEqual(semanticTokens('a {# note #} b\n').map((token) => [token.character, token.length, token.type]), [[2, 10, 'comment']]);
|
|
38
|
+
});
|
|
24
39
|
test('reports carve-breakage migration warnings', () => {
|
|
25
40
|
const result = analyzeCarve('**bold**');
|
|
26
41
|
assert.equal(result.diagnostics.length, 1);
|
|
@@ -215,4 +230,94 @@ test('returns semantic tokens for YAML frontmatter', () => {
|
|
|
215
230
|
[2, 0, 3, 'string'],
|
|
216
231
|
]);
|
|
217
232
|
});
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Include resolution (PART 9 §19)
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
test('includes are OFF by default: the directive stays literal and nothing is read', () => {
|
|
237
|
+
// §19 requires opt-in. `analyzeCarve` with no include options must not
|
|
238
|
+
// construct a capability, so a resolver is never consulted and no include
|
|
239
|
+
// diagnostic appears - the directive is just text.
|
|
240
|
+
const result = analyzeCarve('See {{ secret.crv }} here.\n');
|
|
241
|
+
assert.deepEqual(result.diagnostics.filter((d) => String(d.code ?? '').startsWith('include-')), []);
|
|
242
|
+
assert.deepEqual(result.dependencies, []);
|
|
243
|
+
});
|
|
244
|
+
test('include options carrying no resolver are still inert', () => {
|
|
245
|
+
const result = analyzeCarve('{{ child.crv }}\n', { includes: { sourcePath: '/doc.crv' } });
|
|
246
|
+
assert.deepEqual(result.dependencies, []);
|
|
247
|
+
assert.deepEqual(result.diagnostics.filter((d) => String(d.code ?? '').startsWith('include-')), []);
|
|
248
|
+
});
|
|
249
|
+
test('an enabled include publishes its warning as a diagnostic on the directive range', () => {
|
|
250
|
+
const source = 'intro\n\n{{ absent.crv }}\n';
|
|
251
|
+
const result = analyzeCarve(source, {
|
|
252
|
+
includes: {
|
|
253
|
+
resolver: (includePath) => ({ ok: false, id: includePath, denial: 'not-found' }),
|
|
254
|
+
sourcePath: '/doc.crv',
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
const diagnostic = result.diagnostics.find((d) => d.code === 'include-unresolved');
|
|
258
|
+
assert.ok(diagnostic, 'expected an include-unresolved diagnostic');
|
|
259
|
+
assert.deepEqual(diagnostic.range, {
|
|
260
|
+
start: { line: 2, character: 0 },
|
|
261
|
+
end: { line: 2, character: 16 },
|
|
262
|
+
});
|
|
263
|
+
assert.equal(diagnostic.source, 'carve');
|
|
264
|
+
assert.deepEqual(result.dependencies, [{ id: 'absent.crv', resolved: false }]);
|
|
265
|
+
});
|
|
266
|
+
test('a denial class never reaches the published diagnostic message', () => {
|
|
267
|
+
// §19 I7: the message names the failure class in the processor's own words.
|
|
268
|
+
// The internal denial (`outside-root`) is diagnostic detail, not author text,
|
|
269
|
+
// because a distinguishable denial is a probe for host layout.
|
|
270
|
+
const result = analyzeCarve('{{ ../secret.crv }}\n', {
|
|
271
|
+
includes: {
|
|
272
|
+
resolver: (includePath) => ({ ok: false, id: includePath, denial: 'outside-root' }),
|
|
273
|
+
sourcePath: '/doc.crv',
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
const diagnostic = result.diagnostics.find((d) => d.code === 'include-unresolved');
|
|
277
|
+
assert.ok(diagnostic);
|
|
278
|
+
assert.ok(!diagnostic.message.includes('outside-root'));
|
|
279
|
+
});
|
|
280
|
+
test('a nested warning names the child relative to the include root, not absolutely', () => {
|
|
281
|
+
const files = {
|
|
282
|
+
'/ws/a.crv': 'child\n\n{{ absent.crv }}',
|
|
283
|
+
};
|
|
284
|
+
const result = analyzeCarve('{{ a.crv }}\n', {
|
|
285
|
+
includes: {
|
|
286
|
+
resolver: (includePath) => {
|
|
287
|
+
const id = includePath.startsWith('/') ? includePath : `/ws/${includePath}`;
|
|
288
|
+
const source = files[id];
|
|
289
|
+
if (source === undefined)
|
|
290
|
+
return { ok: false, id, denial: 'not-found' };
|
|
291
|
+
return { ok: true, id, source, bytes: Buffer.byteLength(source, 'utf8') };
|
|
292
|
+
},
|
|
293
|
+
sourcePath: '/ws/doc.crv',
|
|
294
|
+
includeRoot: '/ws',
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
const diagnostic = result.diagnostics.find((d) => d.code === 'include-unresolved');
|
|
298
|
+
assert.ok(diagnostic);
|
|
299
|
+
assert.ok(diagnostic.message.includes('(in a.crv)'), diagnostic.message);
|
|
300
|
+
assert.ok(!diagnostic.message.includes('/ws/a.crv'));
|
|
301
|
+
});
|
|
302
|
+
test('locates parser errors that carry a line and column', () => {
|
|
303
|
+
assert.deepEqual(parseErrorRange('one\ntwo\n', 'Parse error at 2:3'), {
|
|
304
|
+
start: { line: 1, character: 2 },
|
|
305
|
+
end: { line: 1, character: 3 },
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
test('keeps a usable heading outline when resolved analysis is unavailable', () => {
|
|
309
|
+
assert.deepEqual(tolerantHeadingSymbols('# One\n\n## Two\n').map((symbol) => symbol.name), ['One', 'Two']);
|
|
310
|
+
});
|
|
311
|
+
test('duplicate diagnostics point back to the first declaration', () => {
|
|
312
|
+
const uri = 'file:///document.crv';
|
|
313
|
+
const heading = analyzeCarve('{#same}\n# One\n\n{#same}\n# Two\n', { uri });
|
|
314
|
+
const headingDuplicate = heading.diagnostics.find((item) => item.code === 'duplicate-heading-id');
|
|
315
|
+
assert.deepEqual(headingDuplicate?.relatedInformation, [{
|
|
316
|
+
location: { uri, range: { start: { line: 0, character: 2 }, end: { line: 0, character: 6 } } },
|
|
317
|
+
message: 'First declaration is here.',
|
|
318
|
+
}]);
|
|
319
|
+
const footnote = analyzeCarve('[^same]: one\n\n[^same]: two\n', { uri });
|
|
320
|
+
assert.equal(footnote.diagnostics.find((item) => item.code === 'duplicate-footnote-definition')
|
|
321
|
+
?.relatedInformation?.[0]?.location.range.start.line, 0);
|
|
322
|
+
});
|
|
218
323
|
//# sourceMappingURL=analyze.test.js.map
|