@swiftuijs/twill 0.3.0 → 0.4.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/README.md +8 -3
- package/bin/run.mjs +2 -2
- package/dist/branches.d.ts +7 -1
- package/dist/cli.js +7 -8
- package/dist/{compilation-cache-7SugqJ4n.js → compilation-cache-BrV71YKt.js} +2 -3
- package/dist/{compilation-cache-7SugqJ4n.js.map → compilation-cache-BrV71YKt.js.map} +1 -1
- package/dist/{compiler-CbNSBUI2.js → compiler-DI0H4d1R.js} +178 -66
- package/dist/compiler-DI0H4d1R.js.map +1 -0
- package/dist/compiler.d.ts +2 -0
- package/dist/config-la_KkjCS.js +1 -0
- package/dist/config.js +2 -2
- package/dist/{configuration-BVMf6Q_j.js → configuration-ppqhmuy4.js} +7 -5
- package/dist/configuration-ppqhmuy4.js.map +1 -0
- package/dist/configuration.d.ts +1 -1
- package/dist/declarations-DXtb1AHP.js +131 -0
- package/dist/declarations-DXtb1AHP.js.map +1 -0
- package/dist/declarations.js +1 -132
- package/dist/doctor-BHwU_YBw.js +200 -0
- package/dist/doctor-BHwU_YBw.js.map +1 -0
- package/dist/doctor.js +1 -202
- package/dist/editor.d.ts +1 -0
- package/dist/editor.js +31 -5
- package/dist/editor.js.map +1 -1
- package/dist/esbuild.js +2 -3
- package/dist/{extensions-B1xTkoYP.js → extensions-7ixttcoK.js} +2 -3
- package/dist/{extensions-B1xTkoYP.js.map → extensions-7ixttcoK.js.map} +1 -1
- package/dist/{files-BW9geU0_.js → files-CgwJJ992.js} +3 -4
- package/dist/{files-BW9geU0_.js.map → files-CgwJJ992.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/{loader-compiler-D1teTrXw.js → loader-compiler.js} +4 -5
- package/dist/loader-compiler.js.map +1 -0
- package/dist/loader-registration-BO43rvVU.js +14 -0
- package/dist/loader-registration-BO43rvVU.js.map +1 -0
- package/dist/loader-registration.d.ts +4 -0
- package/dist/loader-registration.js +1 -0
- package/dist/loader-state-DB7sONR_.js +60 -0
- package/dist/loader-state-DB7sONR_.js.map +1 -0
- package/dist/loader-state.d.ts +34 -0
- package/dist/loader-sync.d.ts +3 -0
- package/dist/loader-sync.js +27 -0
- package/dist/loader-sync.js.map +1 -0
- package/dist/loader.d.ts +2 -4
- package/dist/loader.js +10 -48
- package/dist/loader.js.map +1 -1
- package/dist/{plugin-BHfiQ2L-.js → plugin-DDOHhv7Z.js} +6 -7
- package/dist/{plugin-BHfiQ2L-.js.map → plugin-DDOHhv7Z.js.map} +1 -1
- package/dist/project-DYXf2Kgt.js +442 -0
- package/dist/project-DYXf2Kgt.js.map +1 -0
- package/dist/project.js +2 -443
- package/dist/register.js +3 -4
- package/dist/register.js.map +1 -1
- package/dist/rollup.js +2 -3
- package/dist/rspack.js +2 -3
- package/dist/syntax.js +2 -3
- package/dist/{transpile-D8P8Lsbx.js → transpile--6CFGUm0.js} +3 -4
- package/dist/{transpile-D8P8Lsbx.js.map → transpile--6CFGUm0.js.map} +1 -1
- package/dist/typescript-plugin.cjs +252 -128
- package/dist/typescript-plugin.cjs.map +1 -1
- package/dist/vite-D0Ct4uy4.js +6 -0
- package/dist/vite-D0Ct4uy4.js.map +1 -0
- package/dist/vite-react.js +2 -3
- package/dist/vite.js +1 -7
- package/dist/webpack.js +2 -3
- package/package.json +3 -3
- package/schemas/twill.schema.json +6 -0
- package/dist/compiler-CbNSBUI2.js.map +0 -1
- package/dist/configuration-BVMf6Q_j.js.map +0 -1
- package/dist/declarations.js.map +0 -1
- package/dist/doctor.js.map +0 -1
- package/dist/loader-compiler-D1teTrXw.js.map +0 -1
- package/dist/project.js.map +0 -1
- package/dist/vite.js.map +0 -1
package/dist/doctor.js
CHANGED
|
@@ -1,202 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import ts from "typescript";
|
|
3
|
-
var package_default = {
|
|
4
|
-
name: "@swiftuijs/twill",
|
|
5
|
-
version: "0.3.0",
|
|
6
|
-
description: "Twill extends TypeScript with Swift-inspired syntax: trailing closures, guards, defer and checked switch expressions. Compiles to ordinary JavaScript.",
|
|
7
|
-
main: "./dist/typescript-plugin.cjs",
|
|
8
|
-
repository: {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/swiftuijs/twill.git",
|
|
11
|
-
"directory": "packages/twill"
|
|
12
|
-
},
|
|
13
|
-
keywords: [
|
|
14
|
-
"javascript",
|
|
15
|
-
"typescript",
|
|
16
|
-
"trailing-closures",
|
|
17
|
-
"swift",
|
|
18
|
-
"vite",
|
|
19
|
-
"unplugin",
|
|
20
|
-
"react",
|
|
21
|
-
"vue",
|
|
22
|
-
"twill",
|
|
23
|
-
"guard",
|
|
24
|
-
"defer"
|
|
25
|
-
],
|
|
26
|
-
author: {
|
|
27
|
-
"name": "forth.ink",
|
|
28
|
-
"url": "https://forth.ink"
|
|
29
|
-
},
|
|
30
|
-
license: "MIT",
|
|
31
|
-
type: "module",
|
|
32
|
-
bugs: { "url": "https://github.com/swiftuijs/twill/issues" },
|
|
33
|
-
homepage: "https://twill.evecalm.com/",
|
|
34
|
-
dependencies: {
|
|
35
|
-
"@ampproject/remapping": "^2.3.0",
|
|
36
|
-
"@jridgewell/trace-mapping": "^0.3.31",
|
|
37
|
-
"acorn": "8.18.0",
|
|
38
|
-
"acorn-jsx": "^5.3.2",
|
|
39
|
-
"acorn-typescript": "1.4.13",
|
|
40
|
-
"magic-string": "^1.4.2",
|
|
41
|
-
"typescript": "catalog:",
|
|
42
|
-
"unplugin": "^3.4.0"
|
|
43
|
-
},
|
|
44
|
-
sideEffects: false,
|
|
45
|
-
engines: { "node": "^20.19.0 || >=22.12.0" },
|
|
46
|
-
files: [
|
|
47
|
-
"bin",
|
|
48
|
-
"dist/**/*.js",
|
|
49
|
-
"dist/**/*.js.map",
|
|
50
|
-
"dist/**/*.d.ts",
|
|
51
|
-
"schemas",
|
|
52
|
-
"README.md",
|
|
53
|
-
"LICENSE",
|
|
54
|
-
"dist/**/*.cjs",
|
|
55
|
-
"dist/**/*.cjs.map",
|
|
56
|
-
"dist/*.LICENSE.txt"
|
|
57
|
-
],
|
|
58
|
-
bin: { "twill": "./bin/twill.mjs" },
|
|
59
|
-
exports: {
|
|
60
|
-
".": {
|
|
61
|
-
"types": "./dist/index.d.ts",
|
|
62
|
-
"import": "./dist/index.js"
|
|
63
|
-
},
|
|
64
|
-
"./vite": {
|
|
65
|
-
"types": "./dist/vite.d.ts",
|
|
66
|
-
"import": "./dist/vite.js"
|
|
67
|
-
},
|
|
68
|
-
"./rollup": {
|
|
69
|
-
"types": "./dist/rollup.d.ts",
|
|
70
|
-
"import": "./dist/rollup.js"
|
|
71
|
-
},
|
|
72
|
-
"./esbuild": {
|
|
73
|
-
"types": "./dist/esbuild.d.ts",
|
|
74
|
-
"import": "./dist/esbuild.js"
|
|
75
|
-
},
|
|
76
|
-
"./webpack": {
|
|
77
|
-
"types": "./dist/webpack.d.ts",
|
|
78
|
-
"import": "./dist/webpack.js"
|
|
79
|
-
},
|
|
80
|
-
"./rspack": {
|
|
81
|
-
"types": "./dist/rspack.d.ts",
|
|
82
|
-
"import": "./dist/rspack.js"
|
|
83
|
-
},
|
|
84
|
-
"./project": {
|
|
85
|
-
"types": "./dist/project.d.ts",
|
|
86
|
-
"import": "./dist/project.js"
|
|
87
|
-
},
|
|
88
|
-
"./editor": {
|
|
89
|
-
"types": "./dist/editor.d.ts",
|
|
90
|
-
"import": "./dist/editor.js"
|
|
91
|
-
},
|
|
92
|
-
"./register": {
|
|
93
|
-
"types": "./dist/register.d.ts",
|
|
94
|
-
"import": "./dist/register.js"
|
|
95
|
-
},
|
|
96
|
-
"./schema": "./schemas/twill.schema.json",
|
|
97
|
-
"./typescript-plugin": {
|
|
98
|
-
"types": "./dist/typescript-plugin.d.ts",
|
|
99
|
-
"require": "./dist/typescript-plugin.cjs",
|
|
100
|
-
"default": "./dist/typescript-plugin.cjs"
|
|
101
|
-
},
|
|
102
|
-
"./doctor": {
|
|
103
|
-
"types": "./dist/doctor.d.ts",
|
|
104
|
-
"import": "./dist/doctor.js"
|
|
105
|
-
},
|
|
106
|
-
"./syntax": {
|
|
107
|
-
"types": "./dist/syntax.d.ts",
|
|
108
|
-
"import": "./dist/syntax.js"
|
|
109
|
-
},
|
|
110
|
-
"./config": {
|
|
111
|
-
"types": "./dist/config.d.ts",
|
|
112
|
-
"import": "./dist/config.js"
|
|
113
|
-
},
|
|
114
|
-
"./declarations": {
|
|
115
|
-
"types": "./dist/declarations.d.ts",
|
|
116
|
-
"import": "./dist/declarations.js"
|
|
117
|
-
},
|
|
118
|
-
"./vite-react": {
|
|
119
|
-
"types": "./dist/vite-react.d.ts",
|
|
120
|
-
"import": "./dist/vite-react.js"
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
peerDependencies: {
|
|
124
|
-
"react": "^18.2.0 || ^19.0.0",
|
|
125
|
-
"vue": "^3.3.0",
|
|
126
|
-
"@vitejs/plugin-react": "^6.1.1"
|
|
127
|
-
},
|
|
128
|
-
peerDependenciesMeta: {
|
|
129
|
-
"react": { "optional": true },
|
|
130
|
-
"vue": { "optional": true },
|
|
131
|
-
"@vitejs/plugin-react": { "optional": true }
|
|
132
|
-
},
|
|
133
|
-
types: "./dist/index.d.ts",
|
|
134
|
-
publishConfig: { "access": "public" },
|
|
135
|
-
module: "./dist/index.js",
|
|
136
|
-
scripts: {
|
|
137
|
-
"build": "node ../../scripts/generate-runtime-helper.mjs && vite build && vite build --config vite.plugin.config.ts && node scripts/prepare-core.mjs",
|
|
138
|
-
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
139
|
-
"prepack": "pnpm run build",
|
|
140
|
-
"test:unit": "vitest run",
|
|
141
|
-
"test:watch": "vitest",
|
|
142
|
-
"test:coverage": "vitest run --coverage",
|
|
143
|
-
"test:package": "node tests/consumer.mjs",
|
|
144
|
-
"test:size": "node tests/bundle-size.mjs",
|
|
145
|
-
"test:browser": "playwright test",
|
|
146
|
-
"benchmark": "node benchmarks/compiler.mjs",
|
|
147
|
-
"test": "pnpm run test:unit",
|
|
148
|
-
"benchmark:branching": "node benchmarks/branching.mjs",
|
|
149
|
-
"benchmark:enum-patterns": "node benchmarks/enum-patterns.mjs",
|
|
150
|
-
"benchmark:runtime": "node benchmarks/runtime-helpers.mjs",
|
|
151
|
-
"benchmark:if-bindings": "node benchmarks/if-bindings.mjs"
|
|
152
|
-
},
|
|
153
|
-
devDependencies: {
|
|
154
|
-
"vite": "catalog:",
|
|
155
|
-
"vite-plugin-dts": "^5.1.2",
|
|
156
|
-
"@types/node": "catalog:",
|
|
157
|
-
"@vitejs/plugin-react": "catalog:",
|
|
158
|
-
"vitest": "catalog:",
|
|
159
|
-
"@vitest/coverage-v8": "catalog:",
|
|
160
|
-
"@rspack/core": "catalog:",
|
|
161
|
-
"@types/react": "catalog:",
|
|
162
|
-
"@types/react-dom": "catalog:",
|
|
163
|
-
"@vue/server-renderer": "catalog:",
|
|
164
|
-
"esbuild": "catalog:",
|
|
165
|
-
"react": "catalog:",
|
|
166
|
-
"react-dom": "catalog:",
|
|
167
|
-
"rollup": "catalog:",
|
|
168
|
-
"vue": "catalog:",
|
|
169
|
-
"webpack": "catalog:",
|
|
170
|
-
"@playwright/test": "catalog:",
|
|
171
|
-
"@swiftuijs/twill-runtime": "workspace:*"
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
//#endregion
|
|
175
|
-
//#region src/doctor.ts
|
|
176
|
-
/** Shareable diagnostics without source contents or environment-variable values. */
|
|
177
|
-
function inspectProject(project, filename) {
|
|
178
|
-
const started = performance.now();
|
|
179
|
-
const diagnostics = project.diagnostics(filename);
|
|
180
|
-
const files = project.sourceFiles();
|
|
181
|
-
return {
|
|
182
|
-
twillVersion: package_default.version,
|
|
183
|
-
typescriptVersion: ts.version,
|
|
184
|
-
nodeVersion: process.version,
|
|
185
|
-
root: project.root,
|
|
186
|
-
configFiles: project.configFiles,
|
|
187
|
-
compilerOptions: project.compilerOptions,
|
|
188
|
-
files: {
|
|
189
|
-
total: files.length,
|
|
190
|
-
twill: files.filter(isTwillFile).length,
|
|
191
|
-
native: files.filter((file) => !isTwillFile(file)).length
|
|
192
|
-
},
|
|
193
|
-
sourceFiles: files,
|
|
194
|
-
diagnostics,
|
|
195
|
-
diagnosticTimeMs: performance.now() - started,
|
|
196
|
-
ok: !diagnostics.some((diagnostic) => diagnostic.category === "error")
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
//#endregion
|
|
200
|
-
export { inspectProject };
|
|
201
|
-
|
|
202
|
-
//# sourceMappingURL=doctor.js.map
|
|
1
|
+
export { t as inspectProject } from "./doctor-BHwU_YBw.js";
|
package/dist/editor.d.ts
CHANGED
package/dist/editor.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
1
|
+
import { n as sourceFilename, r as virtualFilename } from "./project-DYXf2Kgt.js";
|
|
2
|
+
import { n as isTwillFile } from "./extensions-7ixttcoK.js";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
-
|
|
4
|
+
// src/editor.ts
|
|
5
5
|
/** Shared semantic requests and conservative source edits for both editor hosts. */
|
|
6
6
|
var TwillEditor = class {
|
|
7
7
|
project;
|
|
8
8
|
attributeCache = /* @__PURE__ */ new WeakMap();
|
|
9
9
|
descriptorCache = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
internalBindingCache = /* @__PURE__ */ new WeakMap();
|
|
10
11
|
constructor(project) {
|
|
11
12
|
this.project = project;
|
|
12
13
|
}
|
|
@@ -57,11 +58,37 @@ var TwillEditor = class {
|
|
|
57
58
|
}
|
|
58
59
|
completions(filename, position, preferences = {}) {
|
|
59
60
|
let { offset, props } = this.completionLocation(filename, position);
|
|
60
|
-
|
|
61
|
+
let info = this.project.service.getCompletionsAtPosition(virtualFilename(filename), offset, {
|
|
61
62
|
includeCompletionsForModuleExports: true,
|
|
62
63
|
includeCompletionsWithInsertText: true,
|
|
63
64
|
...preferences
|
|
64
65
|
});
|
|
66
|
+
if (info && !info.isMemberCompletion && isTwillFile(sourceFilename(filename)) && this.project.transformed(filename)?.changed) {
|
|
67
|
+
const file = this.sourceFile(filename);
|
|
68
|
+
if (file) {
|
|
69
|
+
let internal = this.internalBindingCache.get(file);
|
|
70
|
+
if (!internal) {
|
|
71
|
+
internal = /* @__PURE__ */ new Set();
|
|
72
|
+
const visit = (node) => {
|
|
73
|
+
if (ts.isIdentifier(node) && node.text.startsWith("__twill")) {
|
|
74
|
+
const parent = node.parent;
|
|
75
|
+
if ((ts.isVariableDeclaration(parent) || ts.isBindingElement(parent) || ts.isParameter(parent) || ts.isTypeAliasDeclaration(parent) || ts.isFunctionDeclaration(parent)) && parent.name === node && !this.mapSpan(filename, {
|
|
76
|
+
start: node.getStart(),
|
|
77
|
+
length: node.getWidth()
|
|
78
|
+
})) internal.add(node.text);
|
|
79
|
+
}
|
|
80
|
+
ts.forEachChild(node, visit);
|
|
81
|
+
};
|
|
82
|
+
visit(file);
|
|
83
|
+
this.internalBindingCache.set(file, internal);
|
|
84
|
+
}
|
|
85
|
+
const hidden = internal;
|
|
86
|
+
if (hidden.size) info = {
|
|
87
|
+
...info,
|
|
88
|
+
entries: info.entries.filter((entry) => !hidden.has(entry.name))
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
65
92
|
if (props && !info?.isMemberCompletion) props = void 0;
|
|
66
93
|
return {
|
|
67
94
|
offset,
|
|
@@ -326,7 +353,6 @@ var TwillEditor = class {
|
|
|
326
353
|
});
|
|
327
354
|
}
|
|
328
355
|
};
|
|
329
|
-
//#endregion
|
|
330
356
|
export { TwillEditor };
|
|
331
357
|
|
|
332
358
|
//# sourceMappingURL=editor.js.map
|
package/dist/editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.js","names":[],"sources":["../src/editor.ts"],"sourcesContent":["import ts from 'typescript';\nimport { TwillProject, sourceFilename, virtualFilename } from './project.js';\nimport { isTwillFile, type TransformResult } from './compiler.js';\n\nexport interface SourceEdit {\n filename: string;\n span: ts.TextSpan;\n newText: string;\n}\n\nexport interface CompletionRequest {\n offset: number;\n info: ts.CompletionInfo | undefined;\n props?: { start: number; end: number };\n}\n\n/** Shared semantic requests and conservative source edits for both editor hosts. */\nexport class TwillEditor {\n private attributeCache = new WeakMap<ts.SourceFile, ts.JsxAttribute[]>();\n private descriptorCache = new WeakMap<ts.Program, Set<ts.Symbol>>();\n constructor(readonly project: TwillProject) {}\n\n private sourceFile(filename: string) {\n return this.project.service.getProgram()?.getSourceFile(virtualFilename(filename));\n }\n\n private attributes(filename: string) {\n const file = this.sourceFile(filename);\n if (!file) return [];\n const cached = this.attributeCache.get(file);\n if (cached) return cached;\n const result: ts.JsxAttribute[] = [];\n const visit = (node: ts.Node) => {\n if (ts.isJsxAttribute(node)) result.push(node);\n ts.forEachChild(node, visit);\n };\n visit(file);\n this.attributeCache.set(file, result);\n return result;\n }\n\n completionLocation(filename: string, position: number) {\n let offset = this.project.toGeneratedOffset(filename, position);\n // A repaired member name and generated arm punctuation can share the same\n // original boundary. Anchor requests at the source-backed dot instead.\n const prefix = this.project.text(filename)?.slice(0, position);\n const member = prefix?.match(/\\.([\\p{ID_Continue}$\\u200c\\u200d]*)$/u);\n const missingMember = prefix?.match(/\\.\\s*$/);\n if (member) offset = this.project.toGeneratedOffset(filename, member.index!) + member[0].length;\n else if (missingMember)\n offset = this.project.toGeneratedOffset(filename, missingMember.index!) + 1;\n let props: CompletionRequest['props'];\n const metadata = this.project.transformed(filename)?.componentProps;\n const property = metadata\n ?.flatMap((object) => object.properties)\n .find((item) => item.shorthand && position >= item.start && position <= item.end);\n if (property) {\n const attribute = this.attributes(filename).find(\n (item) =>\n item.name.getText() === property.name &&\n item.initializer &&\n ts.isJsxExpression(item.initializer) &&\n item.initializer.expression &&\n this.project.toOriginalOffset(filename, item.initializer.expression.getStart()) ===\n property.start,\n );\n if (attribute) {\n offset = attribute.name.getStart() + position - property.start;\n props = { start: property.start, end: property.end };\n }\n } else if (\n metadata?.some((object) => position > object.start && position < object.end) &&\n !this.attributes(filename).some(\n (attribute) => offset >= attribute.name.end && offset <= attribute.end,\n )\n ) {\n // Empty objects and gaps between properties already map to JSX attribute\n // positions. Only classify requests that TS identifies as member lists.\n props = { start: position, end: position };\n }\n return { offset, props };\n }\n\n completions(filename: string, position: number, preferences: ts.UserPreferences = {}) {\n let { offset, props } = this.completionLocation(filename, position);\n const info = this.project.service.getCompletionsAtPosition(virtualFilename(filename), offset, {\n includeCompletionsForModuleExports: true,\n includeCompletionsWithInsertText: true,\n ...preferences,\n });\n if (props && !info?.isMemberCompletion) props = undefined;\n return { offset, info, props } satisfies CompletionRequest;\n }\n\n /** Never stretch a generated edit across lowered punctuation or helper code. */\n mapSpan(filename: string, span: ts.TextSpan): ts.TextSpan | undefined {\n filename = sourceFilename(filename);\n const source = this.project.text(filename);\n if (source === undefined) return undefined;\n if (!isTwillFile(filename))\n return span.start >= 0 && span.start + span.length <= source.length ? span : undefined;\n const transformed = this.project.transformed(filename);\n const generated = transformed?.code;\n if (generated === undefined) return undefined;\n const start = this.project.toOriginalOffset(filename, span.start);\n if (\n start < 0 ||\n start + span.length > source.length ||\n (this.project.toGeneratedOffset(filename, start) !== span.start &&\n !transformed!.enumCopies.some(\n (copy) =>\n (span.start >= copy.generatedStart &&\n span.start + span.length <= copy.generatedStart + copy.length &&\n start === copy.sourceStart + span.start - copy.generatedStart) ||\n (start >= copy.sourceStart &&\n start + span.length <= copy.sourceStart + copy.length &&\n this.project.toOriginalOffset(filename, span.start + span.length - 1) ===\n start + span.length - 1),\n )) ||\n source.slice(start, start + span.length) !==\n generated.slice(span.start, span.start + span.length)\n )\n return undefined;\n return { start, length: span.length };\n }\n\n mapChanges(changes: readonly ts.FileTextChanges[]): SourceEdit[] | undefined {\n const edits: SourceEdit[] = [];\n for (const file of changes) {\n if (file.isNewFile) return undefined;\n const filename = sourceFilename(file.fileName);\n for (const change of file.textChanges) {\n let span = this.mapSpan(filename, change.span);\n // Inferred JSX runtime pragmas can precede the first source token.\n // A fresh import can safely be inserted before the original module.\n if (!span && change.span.length === 0 && /^\\s*import\\b/.test(change.newText)) {\n const firstStatement = this.sourceFile(filename)?.statements[0];\n if (change.span.start <= (firstStatement?.getStart() ?? 0))\n span = { start: 0, length: 0 };\n }\n if (!span) return undefined;\n edits.push({ filename, span, newText: this.importText(change.newText) });\n }\n }\n return edits;\n }\n\n private importText(text: string) {\n // Edit only module literals, never user strings in an unrelated code fix.\n const file = ts.createSourceFile('edits.ts', text, ts.ScriptTarget.Latest, true);\n const replacements: { start: number; end: number; text: string }[] = [];\n for (const statement of file.statements) {\n if (\n (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) &&\n statement.moduleSpecifier &&\n ts.isStringLiteral(statement.moduleSpecifier)\n ) {\n const literal = statement.moduleSpecifier;\n const value = sourceFilename(literal.text);\n if (value !== literal.text)\n replacements.push({ start: literal.getStart() + 1, end: literal.end - 1, text: value });\n }\n }\n for (const replacement of replacements.reverse())\n text = text.slice(0, replacement.start) + replacement.text + text.slice(replacement.end);\n return text;\n }\n\n organizeImports(filename: string, mode = ts.OrganizeImportsMode.All) {\n return this.mapChanges(\n this.project.service.organizeImports(\n { type: 'file', fileName: virtualFilename(filename), mode },\n {},\n {},\n ),\n );\n }\n\n /** Read-only navigation must also exclude generated helpers and duplicate JSX tags. */\n referenceGroups(filename: string, position: number): ts.ReferencedSymbol[] | undefined {\n const groups = this.project.service.findReferences(\n virtualFilename(filename),\n this.project.toGeneratedOffset(filename, position),\n );\n const mapped = <T extends ts.DocumentSpan>(entry: T): T | undefined => {\n const fileName = sourceFilename(entry.fileName);\n const textSpan = this.mapSpan(fileName, entry.textSpan);\n if (!textSpan) return undefined;\n const contextSpan = entry.contextSpan && this.mapSpan(fileName, entry.contextSpan);\n return { ...entry, fileName, textSpan, contextSpan };\n };\n return groups?.flatMap((group) => {\n const definition = mapped(group.definition);\n if (!definition) return [];\n const seen = new Set<string>();\n const references = group.references.flatMap((reference) => {\n const entry = mapped(reference);\n if (!entry) return [];\n // Some TS versions omit isDefinition from findReferences results.\n // Preserve supplied flags; otherwise compare the source-backed span\n // with this symbol group's definition for includeDeclaration requests.\n entry.isDefinition ??=\n entry.fileName === definition.fileName &&\n entry.textSpan.start === definition.textSpan.start &&\n entry.textSpan.length === definition.textSpan.length;\n const key = `${entry.fileName}:${entry.textSpan.start}:${entry.textSpan.length}`;\n if (seen.has(key)) return [];\n seen.add(key);\n return [entry];\n });\n return [{ definition, references }];\n });\n }\n\n references(filename: string, position: number) {\n return this.referenceGroups(filename, position)?.flatMap((group) => group.references);\n }\n\n private descriptorSymbols(program: ts.Program) {\n const cached = this.descriptorCache.get(program);\n if (cached) return cached;\n const symbols = new Set<ts.Symbol>();\n const checker = program.getTypeChecker();\n for (const file of program.getSourceFiles()) {\n const original = sourceFilename(file.fileName);\n if (!isTwillFile(original)) continue;\n let patterns: TransformResult['enumPatterns'] | undefined;\n try {\n patterns = this.project.transformed(original)?.enumPatterns;\n } catch {\n // One malformed document must not disable safe edits in other files.\n // Strict diagnostics and mapChanges still reject its unmappable edits.\n continue;\n }\n if (!patterns?.length) continue;\n const offsets = new Set(\n patterns.map((pattern) =>\n this.project.toGeneratedOffset(original, pattern.reference.property.start),\n ),\n );\n // Index each source once, rather than traversing it for every arm.\n // Program identity invalidates the cached symbols on any source edit.\n const visit = (node: ts.Node) => {\n if (ts.isIdentifier(node) && offsets.has(node.getStart())) {\n const symbol = checker.getSymbolAtLocation(node);\n if (symbol) for (const root of checker.getRootSymbols(symbol)) symbols.add(root);\n }\n ts.forEachChild(node, visit);\n };\n visit(file);\n }\n this.descriptorCache.set(program, symbols);\n return symbols;\n }\n\n renameInfo(filename: string, position: number): ts.RenameInfo {\n const offset = this.project.toGeneratedOffset(filename, position);\n const definitions = this.project.service.getDefinitionAtPosition(\n virtualFilename(filename),\n offset,\n );\n const program = this.project.service.getProgram()!;\n const descriptors = this.descriptorSymbols(program);\n for (const definition of definitions ?? []) {\n const file = sourceFilename(definition.fileName);\n const definitionFile = this.sourceFile(file);\n let descriptor = false;\n const visitDefinition = (node: ts.Node) => {\n if (definition.textSpan.start < node.getStart() || definition.textSpan.start >= node.end)\n return;\n if (ts.isIdentifier(node) || ts.isStringLiteral(node)) {\n const symbol = program.getTypeChecker().getSymbolAtLocation(node);\n descriptor =\n !!symbol &&\n program\n .getTypeChecker()\n .getRootSymbols(symbol)\n .some((root) => descriptors.has(root));\n } else ts.forEachChild(node, visitDefinition);\n };\n if (descriptors.size && definitionFile) visitDefinition(definitionFile);\n if (descriptor)\n return {\n canRename: false,\n localizedErrorMessage:\n 'Renaming an enum-pattern case descriptor requires linked discriminator edits and is not supported yet.',\n };\n const declarations = this.project.transformed(file)?.associatedEnums;\n if (!declarations?.length) continue;\n const sourceFile = this.sourceFile(file);\n let generatedEnum = false;\n const visit = (node: ts.Node) => {\n if (definition.textSpan.start < node.getStart() || definition.textSpan.start >= node.end)\n return;\n if (\n (ts.isTypeAliasDeclaration(node) || ts.isVariableDeclaration(node)) &&\n ts.isIdentifier(node.name)\n ) {\n const start = this.project.toOriginalOffset(file, node.name.getStart());\n if (declarations.some((declaration) => declaration.id.start === start)) {\n generatedEnum = true;\n return;\n }\n }\n ts.forEachChild(node, visit);\n };\n if (sourceFile) visit(sourceFile);\n if (generatedEnum)\n return {\n canRename: false,\n localizedErrorMessage:\n 'Renaming associated-value enum declarations, cases, payload fields and type parameters is not supported yet.',\n };\n }\n const info = this.project.service.getRenameInfo(virtualFilename(filename), offset, {\n allowRenameOfImportPath: false,\n });\n if (!info.canRename) return info;\n const span = this.mapSpan(filename, info.triggerSpan);\n return span\n ? { ...info, triggerSpan: span }\n : {\n canRename: false,\n localizedErrorMessage: 'This generated symbol cannot be renamed in Twill source.',\n };\n }\n\n renameLocations(\n filename: string,\n position: number,\n preferences: ts.UserPreferences | boolean = true,\n ) {\n const info = this.renameInfo(filename, position);\n if (!info.canRename) return undefined;\n const locations = this.project.service.findRenameLocations(\n virtualFilename(filename),\n this.project.toGeneratedOffset(filename, position),\n false,\n false,\n typeof preferences === 'boolean'\n ? { providePrefixAndSuffixTextForRename: preferences }\n : preferences,\n );\n if (!locations) return undefined;\n const result: ts.RenameLocation[] = [];\n for (const location of locations) {\n const file = sourceFilename(location.fileName);\n let span = this.mapSpan(file, location.textSpan);\n let prefixText = location.prefixText;\n let suffixText = location.suffixText;\n if (isTwillFile(file)) {\n const attribute = this.attributes(file).find(\n (item) =>\n item.name.getStart() === location.textSpan.start &&\n item.initializer &&\n ts.isJsxExpression(item.initializer) &&\n item.initializer.expression,\n );\n if (attribute && attribute.initializer && ts.isJsxExpression(attribute.initializer)) {\n const original = this.project.toOriginalOffset(\n file,\n attribute.initializer.expression!.getStart(),\n );\n const property = this.project\n .transformed(file)\n ?.componentProps.flatMap((object) => object.properties)\n .find(\n (item) =>\n item.name === attribute.name.getText() &&\n (item.shorthand\n ? item.start === original\n : item.start === this.project.toOriginalOffset(file, attribute.name.getStart())),\n );\n if (property) {\n span = { start: property.start, length: property.end - property.start };\n if (property.shorthand) suffixText = `: ${property.name}`;\n else {\n const quote = this.project.text(file)?.[property.start];\n if (quote === '\"' || quote === \"'\") {\n prefixText = quote;\n suffixText = quote;\n }\n }\n }\n } else if (span) {\n const property = this.project\n .transformed(file)\n ?.componentProps.flatMap((object) => object.properties)\n .find((item) => item.shorthand && item.start === span!.start);\n if (property) prefixText = `${property.name}: `;\n }\n }\n if (!span) {\n const generated = this.project.transformed(file)?.code;\n const start = this.project.toOriginalOffset(file, location.textSpan.start);\n if (\n generated &&\n this.project.text(file)?.slice(start, start + location.textSpan.length) !==\n generated.slice(\n location.textSpan.start,\n location.textSpan.start + location.textSpan.length,\n )\n )\n continue; // A compiler-inserted guard/defer reference is regenerated.\n // Generated closing JSX tags duplicate a source component reference;\n // they have no independent source occurrence to edit.\n const sf = this.sourceFile(file);\n let closing = false;\n const visit = (node: ts.Node) => {\n if (\n ts.isJsxClosingElement(node) &&\n location.textSpan.start >= node.tagName.getStart() &&\n location.textSpan.start < node.tagName.end\n )\n closing = true;\n else if (\n location.textSpan.start >= node.getFullStart() &&\n location.textSpan.start < node.end\n )\n ts.forEachChild(node, visit);\n };\n if (sf) visit(sf);\n if (closing) continue;\n return undefined;\n }\n result.push({\n ...location,\n fileName: file,\n textSpan: span,\n prefixText,\n suffixText,\n contextSpan: location.contextSpan ? this.mapSpan(file, location.contextSpan) : undefined,\n });\n }\n return result.filter(\n (item, index) =>\n result.findIndex(\n (other) =>\n item.fileName === other.fileName &&\n item.textSpan.start === other.textSpan.start &&\n item.textSpan.length === other.textSpan.length,\n ) === index,\n );\n }\n\n rename(\n filename: string,\n position: number,\n name: string,\n preferences: ts.UserPreferences | boolean = true,\n ): SourceEdit[] | undefined {\n const scanner = ts.createScanner(\n ts.ScriptTarget.Latest,\n false,\n ts.LanguageVariant.Standard,\n name,\n );\n if (\n scanner.scan() !== ts.SyntaxKind.Identifier ||\n scanner.scan() !== ts.SyntaxKind.EndOfFileToken\n )\n return undefined;\n return this.renameLocations(filename, position, preferences)?.map((location) => ({\n filename: location.fileName,\n span: location.textSpan,\n newText: (location.prefixText ?? '') + name + (location.suffixText ?? ''),\n }));\n }\n\n fixes(filename: string, start: number, end: number, codes: readonly number[]) {\n return this.project.service\n .getCodeFixesAtPosition(\n virtualFilename(filename),\n this.project.toGeneratedOffset(filename, start),\n this.project.toGeneratedOffset(filename, end),\n codes,\n {},\n {},\n )\n .flatMap((fix) => {\n const edits = this.mapChanges(fix.changes);\n return edits?.length && !fix.commands?.length\n ? [{ description: fix.description, edits }]\n : [];\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"editor.js","names":[],"sources":["../src/editor.ts"],"sourcesContent":["import ts from 'typescript';\nimport { TwillProject, sourceFilename, virtualFilename } from './project.js';\nimport { isTwillFile, type TransformResult } from './compiler.js';\n\nexport interface SourceEdit {\n filename: string;\n span: ts.TextSpan;\n newText: string;\n}\n\nexport interface CompletionRequest {\n offset: number;\n info: ts.CompletionInfo | undefined;\n props?: { start: number; end: number };\n}\n\n/** Shared semantic requests and conservative source edits for both editor hosts. */\nexport class TwillEditor {\n private attributeCache = new WeakMap<ts.SourceFile, ts.JsxAttribute[]>();\n private descriptorCache = new WeakMap<ts.Program, Set<ts.Symbol>>();\n private internalBindingCache = new WeakMap<ts.SourceFile, Set<string>>();\n constructor(readonly project: TwillProject) {}\n\n private sourceFile(filename: string) {\n return this.project.service.getProgram()?.getSourceFile(virtualFilename(filename));\n }\n\n private attributes(filename: string) {\n const file = this.sourceFile(filename);\n if (!file) return [];\n const cached = this.attributeCache.get(file);\n if (cached) return cached;\n const result: ts.JsxAttribute[] = [];\n const visit = (node: ts.Node) => {\n if (ts.isJsxAttribute(node)) result.push(node);\n ts.forEachChild(node, visit);\n };\n visit(file);\n this.attributeCache.set(file, result);\n return result;\n }\n\n completionLocation(filename: string, position: number) {\n let offset = this.project.toGeneratedOffset(filename, position);\n // A repaired member name and generated arm punctuation can share the same\n // original boundary. Anchor requests at the source-backed dot instead.\n const prefix = this.project.text(filename)?.slice(0, position);\n const member = prefix?.match(/\\.([\\p{ID_Continue}$\\u200c\\u200d]*)$/u);\n const missingMember = prefix?.match(/\\.\\s*$/);\n if (member) offset = this.project.toGeneratedOffset(filename, member.index!) + member[0].length;\n else if (missingMember)\n offset = this.project.toGeneratedOffset(filename, missingMember.index!) + 1;\n let props: CompletionRequest['props'];\n const metadata = this.project.transformed(filename)?.componentProps;\n const property = metadata\n ?.flatMap((object) => object.properties)\n .find((item) => item.shorthand && position >= item.start && position <= item.end);\n if (property) {\n const attribute = this.attributes(filename).find(\n (item) =>\n item.name.getText() === property.name &&\n item.initializer &&\n ts.isJsxExpression(item.initializer) &&\n item.initializer.expression &&\n this.project.toOriginalOffset(filename, item.initializer.expression.getStart()) ===\n property.start,\n );\n if (attribute) {\n offset = attribute.name.getStart() + position - property.start;\n props = { start: property.start, end: property.end };\n }\n } else if (\n metadata?.some((object) => position > object.start && position < object.end) &&\n !this.attributes(filename).some(\n (attribute) => offset >= attribute.name.end && offset <= attribute.end,\n )\n ) {\n // Empty objects and gaps between properties already map to JSX attribute\n // positions. Only classify requests that TS identifies as member lists.\n props = { start: position, end: position };\n }\n return { offset, props };\n }\n\n completions(filename: string, position: number, preferences: ts.UserPreferences = {}) {\n let { offset, props } = this.completionLocation(filename, position);\n let info = this.project.service.getCompletionsAtPosition(virtualFilename(filename), offset, {\n includeCompletionsForModuleExports: true,\n includeCompletionsWithInsertText: true,\n ...preferences,\n });\n if (\n info &&\n !info.isMemberCompletion &&\n isTwillFile(sourceFilename(filename)) &&\n this.project.transformed(filename)?.changed\n ) {\n const file = this.sourceFile(filename);\n if (file) {\n let internal = this.internalBindingCache.get(file);\n if (!internal) {\n internal = new Set<string>();\n const visit = (node: ts.Node) => {\n if (ts.isIdentifier(node) && node.text.startsWith('__twill')) {\n const parent = node.parent;\n if (\n (ts.isVariableDeclaration(parent) ||\n ts.isBindingElement(parent) ||\n ts.isParameter(parent) ||\n ts.isTypeAliasDeclaration(parent) ||\n ts.isFunctionDeclaration(parent)) &&\n parent.name === node &&\n !this.mapSpan(filename, { start: node.getStart(), length: node.getWidth() })\n )\n internal!.add(node.text);\n }\n ts.forEachChild(node, visit);\n };\n visit(file);\n this.internalBindingCache.set(file, internal);\n }\n const hidden = internal;\n if (hidden.size)\n info = { ...info, entries: info.entries.filter((entry) => !hidden.has(entry.name)) };\n }\n }\n if (props && !info?.isMemberCompletion) props = undefined;\n return { offset, info, props } satisfies CompletionRequest;\n }\n\n /** Never stretch a generated edit across lowered punctuation or helper code. */\n mapSpan(filename: string, span: ts.TextSpan): ts.TextSpan | undefined {\n filename = sourceFilename(filename);\n const source = this.project.text(filename);\n if (source === undefined) return undefined;\n if (!isTwillFile(filename))\n return span.start >= 0 && span.start + span.length <= source.length ? span : undefined;\n const transformed = this.project.transformed(filename);\n const generated = transformed?.code;\n if (generated === undefined) return undefined;\n const start = this.project.toOriginalOffset(filename, span.start);\n if (\n start < 0 ||\n start + span.length > source.length ||\n (this.project.toGeneratedOffset(filename, start) !== span.start &&\n !transformed!.enumCopies.some(\n (copy) =>\n (span.start >= copy.generatedStart &&\n span.start + span.length <= copy.generatedStart + copy.length &&\n start === copy.sourceStart + span.start - copy.generatedStart) ||\n (start >= copy.sourceStart &&\n start + span.length <= copy.sourceStart + copy.length &&\n this.project.toOriginalOffset(filename, span.start + span.length - 1) ===\n start + span.length - 1),\n )) ||\n source.slice(start, start + span.length) !==\n generated.slice(span.start, span.start + span.length)\n )\n return undefined;\n return { start, length: span.length };\n }\n\n mapChanges(changes: readonly ts.FileTextChanges[]): SourceEdit[] | undefined {\n const edits: SourceEdit[] = [];\n for (const file of changes) {\n if (file.isNewFile) return undefined;\n const filename = sourceFilename(file.fileName);\n for (const change of file.textChanges) {\n let span = this.mapSpan(filename, change.span);\n // Inferred JSX runtime pragmas can precede the first source token.\n // A fresh import can safely be inserted before the original module.\n if (!span && change.span.length === 0 && /^\\s*import\\b/.test(change.newText)) {\n const firstStatement = this.sourceFile(filename)?.statements[0];\n if (change.span.start <= (firstStatement?.getStart() ?? 0))\n span = { start: 0, length: 0 };\n }\n if (!span) return undefined;\n edits.push({ filename, span, newText: this.importText(change.newText) });\n }\n }\n return edits;\n }\n\n private importText(text: string) {\n // Edit only module literals, never user strings in an unrelated code fix.\n const file = ts.createSourceFile('edits.ts', text, ts.ScriptTarget.Latest, true);\n const replacements: { start: number; end: number; text: string }[] = [];\n for (const statement of file.statements) {\n if (\n (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) &&\n statement.moduleSpecifier &&\n ts.isStringLiteral(statement.moduleSpecifier)\n ) {\n const literal = statement.moduleSpecifier;\n const value = sourceFilename(literal.text);\n if (value !== literal.text)\n replacements.push({ start: literal.getStart() + 1, end: literal.end - 1, text: value });\n }\n }\n for (const replacement of replacements.reverse())\n text = text.slice(0, replacement.start) + replacement.text + text.slice(replacement.end);\n return text;\n }\n\n organizeImports(filename: string, mode = ts.OrganizeImportsMode.All) {\n return this.mapChanges(\n this.project.service.organizeImports(\n { type: 'file', fileName: virtualFilename(filename), mode },\n {},\n {},\n ),\n );\n }\n\n /** Read-only navigation must also exclude generated helpers and duplicate JSX tags. */\n referenceGroups(filename: string, position: number): ts.ReferencedSymbol[] | undefined {\n const groups = this.project.service.findReferences(\n virtualFilename(filename),\n this.project.toGeneratedOffset(filename, position),\n );\n const mapped = <T extends ts.DocumentSpan>(entry: T): T | undefined => {\n const fileName = sourceFilename(entry.fileName);\n const textSpan = this.mapSpan(fileName, entry.textSpan);\n if (!textSpan) return undefined;\n const contextSpan = entry.contextSpan && this.mapSpan(fileName, entry.contextSpan);\n return { ...entry, fileName, textSpan, contextSpan };\n };\n return groups?.flatMap((group) => {\n const definition = mapped(group.definition);\n if (!definition) return [];\n const seen = new Set<string>();\n const references = group.references.flatMap((reference) => {\n const entry = mapped(reference);\n if (!entry) return [];\n // Some TS versions omit isDefinition from findReferences results.\n // Preserve supplied flags; otherwise compare the source-backed span\n // with this symbol group's definition for includeDeclaration requests.\n entry.isDefinition ??=\n entry.fileName === definition.fileName &&\n entry.textSpan.start === definition.textSpan.start &&\n entry.textSpan.length === definition.textSpan.length;\n const key = `${entry.fileName}:${entry.textSpan.start}:${entry.textSpan.length}`;\n if (seen.has(key)) return [];\n seen.add(key);\n return [entry];\n });\n return [{ definition, references }];\n });\n }\n\n references(filename: string, position: number) {\n return this.referenceGroups(filename, position)?.flatMap((group) => group.references);\n }\n\n private descriptorSymbols(program: ts.Program) {\n const cached = this.descriptorCache.get(program);\n if (cached) return cached;\n const symbols = new Set<ts.Symbol>();\n const checker = program.getTypeChecker();\n for (const file of program.getSourceFiles()) {\n const original = sourceFilename(file.fileName);\n if (!isTwillFile(original)) continue;\n let patterns: TransformResult['enumPatterns'] | undefined;\n try {\n patterns = this.project.transformed(original)?.enumPatterns;\n } catch {\n // One malformed document must not disable safe edits in other files.\n // Strict diagnostics and mapChanges still reject its unmappable edits.\n continue;\n }\n if (!patterns?.length) continue;\n const offsets = new Set(\n patterns.map((pattern) =>\n this.project.toGeneratedOffset(original, pattern.reference.property.start),\n ),\n );\n // Index each source once, rather than traversing it for every arm.\n // Program identity invalidates the cached symbols on any source edit.\n const visit = (node: ts.Node) => {\n if (ts.isIdentifier(node) && offsets.has(node.getStart())) {\n const symbol = checker.getSymbolAtLocation(node);\n if (symbol) for (const root of checker.getRootSymbols(symbol)) symbols.add(root);\n }\n ts.forEachChild(node, visit);\n };\n visit(file);\n }\n this.descriptorCache.set(program, symbols);\n return symbols;\n }\n\n renameInfo(filename: string, position: number): ts.RenameInfo {\n const offset = this.project.toGeneratedOffset(filename, position);\n const definitions = this.project.service.getDefinitionAtPosition(\n virtualFilename(filename),\n offset,\n );\n const program = this.project.service.getProgram()!;\n const descriptors = this.descriptorSymbols(program);\n for (const definition of definitions ?? []) {\n const file = sourceFilename(definition.fileName);\n const definitionFile = this.sourceFile(file);\n let descriptor = false;\n const visitDefinition = (node: ts.Node) => {\n if (definition.textSpan.start < node.getStart() || definition.textSpan.start >= node.end)\n return;\n if (ts.isIdentifier(node) || ts.isStringLiteral(node)) {\n const symbol = program.getTypeChecker().getSymbolAtLocation(node);\n descriptor =\n !!symbol &&\n program\n .getTypeChecker()\n .getRootSymbols(symbol)\n .some((root) => descriptors.has(root));\n } else ts.forEachChild(node, visitDefinition);\n };\n if (descriptors.size && definitionFile) visitDefinition(definitionFile);\n if (descriptor)\n return {\n canRename: false,\n localizedErrorMessage:\n 'Renaming an enum-pattern case descriptor requires linked discriminator edits and is not supported yet.',\n };\n const declarations = this.project.transformed(file)?.associatedEnums;\n if (!declarations?.length) continue;\n const sourceFile = this.sourceFile(file);\n let generatedEnum = false;\n const visit = (node: ts.Node) => {\n if (definition.textSpan.start < node.getStart() || definition.textSpan.start >= node.end)\n return;\n if (\n (ts.isTypeAliasDeclaration(node) || ts.isVariableDeclaration(node)) &&\n ts.isIdentifier(node.name)\n ) {\n const start = this.project.toOriginalOffset(file, node.name.getStart());\n if (declarations.some((declaration) => declaration.id.start === start)) {\n generatedEnum = true;\n return;\n }\n }\n ts.forEachChild(node, visit);\n };\n if (sourceFile) visit(sourceFile);\n if (generatedEnum)\n return {\n canRename: false,\n localizedErrorMessage:\n 'Renaming associated-value enum declarations, cases, payload fields and type parameters is not supported yet.',\n };\n }\n const info = this.project.service.getRenameInfo(virtualFilename(filename), offset, {\n allowRenameOfImportPath: false,\n });\n if (!info.canRename) return info;\n const span = this.mapSpan(filename, info.triggerSpan);\n return span\n ? { ...info, triggerSpan: span }\n : {\n canRename: false,\n localizedErrorMessage: 'This generated symbol cannot be renamed in Twill source.',\n };\n }\n\n renameLocations(\n filename: string,\n position: number,\n preferences: ts.UserPreferences | boolean = true,\n ) {\n const info = this.renameInfo(filename, position);\n if (!info.canRename) return undefined;\n const locations = this.project.service.findRenameLocations(\n virtualFilename(filename),\n this.project.toGeneratedOffset(filename, position),\n false,\n false,\n typeof preferences === 'boolean'\n ? { providePrefixAndSuffixTextForRename: preferences }\n : preferences,\n );\n if (!locations) return undefined;\n const result: ts.RenameLocation[] = [];\n for (const location of locations) {\n const file = sourceFilename(location.fileName);\n let span = this.mapSpan(file, location.textSpan);\n let prefixText = location.prefixText;\n let suffixText = location.suffixText;\n if (isTwillFile(file)) {\n const attribute = this.attributes(file).find(\n (item) =>\n item.name.getStart() === location.textSpan.start &&\n item.initializer &&\n ts.isJsxExpression(item.initializer) &&\n item.initializer.expression,\n );\n if (attribute && attribute.initializer && ts.isJsxExpression(attribute.initializer)) {\n const original = this.project.toOriginalOffset(\n file,\n attribute.initializer.expression!.getStart(),\n );\n const property = this.project\n .transformed(file)\n ?.componentProps.flatMap((object) => object.properties)\n .find(\n (item) =>\n item.name === attribute.name.getText() &&\n (item.shorthand\n ? item.start === original\n : item.start === this.project.toOriginalOffset(file, attribute.name.getStart())),\n );\n if (property) {\n span = { start: property.start, length: property.end - property.start };\n if (property.shorthand) suffixText = `: ${property.name}`;\n else {\n const quote = this.project.text(file)?.[property.start];\n if (quote === '\"' || quote === \"'\") {\n prefixText = quote;\n suffixText = quote;\n }\n }\n }\n } else if (span) {\n const property = this.project\n .transformed(file)\n ?.componentProps.flatMap((object) => object.properties)\n .find((item) => item.shorthand && item.start === span!.start);\n if (property) prefixText = `${property.name}: `;\n }\n }\n if (!span) {\n const generated = this.project.transformed(file)?.code;\n const start = this.project.toOriginalOffset(file, location.textSpan.start);\n if (\n generated &&\n this.project.text(file)?.slice(start, start + location.textSpan.length) !==\n generated.slice(\n location.textSpan.start,\n location.textSpan.start + location.textSpan.length,\n )\n )\n continue; // A compiler-inserted guard/defer reference is regenerated.\n // Generated closing JSX tags duplicate a source component reference;\n // they have no independent source occurrence to edit.\n const sf = this.sourceFile(file);\n let closing = false;\n const visit = (node: ts.Node) => {\n if (\n ts.isJsxClosingElement(node) &&\n location.textSpan.start >= node.tagName.getStart() &&\n location.textSpan.start < node.tagName.end\n )\n closing = true;\n else if (\n location.textSpan.start >= node.getFullStart() &&\n location.textSpan.start < node.end\n )\n ts.forEachChild(node, visit);\n };\n if (sf) visit(sf);\n if (closing) continue;\n return undefined;\n }\n result.push({\n ...location,\n fileName: file,\n textSpan: span,\n prefixText,\n suffixText,\n contextSpan: location.contextSpan ? this.mapSpan(file, location.contextSpan) : undefined,\n });\n }\n return result.filter(\n (item, index) =>\n result.findIndex(\n (other) =>\n item.fileName === other.fileName &&\n item.textSpan.start === other.textSpan.start &&\n item.textSpan.length === other.textSpan.length,\n ) === index,\n );\n }\n\n rename(\n filename: string,\n position: number,\n name: string,\n preferences: ts.UserPreferences | boolean = true,\n ): SourceEdit[] | undefined {\n const scanner = ts.createScanner(\n ts.ScriptTarget.Latest,\n false,\n ts.LanguageVariant.Standard,\n name,\n );\n if (\n scanner.scan() !== ts.SyntaxKind.Identifier ||\n scanner.scan() !== ts.SyntaxKind.EndOfFileToken\n )\n return undefined;\n return this.renameLocations(filename, position, preferences)?.map((location) => ({\n filename: location.fileName,\n span: location.textSpan,\n newText: (location.prefixText ?? '') + name + (location.suffixText ?? ''),\n }));\n }\n\n fixes(filename: string, start: number, end: number, codes: readonly number[]) {\n return this.project.service\n .getCodeFixesAtPosition(\n virtualFilename(filename),\n this.project.toGeneratedOffset(filename, start),\n this.project.toGeneratedOffset(filename, end),\n codes,\n {},\n {},\n )\n .flatMap((fix) => {\n const edits = this.mapChanges(fix.changes);\n return edits?.length && !fix.commands?.length\n ? [{ description: fix.description, edits }]\n : [];\n });\n }\n}\n"],"mappings":";;;;;AAiBA,IAAa,cAAb,MAAyB;CAIF;CAHrB,iCAAyB,IAAI,QAA0C;CACvE,kCAA0B,IAAI,QAAoC;CAClE,uCAA+B,IAAI,QAAoC;CACvE,YAAY,SAAgC;EAAvB,KAAA,UAAA;CAAwB;CAE7C,WAAmB,UAAkB;EACnC,OAAO,KAAK,QAAQ,QAAQ,WAAW,CAAC,EAAE,cAAc,gBAAgB,QAAQ,CAAC;CACnF;CAEA,WAAmB,UAAkB;EACnC,MAAM,OAAO,KAAK,WAAW,QAAQ;EACrC,IAAI,CAAC,MAAM,OAAO,CAAC;EACnB,MAAM,SAAS,KAAK,eAAe,IAAI,IAAI;EAC3C,IAAI,QAAQ,OAAO;EACnB,MAAM,SAA4B,CAAC;EACnC,MAAM,SAAS,SAAkB;GAC/B,IAAI,GAAG,eAAe,IAAI,GAAG,OAAO,KAAK,IAAI;GAC7C,GAAG,aAAa,MAAM,KAAK;EAC7B;EACA,MAAM,IAAI;EACV,KAAK,eAAe,IAAI,MAAM,MAAM;EACpC,OAAO;CACT;CAEA,mBAAmB,UAAkB,UAAkB;EACrD,IAAI,SAAS,KAAK,QAAQ,kBAAkB,UAAU,QAAQ;EAG9D,MAAM,SAAS,KAAK,QAAQ,KAAK,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ;EAC7D,MAAM,SAAS,QAAQ,MAAM,uCAAuC;EACpE,MAAM,gBAAgB,QAAQ,MAAM,QAAQ;EAC5C,IAAI,QAAQ,SAAS,KAAK,QAAQ,kBAAkB,UAAU,OAAO,KAAM,IAAI,OAAO,EAAE,CAAC;OACpF,IAAI,eACP,SAAS,KAAK,QAAQ,kBAAkB,UAAU,cAAc,KAAM,IAAI;EAC5E,IAAI;EACJ,MAAM,WAAW,KAAK,QAAQ,YAAY,QAAQ,CAAC,EAAE;EACrD,MAAM,WAAW,UACb,SAAS,WAAW,OAAO,UAAU,CAAC,CACvC,MAAM,SAAS,KAAK,aAAa,YAAY,KAAK,SAAS,YAAY,KAAK,GAAG;EAClF,IAAI,UAAU;GACZ,MAAM,YAAY,KAAK,WAAW,QAAQ,CAAC,CAAC,MACzC,SACC,KAAK,KAAK,QAAQ,MAAM,SAAS,QACjC,KAAK,eACL,GAAG,gBAAgB,KAAK,WAAW,KACnC,KAAK,YAAY,cACjB,KAAK,QAAQ,iBAAiB,UAAU,KAAK,YAAY,WAAW,SAAS,CAAC,MAC5E,SAAS,KACf;GACA,IAAI,WAAW;IACb,SAAS,UAAU,KAAK,SAAS,IAAI,WAAW,SAAS;IACzD,QAAQ;KAAE,OAAO,SAAS;KAAO,KAAK,SAAS;IAAI;GACrD;EACF,OAAO,IACL,UAAU,MAAM,WAAW,WAAW,OAAO,SAAS,WAAW,OAAO,GAAG,KAC3E,CAAC,KAAK,WAAW,QAAQ,CAAC,CAAC,MACxB,cAAc,UAAU,UAAU,KAAK,OAAO,UAAU,UAAU,GACrE,GAIA,QAAQ;GAAE,OAAO;GAAU,KAAK;EAAS;EAE3C,OAAO;GAAE;GAAQ;EAAM;CACzB;CAEA,YAAY,UAAkB,UAAkB,cAAkC,CAAC,GAAG;EACpF,IAAI,EAAE,QAAQ,UAAU,KAAK,mBAAmB,UAAU,QAAQ;EAClE,IAAI,OAAO,KAAK,QAAQ,QAAQ,yBAAyB,gBAAgB,QAAQ,GAAG,QAAQ;GAC1F,oCAAoC;GACpC,kCAAkC;GAClC,GAAG;EACL,CAAC;EACD,IACE,QACA,CAAC,KAAK,sBACN,YAAY,eAAe,QAAQ,CAAC,KACpC,KAAK,QAAQ,YAAY,QAAQ,CAAC,EAAE,SACpC;GACA,MAAM,OAAO,KAAK,WAAW,QAAQ;GACrC,IAAI,MAAM;IACR,IAAI,WAAW,KAAK,qBAAqB,IAAI,IAAI;IACjD,IAAI,CAAC,UAAU;KACb,2BAAW,IAAI,IAAY;KAC3B,MAAM,SAAS,SAAkB;MAC/B,IAAI,GAAG,aAAa,IAAI,KAAK,KAAK,KAAK,WAAW,SAAS,GAAG;OAC5D,MAAM,SAAS,KAAK;OACpB,KACG,GAAG,sBAAsB,MAAM,KAC9B,GAAG,iBAAiB,MAAM,KAC1B,GAAG,YAAY,MAAM,KACrB,GAAG,uBAAuB,MAAM,KAChC,GAAG,sBAAsB,MAAM,MACjC,OAAO,SAAS,QAChB,CAAC,KAAK,QAAQ,UAAU;QAAE,OAAO,KAAK,SAAS;QAAG,QAAQ,KAAK,SAAS;OAAE,CAAC,GAE3E,SAAU,IAAI,KAAK,IAAI;MAC3B;MACA,GAAG,aAAa,MAAM,KAAK;KAC7B;KACA,MAAM,IAAI;KACV,KAAK,qBAAqB,IAAI,MAAM,QAAQ;IAC9C;IACA,MAAM,SAAS;IACf,IAAI,OAAO,MACT,OAAO;KAAE,GAAG;KAAM,SAAS,KAAK,QAAQ,QAAQ,UAAU,CAAC,OAAO,IAAI,MAAM,IAAI,CAAC;IAAE;GACvF;EACF;EACA,IAAI,SAAS,CAAC,MAAM,oBAAoB,QAAQ,KAAA;EAChD,OAAO;GAAE;GAAQ;GAAM;EAAM;CAC/B;;CAGA,QAAQ,UAAkB,MAA4C;EACpE,WAAW,eAAe,QAAQ;EAClC,MAAM,SAAS,KAAK,QAAQ,KAAK,QAAQ;EACzC,IAAI,WAAW,KAAA,GAAW,OAAO,KAAA;EACjC,IAAI,CAAC,YAAY,QAAQ,GACvB,OAAO,KAAK,SAAS,KAAK,KAAK,QAAQ,KAAK,UAAU,OAAO,SAAS,OAAO,KAAA;EAC/E,MAAM,cAAc,KAAK,QAAQ,YAAY,QAAQ;EACrD,MAAM,YAAY,aAAa;EAC/B,IAAI,cAAc,KAAA,GAAW,OAAO,KAAA;EACpC,MAAM,QAAQ,KAAK,QAAQ,iBAAiB,UAAU,KAAK,KAAK;EAChE,IACE,QAAQ,KACR,QAAQ,KAAK,SAAS,OAAO,UAC5B,KAAK,QAAQ,kBAAkB,UAAU,KAAK,MAAM,KAAK,SACxD,CAAC,YAAa,WAAW,MACtB,SACE,KAAK,SAAS,KAAK,kBAClB,KAAK,QAAQ,KAAK,UAAU,KAAK,iBAAiB,KAAK,UACvD,UAAU,KAAK,cAAc,KAAK,QAAQ,KAAK,kBAChD,SAAS,KAAK,eACb,QAAQ,KAAK,UAAU,KAAK,cAAc,KAAK,UAC/C,KAAK,QAAQ,iBAAiB,UAAU,KAAK,QAAQ,KAAK,SAAS,CAAC,MAClE,QAAQ,KAAK,SAAS,CAC9B,KACF,OAAO,MAAM,OAAO,QAAQ,KAAK,MAAM,MACrC,UAAU,MAAM,KAAK,OAAO,KAAK,QAAQ,KAAK,MAAM,GAEtD,OAAO,KAAA;EACT,OAAO;GAAE;GAAO,QAAQ,KAAK;EAAO;CACtC;CAEA,WAAW,SAAkE;EAC3E,MAAM,QAAsB,CAAC;EAC7B,KAAK,MAAM,QAAQ,SAAS;GAC1B,IAAI,KAAK,WAAW,OAAO,KAAA;GAC3B,MAAM,WAAW,eAAe,KAAK,QAAQ;GAC7C,KAAK,MAAM,UAAU,KAAK,aAAa;IACrC,IAAI,OAAO,KAAK,QAAQ,UAAU,OAAO,IAAI;IAG7C,IAAI,CAAC,QAAQ,OAAO,KAAK,WAAW,KAAK,eAAe,KAAK,OAAO,OAAO,GAAG;KAC5E,MAAM,iBAAiB,KAAK,WAAW,QAAQ,CAAC,EAAE,WAAW;KAC7D,IAAI,OAAO,KAAK,UAAU,gBAAgB,SAAS,KAAK,IACtD,OAAO;MAAE,OAAO;MAAG,QAAQ;KAAE;IACjC;IACA,IAAI,CAAC,MAAM,OAAO,KAAA;IAClB,MAAM,KAAK;KAAE;KAAU;KAAM,SAAS,KAAK,WAAW,OAAO,OAAO;IAAE,CAAC;GACzE;EACF;EACA,OAAO;CACT;CAEA,WAAmB,MAAc;EAE/B,MAAM,OAAO,GAAG,iBAAiB,YAAY,MAAM,GAAG,aAAa,QAAQ,IAAI;EAC/E,MAAM,eAA+D,CAAC;EACtE,KAAK,MAAM,aAAa,KAAK,YAC3B,KACG,GAAG,oBAAoB,SAAS,KAAK,GAAG,oBAAoB,SAAS,MACtE,UAAU,mBACV,GAAG,gBAAgB,UAAU,eAAe,GAC5C;GACA,MAAM,UAAU,UAAU;GAC1B,MAAM,QAAQ,eAAe,QAAQ,IAAI;GACzC,IAAI,UAAU,QAAQ,MACpB,aAAa,KAAK;IAAE,OAAO,QAAQ,SAAS,IAAI;IAAG,KAAK,QAAQ,MAAM;IAAG,MAAM;GAAM,CAAC;EAC1F;EAEF,KAAK,MAAM,eAAe,aAAa,QAAQ,GAC7C,OAAO,KAAK,MAAM,GAAG,YAAY,KAAK,IAAI,YAAY,OAAO,KAAK,MAAM,YAAY,GAAG;EACzF,OAAO;CACT;CAEA,gBAAgB,UAAkB,OAAO,GAAG,oBAAoB,KAAK;EACnE,OAAO,KAAK,WACV,KAAK,QAAQ,QAAQ,gBACnB;GAAE,MAAM;GAAQ,UAAU,gBAAgB,QAAQ;GAAG;EAAK,GAC1D,CAAC,GACD,CAAC,CACH,CACF;CACF;;CAGA,gBAAgB,UAAkB,UAAqD;EACrF,MAAM,SAAS,KAAK,QAAQ,QAAQ,eAClC,gBAAgB,QAAQ,GACxB,KAAK,QAAQ,kBAAkB,UAAU,QAAQ,CACnD;EACA,MAAM,UAAqC,UAA4B;GACrE,MAAM,WAAW,eAAe,MAAM,QAAQ;GAC9C,MAAM,WAAW,KAAK,QAAQ,UAAU,MAAM,QAAQ;GACtD,IAAI,CAAC,UAAU,OAAO,KAAA;GACtB,MAAM,cAAc,MAAM,eAAe,KAAK,QAAQ,UAAU,MAAM,WAAW;GACjF,OAAO;IAAE,GAAG;IAAO;IAAU;IAAU;GAAY;EACrD;EACA,OAAO,QAAQ,SAAS,UAAU;GAChC,MAAM,aAAa,OAAO,MAAM,UAAU;GAC1C,IAAI,CAAC,YAAY,OAAO,CAAC;GACzB,MAAM,uBAAO,IAAI,IAAY;GAgB7B,OAAO,CAAC;IAAE;IAAY,YAfH,MAAM,WAAW,SAAS,cAAc;KACzD,MAAM,QAAQ,OAAO,SAAS;KAC9B,IAAI,CAAC,OAAO,OAAO,CAAC;KAIpB,MAAM,iBACJ,MAAM,aAAa,WAAW,YAC9B,MAAM,SAAS,UAAU,WAAW,SAAS,SAC7C,MAAM,SAAS,WAAW,WAAW,SAAS;KAChD,MAAM,MAAM,GAAG,MAAM,SAAS,GAAG,MAAM,SAAS,MAAM,GAAG,MAAM,SAAS;KACxE,IAAI,KAAK,IAAI,GAAG,GAAG,OAAO,CAAC;KAC3B,KAAK,IAAI,GAAG;KACZ,OAAO,CAAC,KAAK;IACf,CACsB;GAAW,CAAC;EACpC,CAAC;CACH;CAEA,WAAW,UAAkB,UAAkB;EAC7C,OAAO,KAAK,gBAAgB,UAAU,QAAQ,CAAC,EAAE,SAAS,UAAU,MAAM,UAAU;CACtF;CAEA,kBAA0B,SAAqB;EAC7C,MAAM,SAAS,KAAK,gBAAgB,IAAI,OAAO;EAC/C,IAAI,QAAQ,OAAO;EACnB,MAAM,0BAAU,IAAI,IAAe;EACnC,MAAM,UAAU,QAAQ,eAAe;EACvC,KAAK,MAAM,QAAQ,QAAQ,eAAe,GAAG;GAC3C,MAAM,WAAW,eAAe,KAAK,QAAQ;GAC7C,IAAI,CAAC,YAAY,QAAQ,GAAG;GAC5B,IAAI;GACJ,IAAI;IACF,WAAW,KAAK,QAAQ,YAAY,QAAQ,CAAC,EAAE;GACjD,QAAQ;IAGN;GACF;GACA,IAAI,CAAC,UAAU,QAAQ;GACvB,MAAM,UAAU,IAAI,IAClB,SAAS,KAAK,YACZ,KAAK,QAAQ,kBAAkB,UAAU,QAAQ,UAAU,SAAS,KAAK,CAC3E,CACF;GAGA,MAAM,SAAS,SAAkB;IAC/B,IAAI,GAAG,aAAa,IAAI,KAAK,QAAQ,IAAI,KAAK,SAAS,CAAC,GAAG;KACzD,MAAM,SAAS,QAAQ,oBAAoB,IAAI;KAC/C,IAAI,QAAQ,KAAK,MAAM,QAAQ,QAAQ,eAAe,MAAM,GAAG,QAAQ,IAAI,IAAI;IACjF;IACA,GAAG,aAAa,MAAM,KAAK;GAC7B;GACA,MAAM,IAAI;EACZ;EACA,KAAK,gBAAgB,IAAI,SAAS,OAAO;EACzC,OAAO;CACT;CAEA,WAAW,UAAkB,UAAiC;EAC5D,MAAM,SAAS,KAAK,QAAQ,kBAAkB,UAAU,QAAQ;EAChE,MAAM,cAAc,KAAK,QAAQ,QAAQ,wBACvC,gBAAgB,QAAQ,GACxB,MACF;EACA,MAAM,UAAU,KAAK,QAAQ,QAAQ,WAAW;EAChD,MAAM,cAAc,KAAK,kBAAkB,OAAO;EAClD,KAAK,MAAM,cAAc,eAAe,CAAC,GAAG;GAC1C,MAAM,OAAO,eAAe,WAAW,QAAQ;GAC/C,MAAM,iBAAiB,KAAK,WAAW,IAAI;GAC3C,IAAI,aAAa;GACjB,MAAM,mBAAmB,SAAkB;IACzC,IAAI,WAAW,SAAS,QAAQ,KAAK,SAAS,KAAK,WAAW,SAAS,SAAS,KAAK,KACnF;IACF,IAAI,GAAG,aAAa,IAAI,KAAK,GAAG,gBAAgB,IAAI,GAAG;KACrD,MAAM,SAAS,QAAQ,eAAe,CAAC,CAAC,oBAAoB,IAAI;KAChE,aACE,CAAC,CAAC,UACF,QACG,eAAe,CAAC,CAChB,eAAe,MAAM,CAAC,CACtB,MAAM,SAAS,YAAY,IAAI,IAAI,CAAC;IAC3C,OAAO,GAAG,aAAa,MAAM,eAAe;GAC9C;GACA,IAAI,YAAY,QAAQ,gBAAgB,gBAAgB,cAAc;GACtE,IAAI,YACF,OAAO;IACL,WAAW;IACX,uBACE;GACJ;GACF,MAAM,eAAe,KAAK,QAAQ,YAAY,IAAI,CAAC,EAAE;GACrD,IAAI,CAAC,cAAc,QAAQ;GAC3B,MAAM,aAAa,KAAK,WAAW,IAAI;GACvC,IAAI,gBAAgB;GACpB,MAAM,SAAS,SAAkB;IAC/B,IAAI,WAAW,SAAS,QAAQ,KAAK,SAAS,KAAK,WAAW,SAAS,SAAS,KAAK,KACnF;IACF,KACG,GAAG,uBAAuB,IAAI,KAAK,GAAG,sBAAsB,IAAI,MACjE,GAAG,aAAa,KAAK,IAAI,GACzB;KACA,MAAM,QAAQ,KAAK,QAAQ,iBAAiB,MAAM,KAAK,KAAK,SAAS,CAAC;KACtE,IAAI,aAAa,MAAM,gBAAgB,YAAY,GAAG,UAAU,KAAK,GAAG;MACtE,gBAAgB;MAChB;KACF;IACF;IACA,GAAG,aAAa,MAAM,KAAK;GAC7B;GACA,IAAI,YAAY,MAAM,UAAU;GAChC,IAAI,eACF,OAAO;IACL,WAAW;IACX,uBACE;GACJ;EACJ;EACA,MAAM,OAAO,KAAK,QAAQ,QAAQ,cAAc,gBAAgB,QAAQ,GAAG,QAAQ,EACjF,yBAAyB,MAC3B,CAAC;EACD,IAAI,CAAC,KAAK,WAAW,OAAO;EAC5B,MAAM,OAAO,KAAK,QAAQ,UAAU,KAAK,WAAW;EACpD,OAAO,OACH;GAAE,GAAG;GAAM,aAAa;EAAK,IAC7B;GACE,WAAW;GACX,uBAAuB;EACzB;CACN;CAEA,gBACE,UACA,UACA,cAA4C,MAC5C;EAEA,IAAI,CADS,KAAK,WAAW,UAAU,QAClC,CAAA,CAAK,WAAW,OAAO,KAAA;EAC5B,MAAM,YAAY,KAAK,QAAQ,QAAQ,oBACrC,gBAAgB,QAAQ,GACxB,KAAK,QAAQ,kBAAkB,UAAU,QAAQ,GACjD,OACA,OACA,OAAO,gBAAgB,YACnB,EAAE,qCAAqC,YAAY,IACnD,WACN;EACA,IAAI,CAAC,WAAW,OAAO,KAAA;EACvB,MAAM,SAA8B,CAAC;EACrC,KAAK,MAAM,YAAY,WAAW;GAChC,MAAM,OAAO,eAAe,SAAS,QAAQ;GAC7C,IAAI,OAAO,KAAK,QAAQ,MAAM,SAAS,QAAQ;GAC/C,IAAI,aAAa,SAAS;GAC1B,IAAI,aAAa,SAAS;GAC1B,IAAI,YAAY,IAAI,GAAG;IACrB,MAAM,YAAY,KAAK,WAAW,IAAI,CAAC,CAAC,MACrC,SACC,KAAK,KAAK,SAAS,MAAM,SAAS,SAAS,SAC3C,KAAK,eACL,GAAG,gBAAgB,KAAK,WAAW,KACnC,KAAK,YAAY,UACrB;IACA,IAAI,aAAa,UAAU,eAAe,GAAG,gBAAgB,UAAU,WAAW,GAAG;KACnF,MAAM,WAAW,KAAK,QAAQ,iBAC5B,MACA,UAAU,YAAY,WAAY,SAAS,CAC7C;KACA,MAAM,WAAW,KAAK,QACnB,YAAY,IAAI,CAAC,EAChB,eAAe,SAAS,WAAW,OAAO,UAAU,CAAC,CACtD,MACE,SACC,KAAK,SAAS,UAAU,KAAK,QAAQ,MACpC,KAAK,YACF,KAAK,UAAU,WACf,KAAK,UAAU,KAAK,QAAQ,iBAAiB,MAAM,UAAU,KAAK,SAAS,CAAC,EACpF;KACF,IAAI,UAAU;MACZ,OAAO;OAAE,OAAO,SAAS;OAAO,QAAQ,SAAS,MAAM,SAAS;MAAM;MACtE,IAAI,SAAS,WAAW,aAAa,KAAK,SAAS;WAC9C;OACH,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,CAAC,GAAG,SAAS;OACjD,IAAI,UAAU,QAAO,UAAU,KAAK;QAClC,aAAa;QACb,aAAa;OACf;MACF;KACF;IACF,OAAO,IAAI,MAAM;KACf,MAAM,WAAW,KAAK,QACnB,YAAY,IAAI,CAAC,EAChB,eAAe,SAAS,WAAW,OAAO,UAAU,CAAC,CACtD,MAAM,SAAS,KAAK,aAAa,KAAK,UAAU,KAAM,KAAK;KAC9D,IAAI,UAAU,aAAa,GAAG,SAAS,KAAK;IAC9C;GACF;GACA,IAAI,CAAC,MAAM;IACT,MAAM,YAAY,KAAK,QAAQ,YAAY,IAAI,CAAC,EAAE;IAClD,MAAM,QAAQ,KAAK,QAAQ,iBAAiB,MAAM,SAAS,SAAS,KAAK;IACzE,IACE,aACA,KAAK,QAAQ,KAAK,IAAI,CAAC,EAAE,MAAM,OAAO,QAAQ,SAAS,SAAS,MAAM,MACpE,UAAU,MACR,SAAS,SAAS,OAClB,SAAS,SAAS,QAAQ,SAAS,SAAS,MAC9C,GAEF;IAGF,MAAM,KAAK,KAAK,WAAW,IAAI;IAC/B,IAAI,UAAU;IACd,MAAM,SAAS,SAAkB;KAC/B,IACE,GAAG,oBAAoB,IAAI,KAC3B,SAAS,SAAS,SAAS,KAAK,QAAQ,SAAS,KACjD,SAAS,SAAS,QAAQ,KAAK,QAAQ,KAEvC,UAAU;UACP,IACH,SAAS,SAAS,SAAS,KAAK,aAAa,KAC7C,SAAS,SAAS,QAAQ,KAAK,KAE/B,GAAG,aAAa,MAAM,KAAK;IAC/B;IACA,IAAI,IAAI,MAAM,EAAE;IAChB,IAAI,SAAS;IACb;GACF;GACA,OAAO,KAAK;IACV,GAAG;IACH,UAAU;IACV,UAAU;IACV;IACA;IACA,aAAa,SAAS,cAAc,KAAK,QAAQ,MAAM,SAAS,WAAW,IAAI,KAAA;GACjF,CAAC;EACH;EACA,OAAO,OAAO,QACX,MAAM,UACL,OAAO,WACJ,UACC,KAAK,aAAa,MAAM,YACxB,KAAK,SAAS,UAAU,MAAM,SAAS,SACvC,KAAK,SAAS,WAAW,MAAM,SAAS,MAC5C,MAAM,KACV;CACF;CAEA,OACE,UACA,UACA,MACA,cAA4C,MAClB;EAC1B,MAAM,UAAU,GAAG,cACjB,GAAG,aAAa,QAChB,OACA,GAAG,gBAAgB,UACnB,IACF;EACA,IACE,QAAQ,KAAK,MAAM,GAAG,WAAW,cACjC,QAAQ,KAAK,MAAM,GAAG,WAAW,gBAEjC,OAAO,KAAA;EACT,OAAO,KAAK,gBAAgB,UAAU,UAAU,WAAW,CAAC,EAAE,KAAK,cAAc;GAC/E,UAAU,SAAS;GACnB,MAAM,SAAS;GACf,UAAU,SAAS,cAAc,MAAM,QAAQ,SAAS,cAAc;EACxE,EAAE;CACJ;CAEA,MAAM,UAAkB,OAAe,KAAa,OAA0B;EAC5E,OAAO,KAAK,QAAQ,QACjB,uBACC,gBAAgB,QAAQ,GACxB,KAAK,QAAQ,kBAAkB,UAAU,KAAK,GAC9C,KAAK,QAAQ,kBAAkB,UAAU,GAAG,GAC5C,OACA,CAAC,GACD,CAAC,CACH,CAAC,CACA,SAAS,QAAQ;GAChB,MAAM,QAAQ,KAAK,WAAW,IAAI,OAAO;GACzC,OAAO,OAAO,UAAU,CAAC,IAAI,UAAU,SACnC,CAAC;IAAE,aAAa,IAAI;IAAa;GAAM,CAAC,IACxC,CAAC;EACP,CAAC;CACL;AACF"}
|
package/dist/esbuild.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { t as twillPlugin } from "./plugin-
|
|
2
|
-
|
|
1
|
+
import { t as twillPlugin } from "./plugin-DDOHhv7Z.js";
|
|
2
|
+
// src/esbuild.ts
|
|
3
3
|
var esbuild_default = twillPlugin.esbuild;
|
|
4
|
-
//#endregion
|
|
5
4
|
export { esbuild_default as default };
|
|
6
5
|
|
|
7
6
|
//# sourceMappingURL=esbuild.js.map
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
// src/extensions.ts
|
|
2
2
|
var extensions = [".twill", ".twillx"];
|
|
3
3
|
function isTwillFile(id) {
|
|
4
4
|
return extensions.some((extension) => id.split(/[?#]/, 1)[0].endsWith(extension));
|
|
5
5
|
}
|
|
6
|
-
//#endregion
|
|
7
6
|
export { isTwillFile as n, extensions as t };
|
|
8
7
|
|
|
9
|
-
//# sourceMappingURL=extensions-
|
|
8
|
+
//# sourceMappingURL=extensions-7ixttcoK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensions-
|
|
1
|
+
{"version":3,"file":"extensions-7ixttcoK.js","names":[],"sources":["../src/extensions.ts"],"sourcesContent":["export const extensions = ['.twill', '.twillx'] as const;\nexport function isTwillFile(id: string): boolean {\n return extensions.some((extension) => id.split(/[?#]/, 1)[0]!.endsWith(extension));\n}\n"],"mappings":";AAAA,IAAa,aAAa,CAAC,UAAU,SAAS;AAC9C,SAAgB,YAAY,IAAqB;CAC/C,OAAO,WAAW,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAE,SAAS,SAAS,CAAC;AACnF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as extensions } from "./extensions-
|
|
1
|
+
import { t as extensions } from "./extensions-7ixttcoK.js";
|
|
2
2
|
import { statSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
|
|
4
|
+
// src/files.ts
|
|
5
5
|
var sourceExtensions = [
|
|
6
6
|
".mjs",
|
|
7
7
|
".js",
|
|
@@ -40,7 +40,6 @@ function resolveSourceFile(base) {
|
|
|
40
40
|
if (file(candidate)) return candidate;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
//#endregion
|
|
44
43
|
export { splitId as a, sourceExtensions as i, needsTypeEmission as n, resolveSourceFile as r, isDependency as t };
|
|
45
44
|
|
|
46
|
-
//# sourceMappingURL=files-
|
|
45
|
+
//# sourceMappingURL=files-CgwJJ992.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-
|
|
1
|
+
{"version":3,"file":"files-CgwJJ992.js","names":[],"sources":["../src/files.ts"],"sourcesContent":["import { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { extensions } from './extensions.js';\n\nexport const sourceExtensions = [\n '.mjs',\n '.js',\n '.mts',\n '.ts',\n '.jsx',\n '.tsx',\n '.cjs',\n '.cts',\n '.json',\n ...extensions,\n];\nexport function isDependency(filename: string) {\n return /(?:^|[\\\\/])node_modules[\\\\/]/.test(filename);\n}\nexport function needsTypeEmission(filename: string) {\n return /\\.(?:tsx?|mts|jsx)$/.test(filename) && !/\\.d\\.(?:ts|mts)$/.test(filename);\n}\nexport function splitId(id: string): [string, string] {\n const index = id.search(/[?#]/);\n return index < 0 ? [id, ''] : [id.slice(0, index), id.slice(index)];\n}\nexport function resolveSourceFile(base: string): string | undefined {\n const file = (candidate: string) => {\n try {\n return statSync(candidate).isFile();\n } catch (error) {\n if (['ENOENT', 'ENOTDIR'].includes((error as NodeJS.ErrnoException).code ?? '')) return false;\n throw error;\n }\n };\n if (file(base)) return base;\n // Match the native-first order of the Vite resolver. Explicit filenames\n // remain the way to select one of several same-stem source files.\n for (const extension of sourceExtensions) if (file(base + extension)) return base + extension;\n for (const extension of sourceExtensions) {\n const candidate = resolve(base, 'index' + extension);\n if (file(candidate)) return candidate;\n }\n}\n"],"mappings":";;;;AAIA,IAAa,mBAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,GAAG;AACL;AACA,SAAgB,aAAa,UAAkB;CAC7C,OAAO,+BAA+B,KAAK,QAAQ;AACrD;AACA,SAAgB,kBAAkB,UAAkB;CAClD,OAAO,sBAAsB,KAAK,QAAQ,KAAK,CAAC,mBAAmB,KAAK,QAAQ;AAClF;AACA,SAAgB,QAAQ,IAA8B;CACpD,MAAM,QAAQ,GAAG,OAAO,MAAM;CAC9B,OAAO,QAAQ,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,GAAG,KAAK,GAAG,GAAG,MAAM,KAAK,CAAC;AACpE;AACA,SAAgB,kBAAkB,MAAkC;CAClE,MAAM,QAAQ,cAAsB;EAClC,IAAI;GACF,OAAO,SAAS,SAAS,CAAC,CAAC,OAAO;EACpC,SAAS,OAAO;GACd,IAAI,CAAC,UAAU,SAAS,CAAC,CAAC,SAAU,MAAgC,QAAQ,EAAE,GAAG,OAAO;GACxF,MAAM;EACR;CACF;CACA,IAAI,KAAK,IAAI,GAAG,OAAO;CAGvB,KAAK,MAAM,aAAa,kBAAkB,IAAI,KAAK,OAAO,SAAS,GAAG,OAAO,OAAO;CACpF,KAAK,MAAM,aAAa,kBAAkB;EACxC,MAAM,YAAY,QAAQ,MAAM,UAAU,SAAS;EACnD,IAAI,KAAK,SAAS,GAAG,OAAO;CAC9B;AACF"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as transform, i as originalPosition, n as generatedPosition, r as inferLanguage, t as TwillSyntaxError } from "./compiler-
|
|
2
|
-
import { n as isTwillFile, t as extensions } from "./extensions-
|
|
1
|
+
import { a as transform, i as originalPosition, n as generatedPosition, r as inferLanguage, t as TwillSyntaxError } from "./compiler-DI0H4d1R.js";
|
|
2
|
+
import { n as isTwillFile, t as extensions } from "./extensions-7ixttcoK.js";
|
|
3
3
|
export { TwillSyntaxError, extensions, generatedPosition, inferLanguage, isTwillFile, originalPosition, transform };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as transpileNative, t as transpile } from "./transpile--6CFGUm0.js";
|
|
2
|
+
import { r as loaderConfiguration } from "./configuration-ppqhmuy4.js";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
-
|
|
4
|
+
// src/loader-compiler.ts
|
|
5
5
|
function compileModule(source, filename, dialect) {
|
|
6
6
|
const { config, observations } = loaderConfiguration(filename);
|
|
7
7
|
const result = dialect ? transpile(source, {
|
|
@@ -13,7 +13,6 @@ function compileModule(source, filename, dialect) {
|
|
|
13
13
|
observations
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
//#endregion
|
|
17
16
|
export { compileModule };
|
|
18
17
|
|
|
19
|
-
//# sourceMappingURL=loader-compiler
|
|
18
|
+
//# sourceMappingURL=loader-compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader-compiler.js","names":[],"sources":["../src/loader-compiler.ts"],"sourcesContent":["import ts from 'typescript';\nimport { transpile, transpileNative } from './transpile.js';\nimport { loaderConfiguration } from './configuration.js';\n\nexport function compileModule(source: string, filename: string, dialect: boolean) {\n const { config, observations } = loaderConfiguration(filename);\n const result = dialect\n ? transpile(source, { ...config, filename }, ts.ScriptTarget.ES2022)\n : transpileNative(\n source,\n filename,\n undefined,\n undefined,\n config.jsxImportSource,\n ts.ScriptTarget.ES2022,\n );\n return {\n source:\n result.code +\n '\\n//# sourceMappingURL=data:application/json;base64,' +\n Buffer.from(result.map).toString('base64'),\n observations,\n };\n}\n"],"mappings":";;;;AAIA,SAAgB,cAAc,QAAgB,UAAkB,SAAkB;CAChF,MAAM,EAAE,QAAQ,iBAAiB,oBAAoB,QAAQ;CAC7D,MAAM,SAAS,UACX,UAAU,QAAQ;EAAE,GAAG;EAAQ;CAAS,GAAG,GAAG,aAAa,MAAM,IACjE,gBACE,QACA,UACA,KAAA,GACA,KAAA,GACA,OAAO,iBACP,GAAG,aAAa,MAClB;CACJ,OAAO;EACL,QACE,OAAO,OACP,yDACA,OAAO,KAAK,OAAO,GAAG,CAAC,CAAC,SAAS,QAAQ;EAC3C;CACF;AACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as nodeModule from "node:module";
|
|
2
|
+
// src/loader-registration.ts
|
|
3
|
+
/** Internal registrar shared by the CLI and the public --import entry. */
|
|
4
|
+
async function registerLoader(data = {}) {
|
|
5
|
+
if (typeof nodeModule.registerHooks !== "function") {
|
|
6
|
+
nodeModule.register("./loader.js", import.meta.url, { data });
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const { createHooks } = await import("./loader-sync.js");
|
|
10
|
+
return nodeModule.registerHooks(createHooks(data));
|
|
11
|
+
}
|
|
12
|
+
export { registerLoader as t };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=loader-registration-BO43rvVU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader-registration-BO43rvVU.js","names":[],"sources":["../src/loader-registration.ts"],"sourcesContent":["import * as nodeModule from 'node:module';\nimport type { LoaderOptions } from './loader-state.js';\n\n/** Internal registrar shared by the CLI and the public --import entry. */\nexport async function registerLoader(data: LoaderOptions = {}) {\n if (typeof nodeModule.registerHooks !== 'function') {\n nodeModule.register('./loader.js', import.meta.url, { data });\n return;\n }\n const { createHooks } = await import('./loader-sync.js');\n return nodeModule.registerHooks(createHooks(data));\n}\n"],"mappings":";;;AAIA,eAAsB,eAAe,OAAsB,CAAC,GAAG;CAC7D,IAAI,OAAO,WAAW,kBAAkB,YAAY;EAClD,WAAW,SAAS,eAAe,YAAY,KAAK,EAAE,KAAK,CAAC;EAC5D;CACF;CACA,MAAM,EAAE,gBAAgB,MAAM,OAAO;CACrC,OAAO,WAAW,cAAc,YAAY,IAAI,CAAC;AACnD"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { LoaderOptions } from './loader-state.js';
|
|
2
|
+
import * as nodeModule from 'node:module';
|
|
3
|
+
/** Internal registrar shared by the CLI and the public --import entry. */
|
|
4
|
+
export declare function registerLoader(data?: LoaderOptions): Promise<nodeModule.ModuleHooks | undefined>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as registerLoader } from "./loader-registration-BO43rvVU.js";
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { n as isTwillFile } from "./extensions-7ixttcoK.js";
|
|
2
|
+
import { n as needsTypeEmission, r as resolveSourceFile, t as isDependency } from "./files-CgwJJ992.js";
|
|
3
|
+
import { i as openCompilationCache } from "./compilation-cache-BrV71YKt.js";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
+
// src/loader-state.ts
|
|
7
|
+
function resolveMissing(specifier, parentURL, error) {
|
|
8
|
+
if (["ERR_MODULE_NOT_FOUND", "ERR_UNSUPPORTED_DIR_IMPORT"].includes(error?.code ?? "") && specifier.startsWith(".") && parentURL?.startsWith("file:")) {
|
|
9
|
+
const target = new URL(specifier, parentURL);
|
|
10
|
+
const candidate = resolveSourceFile(fileURLToPath(target));
|
|
11
|
+
if (candidate) return {
|
|
12
|
+
url: pathToFileURL(candidate).href + target.search + target.hash,
|
|
13
|
+
shortCircuit: true
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
function moduleSource(source) {
|
|
19
|
+
return {
|
|
20
|
+
format: "module",
|
|
21
|
+
source,
|
|
22
|
+
shortCircuit: true
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Shared I/O and cache policy; only the small Node hook adapters differ. */
|
|
26
|
+
var LoaderState = class {
|
|
27
|
+
entries;
|
|
28
|
+
cacheEnabled;
|
|
29
|
+
cache;
|
|
30
|
+
cacheInitialized = false;
|
|
31
|
+
constructor(data = {}) {
|
|
32
|
+
this.entries = new Set(data.entries);
|
|
33
|
+
this.cacheEnabled = data.cache === true && process.env.TWILL_CACHE !== "0";
|
|
34
|
+
}
|
|
35
|
+
prepare(url) {
|
|
36
|
+
if (!url.startsWith("file:")) return;
|
|
37
|
+
const filename = fileURLToPath(url);
|
|
38
|
+
const dialect = isTwillFile(url) || this.entries.has(url);
|
|
39
|
+
if (!dialect && (isDependency(filename) || !needsTypeEmission(filename))) return;
|
|
40
|
+
const source = readFileSync(filename, "utf8");
|
|
41
|
+
if (this.cacheEnabled && !this.cacheInitialized) {
|
|
42
|
+
this.cache = openCompilationCache();
|
|
43
|
+
this.cacheInitialized = true;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
url,
|
|
47
|
+
filename,
|
|
48
|
+
source,
|
|
49
|
+
dialect,
|
|
50
|
+
cached: this.cache?.read(url, source, dialect)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
complete(plan, result) {
|
|
54
|
+
this.cache?.write(plan.url, plan.source, plan.dialect, result.source, result.observations);
|
|
55
|
+
return moduleSource(result.source);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
export { moduleSource as n, resolveMissing as r, LoaderState as t };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=loader-state-DB7sONR_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader-state-DB7sONR_.js","names":[],"sources":["../src/loader-state.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { isTwillFile } from './extensions.js';\nimport { isDependency, needsTypeEmission, resolveSourceFile } from './files.js';\nimport { openCompilationCache, type CompilationCache } from './compilation-cache.js';\n\nexport type LoaderOptions = { entries?: string[]; cache?: boolean };\nexport type PreparedModule = {\n url: string;\n filename: string;\n source: string;\n dialect: boolean;\n cached: string | undefined;\n};\n\nexport function resolveMissing(specifier: string, parentURL: string | undefined, error: unknown) {\n if (\n ['ERR_MODULE_NOT_FOUND', 'ERR_UNSUPPORTED_DIR_IMPORT'].includes(\n (error as NodeJS.ErrnoException | undefined)?.code ?? '',\n ) &&\n specifier.startsWith('.') &&\n parentURL?.startsWith('file:')\n ) {\n const target = new URL(specifier, parentURL);\n const candidate = resolveSourceFile(fileURLToPath(target));\n if (candidate)\n return {\n url: pathToFileURL(candidate).href + target.search + target.hash,\n shortCircuit: true,\n };\n }\n throw error;\n}\n\nexport function moduleSource(source: string) {\n return { format: 'module' as const, source, shortCircuit: true };\n}\n\n/** Shared I/O and cache policy; only the small Node hook adapters differ. */\nexport class LoaderState {\n private entries: Set<string>;\n private cacheEnabled: boolean;\n private cache: CompilationCache | undefined;\n private cacheInitialized = false;\n\n constructor(data: LoaderOptions = {}) {\n this.entries = new Set(data.entries);\n this.cacheEnabled = data.cache === true && process.env.TWILL_CACHE !== '0';\n }\n\n prepare(url: string): PreparedModule | undefined {\n if (!url.startsWith('file:')) return;\n const filename = fileURLToPath(url);\n const dialect = isTwillFile(url) || this.entries.has(url);\n if (!dialect && (isDependency(filename) || !needsTypeEmission(filename))) return;\n const source = readFileSync(filename, 'utf8');\n if (this.cacheEnabled && !this.cacheInitialized) {\n this.cache = openCompilationCache();\n this.cacheInitialized = true;\n }\n return { url, filename, source, dialect, cached: this.cache?.read(url, source, dialect) };\n }\n\n complete(\n plan: PreparedModule,\n result: ReturnType<typeof import('./loader-compiler.js').compileModule>,\n ) {\n this.cache?.write(plan.url, plan.source, plan.dialect, result.source, result.observations);\n return moduleSource(result.source);\n }\n}\n"],"mappings":";;;;;;AAeA,SAAgB,eAAe,WAAmB,WAA+B,OAAgB;CAC/F,IACE,CAAC,wBAAwB,4BAA4B,CAAC,CAAC,SACpD,OAA6C,QAAQ,EACxD,KACA,UAAU,WAAW,GAAG,KACxB,WAAW,WAAW,OAAO,GAC7B;EACA,MAAM,SAAS,IAAI,IAAI,WAAW,SAAS;EAC3C,MAAM,YAAY,kBAAkB,cAAc,MAAM,CAAC;EACzD,IAAI,WACF,OAAO;GACL,KAAK,cAAc,SAAS,CAAC,CAAC,OAAO,OAAO,SAAS,OAAO;GAC5D,cAAc;EAChB;CACJ;CACA,MAAM;AACR;AAEA,SAAgB,aAAa,QAAgB;CAC3C,OAAO;EAAE,QAAQ;EAAmB;EAAQ,cAAc;CAAK;AACjE;;AAGA,IAAa,cAAb,MAAyB;CACvB;CACA;CACA;CACA,mBAA2B;CAE3B,YAAY,OAAsB,CAAC,GAAG;EACpC,KAAK,UAAU,IAAI,IAAI,KAAK,OAAO;EACnC,KAAK,eAAe,KAAK,UAAU,QAAQ,QAAQ,IAAI,gBAAgB;CACzE;CAEA,QAAQ,KAAyC;EAC/C,IAAI,CAAC,IAAI,WAAW,OAAO,GAAG;EAC9B,MAAM,WAAW,cAAc,GAAG;EAClC,MAAM,UAAU,YAAY,GAAG,KAAK,KAAK,QAAQ,IAAI,GAAG;EACxD,IAAI,CAAC,YAAY,aAAa,QAAQ,KAAK,CAAC,kBAAkB,QAAQ,IAAI;EAC1E,MAAM,SAAS,aAAa,UAAU,MAAM;EAC5C,IAAI,KAAK,gBAAgB,CAAC,KAAK,kBAAkB;GAC/C,KAAK,QAAQ,qBAAqB;GAClC,KAAK,mBAAmB;EAC1B;EACA,OAAO;GAAE;GAAK;GAAU;GAAQ;GAAS,QAAQ,KAAK,OAAO,KAAK,KAAK,QAAQ,OAAO;EAAE;CAC1F;CAEA,SACE,MACA,QACA;EACA,KAAK,OAAO,MAAM,KAAK,KAAK,KAAK,QAAQ,KAAK,SAAS,OAAO,QAAQ,OAAO,YAAY;EACzF,OAAO,aAAa,OAAO,MAAM;CACnC;AACF"}
|