@markup-carve/carve-lsp 0.1.0 → 0.1.2
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 +55 -0
- package/dist/analyze.d.ts +17 -1
- package/dist/analyze.js +57 -1
- package/dist/analyze.js.map +1 -1
- package/dist/analyze.test.js +95 -0
- package/dist/analyze.test.js.map +1 -1
- package/dist/definition.js +26 -2
- package/dist/definition.js.map +1 -1
- package/dist/definition.test.js +8 -0
- package/dist/definition.test.js.map +1 -1
- package/dist/folding.js +4 -4
- package/dist/folding.js.map +1 -1
- package/dist/hover.js +33 -16
- package/dist/hover.js.map +1 -1
- 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-path.d.ts +63 -0
- package/dist/include-path.js +135 -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 +50 -0
- package/dist/include-settings.js +135 -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 +78 -0
- package/dist/includes.js +158 -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.js +7 -0
- package/dist/references.js.map +1 -1
- package/dist/semantic.d.ts +14 -0
- package/dist/semantic.js +113 -27
- package/dist/semantic.js.map +1 -1
- package/dist/semantic.test.d.ts +1 -0
- package/dist/semantic.test.js +93 -0
- package/dist/semantic.test.js.map +1 -0
- package/dist/server.js +50 -23
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-settings.js","sourceRoot":"","sources":["../src/include-settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { includeOptionsFor, readIncludeSettings, readWorkspaceTrusted, } from './include-settings.js';
|
|
8
|
+
function workspace() {
|
|
9
|
+
const dir = realpathSync(mkdtempSync(path.join(tmpdir(), 'carve-lsp-ws-')));
|
|
10
|
+
mkdirSync(path.join(dir, 'docs'), { recursive: true });
|
|
11
|
+
writeFileSync(path.join(dir, 'docs/main.crv'), '{{ child.crv }}\n');
|
|
12
|
+
writeFileSync(path.join(dir, 'docs/child.crv'), 'Child.\n');
|
|
13
|
+
test.after(() => rmSync(dir, { recursive: true, force: true }));
|
|
14
|
+
return dir;
|
|
15
|
+
}
|
|
16
|
+
const AUTO = { enabled: 'auto' };
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// §19: "MUST treat includes as opt-in (off for untrusted input)"
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
test('the default is OFF: auto plus an untrusted workspace yields no capability', () => {
|
|
21
|
+
const dir = workspace();
|
|
22
|
+
const options = includeOptionsFor({
|
|
23
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
24
|
+
settings: AUTO,
|
|
25
|
+
workspaceTrusted: false,
|
|
26
|
+
workspaceRoots: [dir],
|
|
27
|
+
});
|
|
28
|
+
assert.equal(options, undefined);
|
|
29
|
+
});
|
|
30
|
+
test('a client that says nothing about trust is treated as untrusted', () => {
|
|
31
|
+
assert.equal(readWorkspaceTrusted(undefined), false);
|
|
32
|
+
assert.equal(readWorkspaceTrusted({}), false);
|
|
33
|
+
assert.equal(readWorkspaceTrusted({ workspaceTrusted: 'yes' }), false);
|
|
34
|
+
assert.equal(readWorkspaceTrusted({ workspaceTrusted: true }), true);
|
|
35
|
+
});
|
|
36
|
+
test('auto plus a trusted workspace yields a resolver rooted at the workspace', () => {
|
|
37
|
+
const dir = workspace();
|
|
38
|
+
const options = includeOptionsFor({
|
|
39
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
40
|
+
settings: AUTO,
|
|
41
|
+
workspaceTrusted: true,
|
|
42
|
+
workspaceRoots: [dir],
|
|
43
|
+
});
|
|
44
|
+
assert.ok(options?.resolver);
|
|
45
|
+
assert.equal(options.includeRoot, dir);
|
|
46
|
+
assert.equal(options.sourcePath, path.join(dir, 'docs/main.crv'));
|
|
47
|
+
});
|
|
48
|
+
test('off wins over a trusted workspace', () => {
|
|
49
|
+
const dir = workspace();
|
|
50
|
+
const options = includeOptionsFor({
|
|
51
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
52
|
+
settings: { enabled: 'off' },
|
|
53
|
+
workspaceTrusted: true,
|
|
54
|
+
workspaceRoots: [dir],
|
|
55
|
+
});
|
|
56
|
+
assert.equal(options, undefined);
|
|
57
|
+
});
|
|
58
|
+
test('on enables includes without a trust report', () => {
|
|
59
|
+
const dir = workspace();
|
|
60
|
+
const options = includeOptionsFor({
|
|
61
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
62
|
+
settings: { enabled: 'on' },
|
|
63
|
+
workspaceTrusted: false,
|
|
64
|
+
workspaceRoots: [dir],
|
|
65
|
+
});
|
|
66
|
+
assert.ok(options?.resolver);
|
|
67
|
+
});
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Containment root selection
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
test('a file opened outside any workspace is rooted at its own directory, never the cwd', () => {
|
|
72
|
+
const dir = workspace();
|
|
73
|
+
const options = includeOptionsFor({
|
|
74
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
75
|
+
settings: { enabled: 'on' },
|
|
76
|
+
workspaceTrusted: false,
|
|
77
|
+
});
|
|
78
|
+
assert.equal(options?.includeRoot, path.join(dir, 'docs'));
|
|
79
|
+
assert.notEqual(options?.includeRoot, process.cwd());
|
|
80
|
+
});
|
|
81
|
+
test('a document is rooted at the workspace folder that contains it, not the first one', () => {
|
|
82
|
+
const dir = workspace();
|
|
83
|
+
const other = workspace();
|
|
84
|
+
const options = includeOptionsFor({
|
|
85
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
86
|
+
settings: { enabled: 'on' },
|
|
87
|
+
workspaceTrusted: true,
|
|
88
|
+
// The containing folder is listed second on purpose.
|
|
89
|
+
workspaceRoots: [other, dir],
|
|
90
|
+
});
|
|
91
|
+
assert.equal(options?.includeRoot, dir);
|
|
92
|
+
});
|
|
93
|
+
test('a document in none of the workspace folders falls back to its own directory', () => {
|
|
94
|
+
const dir = workspace();
|
|
95
|
+
const other = workspace();
|
|
96
|
+
const options = includeOptionsFor({
|
|
97
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
98
|
+
settings: { enabled: 'on' },
|
|
99
|
+
workspaceTrusted: true,
|
|
100
|
+
workspaceRoots: [other],
|
|
101
|
+
});
|
|
102
|
+
assert.equal(options?.includeRoot, path.join(dir, 'docs'));
|
|
103
|
+
});
|
|
104
|
+
test('the deepest containing workspace folder wins', () => {
|
|
105
|
+
const dir = workspace();
|
|
106
|
+
const options = includeOptionsFor({
|
|
107
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
108
|
+
settings: { enabled: 'on' },
|
|
109
|
+
workspaceTrusted: true,
|
|
110
|
+
workspaceRoots: [dir, path.join(dir, 'docs')],
|
|
111
|
+
});
|
|
112
|
+
assert.equal(options?.includeRoot, path.join(dir, 'docs'));
|
|
113
|
+
});
|
|
114
|
+
test('an explicit includeRoot wins over the workspace root', () => {
|
|
115
|
+
const dir = workspace();
|
|
116
|
+
const options = includeOptionsFor({
|
|
117
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
118
|
+
settings: { enabled: 'on', includeRoot: path.join(dir, 'docs') },
|
|
119
|
+
workspaceTrusted: true,
|
|
120
|
+
workspaceRoots: [dir],
|
|
121
|
+
});
|
|
122
|
+
assert.equal(options?.includeRoot, path.join(dir, 'docs'));
|
|
123
|
+
});
|
|
124
|
+
test('a root reached through a symlink is reported canonically', () => {
|
|
125
|
+
// The resolver returns canonical child ids. If `includeRoot` were the
|
|
126
|
+
// uncanonical spelling, every child would look like it sits outside the root
|
|
127
|
+
// and a diagnostic naming one would print an absolute filesystem path.
|
|
128
|
+
const dir = workspace();
|
|
129
|
+
const link = path.join(path.dirname(dir), `${path.basename(dir)}-link`);
|
|
130
|
+
symlinkSync(dir, link);
|
|
131
|
+
test.after(() => rmSync(link, { force: true }));
|
|
132
|
+
const options = includeOptionsFor({
|
|
133
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
134
|
+
settings: { enabled: 'on', includeRoot: link },
|
|
135
|
+
workspaceTrusted: true,
|
|
136
|
+
});
|
|
137
|
+
assert.equal(options?.includeRoot, dir);
|
|
138
|
+
});
|
|
139
|
+
test('a root that is not a real directory yields no capability rather than a wider one', () => {
|
|
140
|
+
const dir = workspace();
|
|
141
|
+
const options = includeOptionsFor({
|
|
142
|
+
uri: pathToFileURL(path.join(dir, 'docs/main.crv')).href,
|
|
143
|
+
settings: { enabled: 'on', includeRoot: path.join(dir, 'does-not-exist') },
|
|
144
|
+
workspaceTrusted: true,
|
|
145
|
+
workspaceRoots: [dir],
|
|
146
|
+
});
|
|
147
|
+
assert.equal(options, undefined);
|
|
148
|
+
});
|
|
149
|
+
test('a document with no filesystem identity gets no capability', () => {
|
|
150
|
+
const options = includeOptionsFor({
|
|
151
|
+
uri: 'untitled:Untitled-1',
|
|
152
|
+
settings: { enabled: 'on' },
|
|
153
|
+
workspaceTrusted: true,
|
|
154
|
+
workspaceRoots: ['/tmp'],
|
|
155
|
+
});
|
|
156
|
+
assert.equal(options, undefined);
|
|
157
|
+
});
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Settings parsing
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
test('an absent or unrecognized settings payload falls back to the default', () => {
|
|
162
|
+
assert.deepEqual(readIncludeSettings(undefined), { enabled: 'auto' });
|
|
163
|
+
assert.deepEqual(readIncludeSettings({}), { enabled: 'auto' });
|
|
164
|
+
assert.deepEqual(readIncludeSettings({ carve: { includes: { enabled: 'yes please' } } }), {
|
|
165
|
+
enabled: 'auto',
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
test('settings are read from the carve.includes section', () => {
|
|
169
|
+
const settings = readIncludeSettings({
|
|
170
|
+
carve: {
|
|
171
|
+
includes: {
|
|
172
|
+
enabled: 'on',
|
|
173
|
+
includeRoot: '/ws',
|
|
174
|
+
allowAbsolute: true,
|
|
175
|
+
allowedRemoteHosts: ['example.com', 7],
|
|
176
|
+
maxDepth: 4,
|
|
177
|
+
maxBytes: 2048,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
assert.deepEqual(settings, {
|
|
182
|
+
enabled: 'on',
|
|
183
|
+
includeRoot: '/ws',
|
|
184
|
+
allowAbsolute: true,
|
|
185
|
+
// Non-string hosts are dropped rather than trusted as given.
|
|
186
|
+
allowedRemoteHosts: ['example.com'],
|
|
187
|
+
maxDepth: 4,
|
|
188
|
+
maxBytes: 2048,
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
//# sourceMappingURL=include-settings.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-settings.test.js","sourceRoot":"","sources":["../src/include-settings.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { IncludeResolver } from './include-path.js';
|
|
2
|
+
/** Warning emitted by {@link resolveIncludes}. Shape mirrors the engine's. */
|
|
3
|
+
export interface IncludeWarning {
|
|
4
|
+
/** 1-based line number in the ROOT document. */
|
|
5
|
+
line: number;
|
|
6
|
+
/** 1-based column number in the ROOT document. */
|
|
7
|
+
column: number;
|
|
8
|
+
/** Stable rule id, e.g. "include-cycle". */
|
|
9
|
+
rule: string;
|
|
10
|
+
/** Human-readable explanation of the include degradation. */
|
|
11
|
+
message: string;
|
|
12
|
+
/**
|
|
13
|
+
* Failure class, when one exists. Kept OUT of `message` on purpose: §19 I7
|
|
14
|
+
* requires a processor-generated message naming the failure class rather
|
|
15
|
+
* than a resolver's own error, which routinely embeds absolute filesystem
|
|
16
|
+
* paths. Tools that want it (a log sink, a test) read it here; the published
|
|
17
|
+
* diagnostic does not print it.
|
|
18
|
+
*/
|
|
19
|
+
detail?: string;
|
|
20
|
+
/** 0-based start offset in the ROOT document, inclusive. */
|
|
21
|
+
start: number;
|
|
22
|
+
/** 0-based end offset in the ROOT document, exclusive. */
|
|
23
|
+
end: number;
|
|
24
|
+
/**
|
|
25
|
+
* Identity of the file the warning arose in: the resolver's canonical id, or
|
|
26
|
+
* the raw directive path when there is none. A directive that failed to
|
|
27
|
+
* resolve is attributed to the document containing it, not to the target it
|
|
28
|
+
* names; a warning raised while walking a child is attributed to that child.
|
|
29
|
+
*/
|
|
30
|
+
file?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* One include target touched during resolution. Hosts key file watchers off
|
|
34
|
+
* `id`, so unresolved targets are reported too: a watcher that followed only
|
|
35
|
+
* successful reads would never notice a missing `{{ chapter-3.crv }}` being
|
|
36
|
+
* created, and would stay stale in exactly the case includes are for.
|
|
37
|
+
*/
|
|
38
|
+
export interface IncludeDependency {
|
|
39
|
+
id: string;
|
|
40
|
+
/** True when the resolver produced source text for this target. */
|
|
41
|
+
resolved: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface IncludeOptions {
|
|
44
|
+
/** Resolve an include path to source text. Absent means the pass is inert. */
|
|
45
|
+
resolver?: IncludeResolver;
|
|
46
|
+
/** Identity of the root document, for warning attribution. */
|
|
47
|
+
sourcePath?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Containment root the resolver was built with. Not used for resolution -
|
|
50
|
+
* the resolver owns that - only so a host can render a child's identity
|
|
51
|
+
* relative to the root instead of as an absolute path (§19 I7).
|
|
52
|
+
*/
|
|
53
|
+
includeRoot?: string;
|
|
54
|
+
/** Maximum transitive include depth. Default 16. */
|
|
55
|
+
maxDepth?: number;
|
|
56
|
+
/** Total byte budget across the walk. Default max(1 MiB, 8 x root bytes). */
|
|
57
|
+
maxBytes?: number;
|
|
58
|
+
}
|
|
59
|
+
export interface IncludeResolution {
|
|
60
|
+
warnings: IncludeWarning[];
|
|
61
|
+
/**
|
|
62
|
+
* Every include target touched, nested children included, de-duplicated and
|
|
63
|
+
* in first-encounter order. Empty when no resolver was supplied.
|
|
64
|
+
*/
|
|
65
|
+
dependencies: IncludeDependency[];
|
|
66
|
+
/** Bytes charged against the budget. */
|
|
67
|
+
bytes: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Walk the include graph rooted at `source`.
|
|
71
|
+
*
|
|
72
|
+
* With no `resolver` the pass is INERT: no directive is recognized as
|
|
73
|
+
* actionable, nothing is read, and neither a warning nor a dependency is
|
|
74
|
+
* produced. That is how §19's "opt-in, off for untrusted input" is enforced at
|
|
75
|
+
* this layer - the capability does not exist until a host hands over a
|
|
76
|
+
* resolver, so no caller can reach the filesystem by forgetting a flag.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolveIncludes(source: string, options?: IncludeOptions): IncludeResolution;
|
package/dist/includes.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Processor-level include resolution for the language server (PART 9 §19).
|
|
3
|
+
*
|
|
4
|
+
* This walks the include graph and reports what it found; it does NOT expand
|
|
5
|
+
* anything into the document. The server publishes diagnostics, tracks
|
|
6
|
+
* dependencies and navigates - none of which needs merged text - and the
|
|
7
|
+
* merge itself (heading shifts, section selection, id and footnote renaming)
|
|
8
|
+
* is engine work that carve-js and carve-php own. Resolution lives here
|
|
9
|
+
* because §19 makes includes processor-level and the pinned engine has no
|
|
10
|
+
* include pass at all.
|
|
11
|
+
*
|
|
12
|
+
* Two of the six §19 MUSTs are properties of the graph rather than of a single
|
|
13
|
+
* path, so they are enforced here:
|
|
14
|
+
*
|
|
15
|
+
* - MUST bound recursion depth
|
|
16
|
+
* - MUST bound total expanded byte size
|
|
17
|
+
*
|
|
18
|
+
* The other four live in {@link ./include-path.js}.
|
|
19
|
+
*/
|
|
20
|
+
import { findDirectives } from './include-directive.js';
|
|
21
|
+
const MIN_BUDGET = 1024 * 1024;
|
|
22
|
+
const DEFAULT_MAX_DEPTH = 16;
|
|
23
|
+
function lineStarts(source) {
|
|
24
|
+
const starts = [0];
|
|
25
|
+
for (let i = 0; i < source.length; i += 1) {
|
|
26
|
+
if (source[i] === '\n')
|
|
27
|
+
starts.push(i + 1);
|
|
28
|
+
}
|
|
29
|
+
return starts;
|
|
30
|
+
}
|
|
31
|
+
function locate(state, offset) {
|
|
32
|
+
let low = 0;
|
|
33
|
+
let high = state.lineStarts.length - 1;
|
|
34
|
+
while (low < high) {
|
|
35
|
+
const mid = (low + high + 1) >> 1;
|
|
36
|
+
if (state.lineStarts[mid] <= offset)
|
|
37
|
+
low = mid;
|
|
38
|
+
else
|
|
39
|
+
high = mid - 1;
|
|
40
|
+
}
|
|
41
|
+
return { line: low + 1, column: offset - state.lineStarts[low] + 1 };
|
|
42
|
+
}
|
|
43
|
+
function warn(state, rule, message, at, file, detail) {
|
|
44
|
+
const warning = {
|
|
45
|
+
...locate(state, at.start),
|
|
46
|
+
rule,
|
|
47
|
+
message,
|
|
48
|
+
start: at.start,
|
|
49
|
+
end: at.end,
|
|
50
|
+
};
|
|
51
|
+
if (file !== undefined)
|
|
52
|
+
warning.file = file;
|
|
53
|
+
if (detail !== undefined)
|
|
54
|
+
warning.detail = detail;
|
|
55
|
+
state.warnings.push(warning);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Record an include target for host file watching. Deduplicated by id, first
|
|
59
|
+
* encounter fixes the order, and a later successful read upgrades an entry
|
|
60
|
+
* first seen unresolved.
|
|
61
|
+
*/
|
|
62
|
+
function note(state, id, resolved) {
|
|
63
|
+
if (resolved || !state.dependencies.has(id))
|
|
64
|
+
state.dependencies.set(id, resolved);
|
|
65
|
+
}
|
|
66
|
+
function visit(state, text, file, stack, depth, anchor) {
|
|
67
|
+
const directives = findDirectives(text, (part, start, end) => {
|
|
68
|
+
warn(state, 'include-unknown-option', `Unknown include option "${part}".`, anchor ?? { start, end }, file);
|
|
69
|
+
});
|
|
70
|
+
for (const directive of directives) {
|
|
71
|
+
// A nested warning is reported at the top-level directive that pulled the
|
|
72
|
+
// chain in, because that is the only range valid in the document the
|
|
73
|
+
// client has open. `file` says where it actually arose.
|
|
74
|
+
const at = anchor ?? { start: directive.start, end: directive.end };
|
|
75
|
+
// GUARD 4 (§19: MUST bound recursion depth). Checked before the resolver
|
|
76
|
+
// is called, so the over-deep target is never read - but it is still
|
|
77
|
+
// reported as a dependency, since a host may want to watch it.
|
|
78
|
+
if (depth >= state.maxDepth) {
|
|
79
|
+
note(state, directive.path, false);
|
|
80
|
+
warn(state, 'include-depth', `Include depth limit of ${state.maxDepth} exceeded for "${directive.path}".`, at, file);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// GUARD 5a (§19: MUST bound total expanded byte size). Once the budget is
|
|
84
|
+
// gone, later directives are refused BEFORE the resolver is called, so an
|
|
85
|
+
// exhausted budget also stops the reads. Without this a document with N
|
|
86
|
+
// sibling directives still pays N reads after expansion had already
|
|
87
|
+
// stopped.
|
|
88
|
+
if (state.usedBytes >= state.maxBytes) {
|
|
89
|
+
warn(state, 'include-budget', `Include byte budget exceeded by "${directive.path}".`, at, file);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
let resolved;
|
|
93
|
+
try {
|
|
94
|
+
resolved = state.resolver(directive.path, {
|
|
95
|
+
stack: [...stack],
|
|
96
|
+
depth,
|
|
97
|
+
...(state.sourcePath !== undefined ? { sourcePath: state.sourcePath } : {}),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
note(state, directive.path, false);
|
|
102
|
+
warn(state, 'include-unresolved', `Include "${directive.path}" could not be resolved.`, at, file, error instanceof Error ? error.message : String(error));
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (!resolved.ok) {
|
|
106
|
+
note(state, resolved.id, false);
|
|
107
|
+
warn(state, 'include-unresolved', `Include "${directive.path}" could not be resolved.`, at, file, resolved.denial);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
note(state, resolved.id, true);
|
|
111
|
+
if (stack.includes(resolved.id)) {
|
|
112
|
+
warn(state, 'include-cycle', `Include cycle detected for "${directive.path}".`, at, file);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// GUARD 5 (§19: MUST bound total expanded byte size). The budget is
|
|
116
|
+
// charged per OCCURRENCE, not per distinct file, so a document that
|
|
117
|
+
// includes the same target N times pays N times - which is the shape an
|
|
118
|
+
// include bomb actually takes.
|
|
119
|
+
state.usedBytes += resolved.bytes;
|
|
120
|
+
if (state.usedBytes > state.maxBytes) {
|
|
121
|
+
warn(state, 'include-budget', `Include byte budget exceeded by "${directive.path}".`, at, file);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
visit(state, resolved.source, resolved.id, [...stack, resolved.id], depth + 1, at);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Walk the include graph rooted at `source`.
|
|
129
|
+
*
|
|
130
|
+
* With no `resolver` the pass is INERT: no directive is recognized as
|
|
131
|
+
* actionable, nothing is read, and neither a warning nor a dependency is
|
|
132
|
+
* produced. That is how §19's "opt-in, off for untrusted input" is enforced at
|
|
133
|
+
* this layer - the capability does not exist until a host hands over a
|
|
134
|
+
* resolver, so no caller can reach the filesystem by forgetting a flag.
|
|
135
|
+
*/
|
|
136
|
+
export function resolveIncludes(source, options = {}) {
|
|
137
|
+
if (!options.resolver)
|
|
138
|
+
return { warnings: [], dependencies: [], bytes: 0 };
|
|
139
|
+
const normalized = source.replace(/\r\n?/g, '\n');
|
|
140
|
+
const state = {
|
|
141
|
+
resolver: options.resolver,
|
|
142
|
+
sourcePath: options.sourcePath,
|
|
143
|
+
maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
144
|
+
maxBytes: options.maxBytes ?? Math.max(MIN_BUDGET, Buffer.byteLength(normalized, 'utf8') * 8),
|
|
145
|
+
usedBytes: 0,
|
|
146
|
+
warnings: [],
|
|
147
|
+
dependencies: new Map(),
|
|
148
|
+
lineStarts: lineStarts(normalized),
|
|
149
|
+
};
|
|
150
|
+
const rootStack = options.sourcePath !== undefined ? [options.sourcePath] : [];
|
|
151
|
+
visit(state, normalized, options.sourcePath, rootStack, 0, null);
|
|
152
|
+
return {
|
|
153
|
+
warnings: state.warnings,
|
|
154
|
+
dependencies: [...state.dependencies].map(([id, resolved]) => ({ id, resolved })),
|
|
155
|
+
bytes: state.usedBytes,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=includes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"includes.js","sourceRoot":"","sources":["../src/includes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AA0EvD,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAA;AAC9B,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAmB5B,SAAS,UAAU,CAAC,MAAc;IAChC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC5C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,MAAM,CAAC,KAAY,EAAE,MAAc;IAC1C,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,IAAI,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAA;IACtC,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAE,IAAI,MAAM;YAAE,GAAG,GAAG,GAAG,CAAA;;YAC1C,IAAI,GAAG,GAAG,GAAG,CAAC,CAAA;IACrB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAE,GAAG,CAAC,EAAE,CAAA;AACvE,CAAC;AAED,SAAS,IAAI,CACX,KAAY,EACZ,IAAY,EACZ,OAAe,EACf,EAAU,EACV,IAAwB,EACxB,MAAe;IAEf,MAAM,OAAO,GAAmB;QAC9B,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;QAC1B,IAAI;QACJ,OAAO;QACP,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,GAAG,EAAE,EAAE,CAAC,GAAG;KACZ,CAAA;IACD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAA;IAC3C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAA;IACjD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC9B,CAAC;AAED;;;;GAIG;AACH,SAAS,IAAI,CAAC,KAAY,EAAE,EAAU,EAAE,QAAiB;IACvD,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;AACnF,CAAC;AAED,SAAS,KAAK,CACZ,KAAY,EACZ,IAAY,EACZ,IAAwB,EACxB,KAAe,EACf,KAAa,EACb,MAAqB;IAErB,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC3D,IAAI,CACF,KAAK,EACL,wBAAwB,EACxB,2BAA2B,IAAI,IAAI,EACnC,MAAM,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EACxB,IAAI,CACL,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,0EAA0E;QAC1E,qEAAqE;QACrE,wDAAwD;QACxD,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CAAA;QAEnE,yEAAyE;QACzE,qEAAqE;QACrE,+DAA+D;QAC/D,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAClC,IAAI,CACF,KAAK,EACL,eAAe,EACf,0BAA0B,KAAK,CAAC,QAAQ,kBAAkB,SAAS,CAAC,IAAI,IAAI,EAC5E,EAAE,EACF,IAAI,CACL,CAAA;YACD,SAAQ;QACV,CAAC;QAED,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,oEAAoE;QACpE,WAAW;QACX,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACtC,IAAI,CACF,KAAK,EACL,gBAAgB,EAChB,oCAAoC,SAAS,CAAC,IAAI,IAAI,EACtD,EAAE,EACF,IAAI,CACL,CAAA;YACD,SAAQ;QACV,CAAC;QAED,IAAI,QAAQ,CAAA;QACZ,IAAI,CAAC;YACH,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE;gBACxC,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;gBACjB,KAAK;gBACL,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5E,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAClC,IAAI,CACF,KAAK,EACL,oBAAoB,EACpB,YAAY,SAAS,CAAC,IAAI,0BAA0B,EACpD,EAAE,EACF,IAAI,EACJ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAA;YACD,SAAQ;QACV,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;YAC/B,IAAI,CACF,KAAK,EACL,oBAAoB,EACpB,YAAY,SAAS,CAAC,IAAI,0BAA0B,EACpD,EAAE,EACF,IAAI,EACJ,QAAQ,CAAC,MAAM,CAChB,CAAA;YACD,SAAQ;QACV,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;QAE9B,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,+BAA+B,SAAS,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;YACzF,SAAQ;QACV,CAAC;QAED,oEAAoE;QACpE,oEAAoE;QACpE,wEAAwE;QACxE,+BAA+B;QAC/B,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAA;QACjC,IAAI,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,IAAI,CACF,KAAK,EACL,gBAAgB,EAChB,oCAAoC,SAAS,CAAC,IAAI,IAAI,EACtD,EAAE,EACF,IAAI,CACL,CAAA;YACD,SAAQ;QACV,CAAC;QAED,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;IACpF,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,UAA0B,EAAE;IAC1E,IAAI,CAAC,OAAO,CAAC,QAAQ;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAE1E,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACjD,MAAM,KAAK,GAAU;QACnB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,iBAAiB;QAC/C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7F,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;KACnC,CAAA;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC9E,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;IAEhE,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjF,KAAK,EAAE,KAAK,CAAC,SAAS;KACvB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|