@swiftuijs/twill 0.3.1 → 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.
Files changed (58) hide show
  1. package/README.md +8 -3
  2. package/dist/branches.d.ts +7 -1
  3. package/dist/cli.js +7 -8
  4. package/dist/{compilation-cache-7SugqJ4n.js → compilation-cache-BrV71YKt.js} +2 -3
  5. package/dist/{compilation-cache-7SugqJ4n.js.map → compilation-cache-BrV71YKt.js.map} +1 -1
  6. package/dist/{compiler-BdkU4Ruh.js → compiler-DI0H4d1R.js} +147 -55
  7. package/dist/compiler-DI0H4d1R.js.map +1 -0
  8. package/dist/compiler.d.ts +2 -0
  9. package/dist/config.js +1 -2
  10. package/dist/{configuration-BVMf6Q_j.js → configuration-ppqhmuy4.js} +7 -5
  11. package/dist/configuration-ppqhmuy4.js.map +1 -0
  12. package/dist/configuration.d.ts +1 -1
  13. package/dist/{declarations-BTAS8Mb_.js → declarations-DXtb1AHP.js} +3 -4
  14. package/dist/{declarations-BTAS8Mb_.js.map → declarations-DXtb1AHP.js.map} +1 -1
  15. package/dist/declarations.js +1 -2
  16. package/dist/{doctor-Co_pdZtt.js → doctor-BHwU_YBw.js} +4 -6
  17. package/dist/{doctor-Co_pdZtt.js.map → doctor-BHwU_YBw.js.map} +1 -1
  18. package/dist/doctor.js +1 -2
  19. package/dist/editor.d.ts +1 -0
  20. package/dist/editor.js +31 -5
  21. package/dist/editor.js.map +1 -1
  22. package/dist/esbuild.js +2 -3
  23. package/dist/{extensions-B1xTkoYP.js → extensions-7ixttcoK.js} +2 -3
  24. package/dist/{extensions-B1xTkoYP.js.map → extensions-7ixttcoK.js.map} +1 -1
  25. package/dist/{files-BW9geU0_.js → files-CgwJJ992.js} +3 -4
  26. package/dist/{files-BW9geU0_.js.map → files-CgwJJ992.js.map} +1 -1
  27. package/dist/index.js +2 -2
  28. package/dist/loader-compiler.js +3 -4
  29. package/dist/{loader-registration-B1ST9h1e.js → loader-registration-BO43rvVU.js} +2 -3
  30. package/dist/{loader-registration-B1ST9h1e.js.map → loader-registration-BO43rvVU.js.map} +1 -1
  31. package/dist/loader-registration.js +1 -2
  32. package/dist/{loader-state-DE2ArGYl.js → loader-state-DB7sONR_.js} +5 -6
  33. package/dist/{loader-state-DE2ArGYl.js.map → loader-state-DB7sONR_.js.map} +1 -1
  34. package/dist/loader-sync.js +2 -3
  35. package/dist/loader.js +2 -3
  36. package/dist/{plugin-DdTVagIU.js → plugin-DDOHhv7Z.js} +6 -7
  37. package/dist/{plugin-DdTVagIU.js.map → plugin-DDOHhv7Z.js.map} +1 -1
  38. package/dist/{project-ZmlpFooa.js → project-DYXf2Kgt.js} +7 -9
  39. package/dist/{project-ZmlpFooa.js.map → project-DYXf2Kgt.js.map} +1 -1
  40. package/dist/project.js +2 -2
  41. package/dist/register.js +2 -3
  42. package/dist/rollup.js +2 -3
  43. package/dist/rspack.js +2 -3
  44. package/dist/syntax.js +2 -3
  45. package/dist/{transpile-CLNavDUr.js → transpile--6CFGUm0.js} +3 -4
  46. package/dist/{transpile-CLNavDUr.js.map → transpile--6CFGUm0.js.map} +1 -1
  47. package/dist/typescript-plugin.cjs +221 -117
  48. package/dist/typescript-plugin.cjs.map +1 -1
  49. package/dist/vite-D0Ct4uy4.js +6 -0
  50. package/dist/{vite-BI-5KRgr.js.map → vite-D0Ct4uy4.js.map} +1 -1
  51. package/dist/vite-react.js +2 -3
  52. package/dist/vite.js +1 -2
  53. package/dist/webpack.js +2 -3
  54. package/package.json +3 -3
  55. package/schemas/twill.schema.json +6 -0
  56. package/dist/compiler-BdkU4Ruh.js.map +0 -1
  57. package/dist/configuration-BVMf6Q_j.js.map +0 -1
  58. package/dist/vite-BI-5KRgr.js +0 -7
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-Co_pdZtt.js","names":["metadata"],"sources":["../package.json","../src/doctor.ts"],"sourcesContent":["{\n \"name\": \"@swiftuijs/twill\",\n \"version\": \"0.3.1\",\n \"description\": \"Twill extends TypeScript with Swift-inspired syntax: trailing closures, guards, defer and checked switch expressions. Compiles to ordinary JavaScript.\",\n \"main\": \"./dist/typescript-plugin.cjs\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/swiftuijs/twill.git\",\n \"directory\": \"packages/twill\"\n },\n \"keywords\": [\n \"javascript\",\n \"typescript\",\n \"trailing-closures\",\n \"swift\",\n \"vite\",\n \"unplugin\",\n \"react\",\n \"vue\",\n \"twill\",\n \"guard\",\n \"defer\"\n ],\n \"author\": {\n \"name\": \"forth.ink\",\n \"url\": \"https://forth.ink\"\n },\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"bugs\": {\n \"url\": \"https://github.com/swiftuijs/twill/issues\"\n },\n \"homepage\": \"https://twill.evecalm.com/\",\n \"dependencies\": {\n \"@ampproject/remapping\": \"^2.3.0\",\n \"@jridgewell/trace-mapping\": \"^0.3.31\",\n \"acorn\": \"8.18.0\",\n \"acorn-jsx\": \"^5.3.2\",\n \"acorn-typescript\": \"1.4.13\",\n \"magic-string\": \"^1.4.2\",\n \"typescript\": \"catalog:\",\n \"unplugin\": \"^3.4.0\"\n },\n \"sideEffects\": false,\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"files\": [\n \"bin\",\n \"dist/**/*.js\",\n \"dist/**/*.js.map\",\n \"dist/**/*.d.ts\",\n \"schemas\",\n \"README.md\",\n \"LICENSE\",\n \"dist/**/*.cjs\",\n \"dist/**/*.cjs.map\",\n \"dist/*.LICENSE.txt\"\n ],\n \"bin\": {\n \"twill\": \"./bin/twill.mjs\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./vite\": {\n \"types\": \"./dist/vite.d.ts\",\n \"import\": \"./dist/vite.js\"\n },\n \"./rollup\": {\n \"types\": \"./dist/rollup.d.ts\",\n \"import\": \"./dist/rollup.js\"\n },\n \"./esbuild\": {\n \"types\": \"./dist/esbuild.d.ts\",\n \"import\": \"./dist/esbuild.js\"\n },\n \"./webpack\": {\n \"types\": \"./dist/webpack.d.ts\",\n \"import\": \"./dist/webpack.js\"\n },\n \"./rspack\": {\n \"types\": \"./dist/rspack.d.ts\",\n \"import\": \"./dist/rspack.js\"\n },\n \"./project\": {\n \"types\": \"./dist/project.d.ts\",\n \"import\": \"./dist/project.js\"\n },\n \"./editor\": {\n \"types\": \"./dist/editor.d.ts\",\n \"import\": \"./dist/editor.js\"\n },\n \"./register\": {\n \"types\": \"./dist/register.d.ts\",\n \"import\": \"./dist/register.js\"\n },\n \"./schema\": \"./schemas/twill.schema.json\",\n \"./typescript-plugin\": {\n \"types\": \"./dist/typescript-plugin.d.ts\",\n \"require\": \"./dist/typescript-plugin.cjs\",\n \"default\": \"./dist/typescript-plugin.cjs\"\n },\n \"./doctor\": {\n \"types\": \"./dist/doctor.d.ts\",\n \"import\": \"./dist/doctor.js\"\n },\n \"./syntax\": {\n \"types\": \"./dist/syntax.d.ts\",\n \"import\": \"./dist/syntax.js\"\n },\n \"./config\": {\n \"types\": \"./dist/config.d.ts\",\n \"import\": \"./dist/config.js\"\n },\n \"./declarations\": {\n \"types\": \"./dist/declarations.d.ts\",\n \"import\": \"./dist/declarations.js\"\n },\n \"./vite-react\": {\n \"types\": \"./dist/vite-react.d.ts\",\n \"import\": \"./dist/vite-react.js\"\n }\n },\n \"peerDependencies\": {\n \"react\": \"^18.2.0 || ^19.0.0\",\n \"vue\": \"^3.3.0\",\n \"@vitejs/plugin-react\": \"^6.1.1\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n },\n \"@vitejs/plugin-react\": {\n \"optional\": true\n }\n },\n \"types\": \"./dist/index.d.ts\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"module\": \"./dist/index.js\",\n \"scripts\": {\n \"build\": \"node ../../scripts/generate-runtime-helper.mjs && vite build && vite build --config vite.plugin.config.ts && node scripts/prepare-core.mjs\",\n \"typecheck\": \"tsc --noEmit -p tsconfig.json\",\n \"prepack\": \"pnpm run build\",\n \"test:unit\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:package\": \"node tests/consumer.mjs\",\n \"test:size\": \"node tests/bundle-size.mjs\",\n \"test:browser\": \"playwright test\",\n \"benchmark\": \"node benchmarks/compiler.mjs\",\n \"test\": \"pnpm run test:unit\",\n \"benchmark:branching\": \"node benchmarks/branching.mjs\",\n \"benchmark:enum-patterns\": \"node benchmarks/enum-patterns.mjs\",\n \"benchmark:runtime\": \"node benchmarks/runtime-helpers.mjs\",\n \"benchmark:if-bindings\": \"node benchmarks/if-bindings.mjs\"\n },\n \"devDependencies\": {\n \"vite\": \"catalog:\",\n \"vite-plugin-dts\": \"^5.1.2\",\n \"@types/node\": \"catalog:\",\n \"@vitejs/plugin-react\": \"catalog:\",\n \"vitest\": \"catalog:\",\n \"@vitest/coverage-v8\": \"catalog:\",\n \"@rspack/core\": \"catalog:\",\n \"@types/react\": \"catalog:\",\n \"@types/react-dom\": \"catalog:\",\n \"@vue/server-renderer\": \"catalog:\",\n \"esbuild\": \"catalog:\",\n \"react\": \"catalog:\",\n \"react-dom\": \"catalog:\",\n \"rollup\": \"catalog:\",\n \"vue\": \"catalog:\",\n \"webpack\": \"catalog:\",\n \"@playwright/test\": \"catalog:\",\n \"@swiftuijs/twill-runtime\": \"workspace:*\"\n }\n}\n","import ts from 'typescript';\nimport metadata from '../package.json';\nimport { TwillProject } from './project.js';\nimport { isTwillFile } from './compiler.js';\n\n/** Shareable diagnostics without source contents or environment-variable values. */\nexport function inspectProject(project: TwillProject, filename?: string) {\n const started = performance.now();\n const diagnostics = project.diagnostics(filename);\n const files = project.sourceFiles();\n return {\n twillVersion: metadata.version,\n typescriptVersion: ts.version,\n nodeVersion: process.version,\n root: project.root,\n configFiles: project.configFiles,\n compilerOptions: project.compilerOptions,\n files: {\n total: files.length,\n twill: files.filter(isTwillFile).length,\n native: files.filter((file) => !isTwillFile(file)).length,\n },\n sourceFiles: files,\n diagnostics,\n diagnosticTimeMs: performance.now() - started,\n ok: !diagnostics.some((diagnostic) => diagnostic.category === 'error'),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACMA,SAAgB,eAAe,SAAuB,UAAmB;CACvE,MAAM,UAAU,YAAY,IAAI;CAChC,MAAM,cAAc,QAAQ,YAAY,QAAQ;CAChD,MAAM,QAAQ,QAAQ,YAAY;CAClC,OAAO;EACL,cAAcA,gBAAS;EACvB,mBAAmB,GAAG;EACtB,aAAa,QAAQ;EACrB,MAAM,QAAQ;EACd,aAAa,QAAQ;EACrB,iBAAiB,QAAQ;EACzB,OAAO;GACL,OAAO,MAAM;GACb,OAAO,MAAM,OAAO,WAAW,CAAC,CAAC;GACjC,QAAQ,MAAM,QAAQ,SAAS,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;EACrD;EACA,aAAa;EACb;EACA,kBAAkB,YAAY,IAAI,IAAI;EACtC,IAAI,CAAC,YAAY,MAAM,eAAe,WAAW,aAAa,OAAO;CACvE;AACF"}
1
+ {"version":3,"file":"doctor-BHwU_YBw.js","names":["metadata"],"sources":["../package.json","../src/doctor.ts"],"sourcesContent":["{\n \"name\": \"@swiftuijs/twill\",\n \"version\": \"0.4.0\",\n \"description\": \"Twill extends TypeScript with Swift-inspired syntax: trailing closures, guards, defer and checked switch expressions. Compiles to ordinary JavaScript.\",\n \"main\": \"./dist/typescript-plugin.cjs\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/swiftuijs/twill.git\",\n \"directory\": \"packages/twill\"\n },\n \"keywords\": [\n \"javascript\",\n \"typescript\",\n \"trailing-closures\",\n \"swift\",\n \"vite\",\n \"unplugin\",\n \"react\",\n \"vue\",\n \"twill\",\n \"guard\",\n \"defer\"\n ],\n \"author\": {\n \"name\": \"forth.ink\",\n \"url\": \"https://forth.ink\"\n },\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"bugs\": {\n \"url\": \"https://github.com/swiftuijs/twill/issues\"\n },\n \"homepage\": \"https://twill.evecalm.com/\",\n \"dependencies\": {\n \"@ampproject/remapping\": \"^2.3.0\",\n \"@jridgewell/trace-mapping\": \"^0.3.31\",\n \"acorn\": \"8.18.0\",\n \"acorn-jsx\": \"^5.3.2\",\n \"acorn-typescript\": \"1.4.13\",\n \"magic-string\": \"^1.4.2\",\n \"typescript\": \"catalog:\",\n \"unplugin\": \"^3.4.0\"\n },\n \"sideEffects\": false,\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"files\": [\n \"bin\",\n \"dist/**/*.js\",\n \"dist/**/*.js.map\",\n \"dist/**/*.d.ts\",\n \"schemas\",\n \"README.md\",\n \"LICENSE\",\n \"dist/**/*.cjs\",\n \"dist/**/*.cjs.map\",\n \"dist/*.LICENSE.txt\"\n ],\n \"bin\": {\n \"twill\": \"./bin/twill.mjs\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./vite\": {\n \"types\": \"./dist/vite.d.ts\",\n \"import\": \"./dist/vite.js\"\n },\n \"./rollup\": {\n \"types\": \"./dist/rollup.d.ts\",\n \"import\": \"./dist/rollup.js\"\n },\n \"./esbuild\": {\n \"types\": \"./dist/esbuild.d.ts\",\n \"import\": \"./dist/esbuild.js\"\n },\n \"./webpack\": {\n \"types\": \"./dist/webpack.d.ts\",\n \"import\": \"./dist/webpack.js\"\n },\n \"./rspack\": {\n \"types\": \"./dist/rspack.d.ts\",\n \"import\": \"./dist/rspack.js\"\n },\n \"./project\": {\n \"types\": \"./dist/project.d.ts\",\n \"import\": \"./dist/project.js\"\n },\n \"./editor\": {\n \"types\": \"./dist/editor.d.ts\",\n \"import\": \"./dist/editor.js\"\n },\n \"./register\": {\n \"types\": \"./dist/register.d.ts\",\n \"import\": \"./dist/register.js\"\n },\n \"./schema\": \"./schemas/twill.schema.json\",\n \"./typescript-plugin\": {\n \"types\": \"./dist/typescript-plugin.d.ts\",\n \"require\": \"./dist/typescript-plugin.cjs\",\n \"default\": \"./dist/typescript-plugin.cjs\"\n },\n \"./doctor\": {\n \"types\": \"./dist/doctor.d.ts\",\n \"import\": \"./dist/doctor.js\"\n },\n \"./syntax\": {\n \"types\": \"./dist/syntax.d.ts\",\n \"import\": \"./dist/syntax.js\"\n },\n \"./config\": {\n \"types\": \"./dist/config.d.ts\",\n \"import\": \"./dist/config.js\"\n },\n \"./declarations\": {\n \"types\": \"./dist/declarations.d.ts\",\n \"import\": \"./dist/declarations.js\"\n },\n \"./vite-react\": {\n \"types\": \"./dist/vite-react.d.ts\",\n \"import\": \"./dist/vite-react.js\"\n }\n },\n \"peerDependencies\": {\n \"react\": \"^18.2.0 || ^19.0.0\",\n \"vue\": \"^3.3.0\",\n \"@vitejs/plugin-react\": \"^6.1.1\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"vue\": {\n \"optional\": true\n },\n \"@vitejs/plugin-react\": {\n \"optional\": true\n }\n },\n \"types\": \"./dist/index.d.ts\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"module\": \"./dist/index.js\",\n \"scripts\": {\n \"build\": \"node ../../scripts/generate-runtime-helper.mjs && vite build && vite build --config vite.plugin.config.ts && node scripts/prepare-core.mjs\",\n \"typecheck\": \"tsc --noEmit -p tsconfig.json\",\n \"prepack\": \"pnpm run build\",\n \"test:unit\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:package\": \"node tests/consumer.mjs\",\n \"test:size\": \"node tests/bundle-size.mjs\",\n \"test:browser\": \"playwright test\",\n \"benchmark\": \"node benchmarks/compiler.mjs\",\n \"test\": \"pnpm run test:unit\",\n \"benchmark:branching\": \"node benchmarks/branching.mjs\",\n \"benchmark:enum-patterns\": \"node benchmarks/enum-patterns.mjs\",\n \"benchmark:runtime\": \"node benchmarks/runtime-helpers.mjs\",\n \"benchmark:if-bindings\": \"node benchmarks/if-bindings.mjs\"\n },\n \"devDependencies\": {\n \"vite\": \"catalog:\",\n \"vite-plugin-dts\": \"^5.1.2\",\n \"@types/node\": \"catalog:\",\n \"@vitejs/plugin-react\": \"catalog:\",\n \"vitest\": \"catalog:\",\n \"@vitest/coverage-v8\": \"catalog:\",\n \"@rspack/core\": \"catalog:\",\n \"@types/react\": \"catalog:\",\n \"@types/react-dom\": \"catalog:\",\n \"@vue/server-renderer\": \"catalog:\",\n \"esbuild\": \"catalog:\",\n \"react\": \"catalog:\",\n \"react-dom\": \"catalog:\",\n \"rollup\": \"catalog:\",\n \"vue\": \"catalog:\",\n \"webpack\": \"catalog:\",\n \"@playwright/test\": \"catalog:\",\n \"@swiftuijs/twill-runtime\": \"workspace:*\"\n }\n}\n","import ts from 'typescript';\nimport metadata from '../package.json';\nimport { TwillProject } from './project.js';\nimport { isTwillFile } from './compiler.js';\n\n/** Shareable diagnostics without source contents or environment-variable values. */\nexport function inspectProject(project: TwillProject, filename?: string) {\n const started = performance.now();\n const diagnostics = project.diagnostics(filename);\n const files = project.sourceFiles();\n return {\n twillVersion: metadata.version,\n typescriptVersion: ts.version,\n nodeVersion: process.version,\n root: project.root,\n configFiles: project.configFiles,\n compilerOptions: project.compilerOptions,\n files: {\n total: files.length,\n twill: files.filter(isTwillFile).length,\n native: files.filter((file) => !isTwillFile(file)).length,\n },\n sourceFiles: files,\n diagnostics,\n diagnosticTimeMs: performance.now() - started,\n ok: !diagnostics.some((diagnostic) => diagnostic.category === 'error'),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACMA,SAAgB,eAAe,SAAuB,UAAmB;CACvE,MAAM,UAAU,YAAY,IAAI;CAChC,MAAM,cAAc,QAAQ,YAAY,QAAQ;CAChD,MAAM,QAAQ,QAAQ,YAAY;CAClC,OAAO;EACL,cAAcA,gBAAS;EACvB,mBAAmB,GAAG;EACtB,aAAa,QAAQ;EACrB,MAAM,QAAQ;EACd,aAAa,QAAQ;EACrB,iBAAiB,QAAQ;EACzB,OAAO;GACL,OAAO,MAAM;GACb,OAAO,MAAM,OAAO,WAAW,CAAC,CAAC;GACjC,QAAQ,MAAM,QAAQ,SAAS,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;EACrD;EACA,aAAa;EACb;EACA,kBAAkB,YAAY,IAAI,IAAI;EACtC,IAAI,CAAC,YAAY,MAAM,eAAe,WAAW,aAAa,OAAO;CACvE;AACF"}
package/dist/doctor.js CHANGED
@@ -1,2 +1 @@
1
- import { t as inspectProject } from "./doctor-Co_pdZtt.js";
2
- export { inspectProject };
1
+ export { t as inspectProject } from "./doctor-BHwU_YBw.js";
package/dist/editor.d.ts CHANGED
@@ -18,6 +18,7 @@ export declare class TwillEditor {
18
18
  readonly project: TwillProject;
19
19
  private attributeCache;
20
20
  private descriptorCache;
21
+ private internalBindingCache;
21
22
  constructor(project: TwillProject);
22
23
  private sourceFile;
23
24
  private attributes;
package/dist/editor.js CHANGED
@@ -1,12 +1,13 @@
1
- import { n as isTwillFile } from "./extensions-B1xTkoYP.js";
2
- import { n as sourceFilename, r as virtualFilename } from "./project-ZmlpFooa.js";
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
- //#region src/editor.ts
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
- const info = this.project.service.getCompletionsAtPosition(virtualFilename(filename), offset, {
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
@@ -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":"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"}
package/dist/esbuild.js CHANGED
@@ -1,7 +1,6 @@
1
- import { t as twillPlugin } from "./plugin-DdTVagIU.js";
2
- //#region src/esbuild.ts
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
- //#region src/extensions.ts
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-B1xTkoYP.js.map
8
+ //# sourceMappingURL=extensions-7ixttcoK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensions-B1xTkoYP.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
+ {"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-B1xTkoYP.js";
1
+ import { t as extensions } from "./extensions-7ixttcoK.js";
2
2
  import { statSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
- //#region src/files.ts
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-BW9geU0_.js.map
45
+ //# sourceMappingURL=files-CgwJJ992.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"files-BW9geU0_.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"}
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-BdkU4Ruh.js";
2
- import { n as isTwillFile, t as extensions } from "./extensions-B1xTkoYP.js";
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 { r as loaderConfiguration } from "./configuration-BVMf6Q_j.js";
2
- import { n as transpileNative, t as transpile } from "./transpile-CLNavDUr.js";
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
- //#region src/loader-compiler.ts
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
18
  //# sourceMappingURL=loader-compiler.js.map
@@ -1,5 +1,5 @@
1
1
  import * as nodeModule from "node:module";
2
- //#region src/loader-registration.ts
2
+ // src/loader-registration.ts
3
3
  /** Internal registrar shared by the CLI and the public --import entry. */
4
4
  async function registerLoader(data = {}) {
5
5
  if (typeof nodeModule.registerHooks !== "function") {
@@ -9,7 +9,6 @@ async function registerLoader(data = {}) {
9
9
  const { createHooks } = await import("./loader-sync.js");
10
10
  return nodeModule.registerHooks(createHooks(data));
11
11
  }
12
- //#endregion
13
12
  export { registerLoader as t };
14
13
 
15
- //# sourceMappingURL=loader-registration-B1ST9h1e.js.map
14
+ //# sourceMappingURL=loader-registration-BO43rvVU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader-registration-B1ST9h1e.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"}
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"}
@@ -1,2 +1 @@
1
- import { t as registerLoader } from "./loader-registration-B1ST9h1e.js";
2
- export { registerLoader };
1
+ export { t as registerLoader } from "./loader-registration-BO43rvVU.js";
@@ -1,9 +1,9 @@
1
- import { n as isTwillFile } from "./extensions-B1xTkoYP.js";
2
- import { i as openCompilationCache } from "./compilation-cache-7SugqJ4n.js";
3
- import { n as needsTypeEmission, r as resolveSourceFile, t as isDependency } from "./files-BW9geU0_.js";
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
4
  import { readFileSync } from "node:fs";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
- //#region src/loader-state.ts
6
+ // src/loader-state.ts
7
7
  function resolveMissing(specifier, parentURL, error) {
8
8
  if (["ERR_MODULE_NOT_FOUND", "ERR_UNSUPPORTED_DIR_IMPORT"].includes(error?.code ?? "") && specifier.startsWith(".") && parentURL?.startsWith("file:")) {
9
9
  const target = new URL(specifier, parentURL);
@@ -55,7 +55,6 @@ var LoaderState = class {
55
55
  return moduleSource(result.source);
56
56
  }
57
57
  };
58
- //#endregion
59
58
  export { moduleSource as n, resolveMissing as r, LoaderState as t };
60
59
 
61
- //# sourceMappingURL=loader-state-DE2ArGYl.js.map
60
+ //# sourceMappingURL=loader-state-DB7sONR_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader-state-DE2ArGYl.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"}
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"}
@@ -1,6 +1,6 @@
1
- import { n as moduleSource, r as resolveMissing, t as LoaderState } from "./loader-state-DE2ArGYl.js";
1
+ import { n as moduleSource, r as resolveMissing, t as LoaderState } from "./loader-state-DB7sONR_.js";
2
2
  import { createRequire } from "node:module";
3
- //#region src/loader-sync.ts
3
+ // src/loader-sync.ts
4
4
  var require = createRequire(import.meta.url);
5
5
  function createHooks(data = {}) {
6
6
  const state = new LoaderState(data);
@@ -22,7 +22,6 @@ function createHooks(data = {}) {
22
22
  }
23
23
  };
24
24
  }
25
- //#endregion
26
25
  export { createHooks };
27
26
 
28
27
  //# sourceMappingURL=loader-sync.js.map
package/dist/loader.js CHANGED
@@ -1,5 +1,5 @@
1
- import { n as moduleSource, r as resolveMissing, t as LoaderState } from "./loader-state-DE2ArGYl.js";
2
- //#region src/loader.ts
1
+ import { n as moduleSource, r as resolveMissing, t as LoaderState } from "./loader-state-DB7sONR_.js";
2
+ // src/loader.ts
3
3
  var state = new LoaderState();
4
4
  function initialize(data) {
5
5
  state = new LoaderState(data);
@@ -18,7 +18,6 @@ var load = async (url, context, nextLoad) => {
18
18
  const { compileModule } = await import("./loader-compiler.js");
19
19
  return state.complete(plan, compileModule(plan.source, plan.filename, plan.dialect));
20
20
  };
21
- //#endregion
22
21
  export { initialize, load, resolve };
23
22
 
24
23
  //# sourceMappingURL=loader.js.map
@@ -1,11 +1,11 @@
1
- import { n as isTwillFile } from "./extensions-B1xTkoYP.js";
2
- import { n as loadConfig, t as configurationFiles } from "./configuration-BVMf6Q_j.js";
3
- import { a as splitId, i as sourceExtensions, n as needsTypeEmission, r as resolveSourceFile, t as isDependency } from "./files-BW9geU0_.js";
4
- import { n as transpileNative, t as transpile } from "./transpile-CLNavDUr.js";
1
+ import { n as isTwillFile } from "./extensions-7ixttcoK.js";
2
+ import { n as loadConfig, t as configurationFiles } from "./configuration-ppqhmuy4.js";
3
+ import { n as transpileNative, t as transpile } from "./transpile--6CFGUm0.js";
4
+ import { a as splitId, i as sourceExtensions, n as needsTypeEmission, r as resolveSourceFile, t as isDependency } from "./files-CgwJJ992.js";
5
5
  import { existsSync } from "node:fs";
6
6
  import { dirname, isAbsolute, resolve } from "node:path";
7
7
  import { createUnplugin } from "unplugin";
8
- //#region src/plugin.ts
8
+ // src/plugin.ts
9
9
  var twillPlugin = createUnplugin((options = {}, meta) => {
10
10
  let root = options.root ?? process.cwd();
11
11
  let config = {
@@ -135,7 +135,6 @@ var twillPlugin = createUnplugin((options = {}, meta) => {
135
135
  }
136
136
  };
137
137
  });
138
- //#endregion
139
138
  export { twillPlugin as t };
140
139
 
141
- //# sourceMappingURL=plugin-DdTVagIU.js.map
140
+ //# sourceMappingURL=plugin-DDOHhv7Z.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-DdTVagIU.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import { dirname, isAbsolute, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { createUnplugin } from 'unplugin';\nimport { isTwillFile, type TransformOptions } from './compiler.js';\nimport { loadConfig, configurationFiles } from './config.js';\nimport { transpile, transpileNative } from './transpile.js';\nimport {\n isDependency,\n needsTypeEmission,\n splitId,\n resolveSourceFile,\n sourceExtensions,\n} from './files.js';\n\nexport interface PluginOptions extends Omit<TransformOptions, 'filename' | 'language'> {\n root?: string;\n /** Resolve relative extensionless native/Twill sources. Defaults to true. */\n resolveExtensions?: boolean;\n /** Native TS/JSX emission: defaults off for Vite/esbuild, on for Rollup/webpack/rspack. */\n nativeSources?: boolean;\n}\n\nexport const twillPlugin = createUnplugin<PluginOptions | undefined, false>(\n (options = {}, meta) => {\n let root = options.root ?? process.cwd();\n let config = { ...loadConfig(root), ...options };\n let configFiles = configurationFiles(root);\n let configError: unknown;\n let servingVite = false;\n // Reuse native host emission where it already exists.\n const nativeSources = options.nativeSources ?? !['vite', 'esbuild'].includes(meta.framework);\n return {\n name: 'twill',\n enforce: 'pre',\n buildStart() {\n // Refresh once per build, including incremental contexts. Vite dev\n // uses its server watcher to report errors and invalidate the graph.\n if (!servingVite) {\n configError = undefined;\n try {\n config = { ...loadConfig(root), ...options };\n configFiles = configurationFiles(root);\n } catch (cause) {\n // Report through transformed modules, retaining their watch\n // dependencies. A fatal make/start error can stop host watching.\n configError = cause;\n }\n }\n },\n webpack(compiler) {\n if (nativeSources)\n compiler.options.module.rules.push({\n include: (file) => !isDependency(file) && needsTypeEmission(file),\n // Twill already emits JS. Webpack's automatic TS stripper rejects\n // .tsx by extension even when a loader has lowered all JSX.\n parser: { typescript: false },\n });\n },\n esbuild: {\n setup(build) {\n // unplugin tags its resolved files with a custom namespace. Native\n // dependencies of those files must re-enter esbuild's normal resolver.\n build.onResolve({ filter: /.*/, namespace: 'twill' }, (args) =>\n build.resolve(args.path, {\n resolveDir: dirname(args.importer),\n kind: args.kind,\n }),\n );\n },\n },\n vite: {\n configResolved(viteConfig) {\n root = options.root ?? viteConfig.root;\n config = { ...loadConfig(root), ...options };\n servingVite = viteConfig.command === 'serve';\n },\n config() {\n return {\n resolve: {\n extensions: sourceExtensions,\n },\n };\n },\n configureServer(server) {\n let files = new Set(configurationFiles(root).map((file) => resolve(file)));\n // Watch the parent of an absent file. Registering a missing path\n // directly can narrow Chokidar's directory filter and lose additions.\n const watch = () =>\n server.watcher.add([...files].map((file) => (existsSync(file) ? file : dirname(file))));\n watch();\n let update: ReturnType<typeof setTimeout> | undefined;\n const changed = (filename: string) => {\n if (files.has(resolve(filename))) {\n clearTimeout(update);\n // Chokidar throttles rapid changes for 50 ms. Read after that\n // window so consecutive saves use the final contents, and a\n // correction after an error overlay produces another event.\n update = setTimeout(() => {\n try {\n config = { ...loadConfig(root), ...options };\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n server.config.logger.error(error.message);\n server.ws.send({\n type: 'error',\n err: { message: error.message, stack: error.stack ?? '', plugin: 'twill' },\n });\n return;\n }\n files = new Set(configurationFiles(root).map((file) => resolve(file)));\n watch();\n if (server.environments)\n for (const environment of Object.values(server.environments))\n environment.moduleGraph.invalidateAll();\n else server.moduleGraph.invalidateAll();\n server.ws.send({ type: 'full-reload' });\n }, 75);\n }\n };\n server.watcher.on('change', changed).on('add', changed).on('unlink', changed);\n server.httpServer?.once('close', () => clearTimeout(update));\n // Chokidar removes listeners when the watcher closes. HTTP can close\n // and reopen independently of the watcher during server setup.\n },\n },\n resolveId(id, importer) {\n if (options.resolveExtensions === false || (!id.startsWith('.') && !isAbsolute(id)))\n return null;\n const [path, query] = splitId(id);\n const base = isAbsolute(path!)\n ? path!\n : resolve(importer ? dirname(splitId(importer)[0]) : root, path!);\n const candidate = resolveSourceFile(base);\n if (!candidate || candidate === base) return null;\n if (meta.framework === 'esbuild' && !isTwillFile(candidate)) return null;\n return candidate + query;\n },\n transformInclude(id) {\n const filename = splitId(id)[0];\n return (\n !isDependency(filename) &&\n (isTwillFile(filename) || (nativeSources && needsTypeEmission(filename)))\n );\n },\n transform(source, id) {\n const filename = splitId(id)[0];\n if (isDependency(filename)) return null;\n const dialect = isTwillFile(filename);\n if (!dialect && !(nativeSources && needsTypeEmission(filename))) return null;\n // Vite's dev import analysis treats addWatchFile as a browser import.\n // Watch config with the server instead; a missing optional config\n // must never become an unresolved browser module.\n if (!servingVite) for (const file of configFiles) this.addWatchFile(file);\n try {\n if (configError !== undefined) throw configError;\n return dialect\n ? transpile(source, { ...config, filename })\n : transpileNative(source, filename, undefined, undefined, config.jsxImportSource);\n } catch (cause) {\n if (meta.framework !== 'esbuild') throw cause;\n // Throwing from esbuild's onLoad discards its watchFiles. Report a\n // failed build while returning dependency metadata for recovery.\n this.error(cause instanceof Error ? cause : String(cause));\n return { code: ';', map: null };\n }\n },\n };\n },\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugin-DDOHhv7Z.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import { dirname, isAbsolute, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { createUnplugin } from 'unplugin';\nimport { isTwillFile, type TransformOptions } from './compiler.js';\nimport { loadConfig, configurationFiles } from './config.js';\nimport { transpile, transpileNative } from './transpile.js';\nimport {\n isDependency,\n needsTypeEmission,\n splitId,\n resolveSourceFile,\n sourceExtensions,\n} from './files.js';\n\nexport interface PluginOptions extends Omit<TransformOptions, 'filename' | 'language'> {\n root?: string;\n /** Resolve relative extensionless native/Twill sources. Defaults to true. */\n resolveExtensions?: boolean;\n /** Native TS/JSX emission: defaults off for Vite/esbuild, on for Rollup/webpack/rspack. */\n nativeSources?: boolean;\n}\n\nexport const twillPlugin = createUnplugin<PluginOptions | undefined, false>(\n (options = {}, meta) => {\n let root = options.root ?? process.cwd();\n let config = { ...loadConfig(root), ...options };\n let configFiles = configurationFiles(root);\n let configError: unknown;\n let servingVite = false;\n // Reuse native host emission where it already exists.\n const nativeSources = options.nativeSources ?? !['vite', 'esbuild'].includes(meta.framework);\n return {\n name: 'twill',\n enforce: 'pre',\n buildStart() {\n // Refresh once per build, including incremental contexts. Vite dev\n // uses its server watcher to report errors and invalidate the graph.\n if (!servingVite) {\n configError = undefined;\n try {\n config = { ...loadConfig(root), ...options };\n configFiles = configurationFiles(root);\n } catch (cause) {\n // Report through transformed modules, retaining their watch\n // dependencies. A fatal make/start error can stop host watching.\n configError = cause;\n }\n }\n },\n webpack(compiler) {\n if (nativeSources)\n compiler.options.module.rules.push({\n include: (file) => !isDependency(file) && needsTypeEmission(file),\n // Twill already emits JS. Webpack's automatic TS stripper rejects\n // .tsx by extension even when a loader has lowered all JSX.\n parser: { typescript: false },\n });\n },\n esbuild: {\n setup(build) {\n // unplugin tags its resolved files with a custom namespace. Native\n // dependencies of those files must re-enter esbuild's normal resolver.\n build.onResolve({ filter: /.*/, namespace: 'twill' }, (args) =>\n build.resolve(args.path, {\n resolveDir: dirname(args.importer),\n kind: args.kind,\n }),\n );\n },\n },\n vite: {\n configResolved(viteConfig) {\n root = options.root ?? viteConfig.root;\n config = { ...loadConfig(root), ...options };\n servingVite = viteConfig.command === 'serve';\n },\n config() {\n return {\n resolve: {\n extensions: sourceExtensions,\n },\n };\n },\n configureServer(server) {\n let files = new Set(configurationFiles(root).map((file) => resolve(file)));\n // Watch the parent of an absent file. Registering a missing path\n // directly can narrow Chokidar's directory filter and lose additions.\n const watch = () =>\n server.watcher.add([...files].map((file) => (existsSync(file) ? file : dirname(file))));\n watch();\n let update: ReturnType<typeof setTimeout> | undefined;\n const changed = (filename: string) => {\n if (files.has(resolve(filename))) {\n clearTimeout(update);\n // Chokidar throttles rapid changes for 50 ms. Read after that\n // window so consecutive saves use the final contents, and a\n // correction after an error overlay produces another event.\n update = setTimeout(() => {\n try {\n config = { ...loadConfig(root), ...options };\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n server.config.logger.error(error.message);\n server.ws.send({\n type: 'error',\n err: { message: error.message, stack: error.stack ?? '', plugin: 'twill' },\n });\n return;\n }\n files = new Set(configurationFiles(root).map((file) => resolve(file)));\n watch();\n if (server.environments)\n for (const environment of Object.values(server.environments))\n environment.moduleGraph.invalidateAll();\n else server.moduleGraph.invalidateAll();\n server.ws.send({ type: 'full-reload' });\n }, 75);\n }\n };\n server.watcher.on('change', changed).on('add', changed).on('unlink', changed);\n server.httpServer?.once('close', () => clearTimeout(update));\n // Chokidar removes listeners when the watcher closes. HTTP can close\n // and reopen independently of the watcher during server setup.\n },\n },\n resolveId(id, importer) {\n if (options.resolveExtensions === false || (!id.startsWith('.') && !isAbsolute(id)))\n return null;\n const [path, query] = splitId(id);\n const base = isAbsolute(path!)\n ? path!\n : resolve(importer ? dirname(splitId(importer)[0]) : root, path!);\n const candidate = resolveSourceFile(base);\n if (!candidate || candidate === base) return null;\n if (meta.framework === 'esbuild' && !isTwillFile(candidate)) return null;\n return candidate + query;\n },\n transformInclude(id) {\n const filename = splitId(id)[0];\n return (\n !isDependency(filename) &&\n (isTwillFile(filename) || (nativeSources && needsTypeEmission(filename)))\n );\n },\n transform(source, id) {\n const filename = splitId(id)[0];\n if (isDependency(filename)) return null;\n const dialect = isTwillFile(filename);\n if (!dialect && !(nativeSources && needsTypeEmission(filename))) return null;\n // Vite's dev import analysis treats addWatchFile as a browser import.\n // Watch config with the server instead; a missing optional config\n // must never become an unresolved browser module.\n if (!servingVite) for (const file of configFiles) this.addWatchFile(file);\n try {\n if (configError !== undefined) throw configError;\n return dialect\n ? transpile(source, { ...config, filename })\n : transpileNative(source, filename, undefined, undefined, config.jsxImportSource);\n } catch (cause) {\n if (meta.framework !== 'esbuild') throw cause;\n // Throwing from esbuild's onLoad discards its watchFiles. Report a\n // failed build while returning dependency metadata for recovery.\n this.error(cause instanceof Error ? cause : String(cause));\n return { code: ';', map: null };\n }\n },\n };\n },\n);\n"],"mappings":";;;;;;;;AAsBA,IAAa,cAAc,gBACxB,UAAU,CAAC,GAAG,SAAS;CACtB,IAAI,OAAO,QAAQ,QAAQ,QAAQ,IAAI;CACvC,IAAI,SAAS;EAAE,GAAG,WAAW,IAAI;EAAG,GAAG;CAAQ;CAC/C,IAAI,cAAc,mBAAmB,IAAI;CACzC,IAAI;CACJ,IAAI,cAAc;CAElB,MAAM,gBAAgB,QAAQ,iBAAiB,CAAC,CAAC,QAAQ,SAAS,CAAC,CAAC,SAAS,KAAK,SAAS;CAC3F,OAAO;EACL,MAAM;EACN,SAAS;EACT,aAAa;GAGX,IAAI,CAAC,aAAa;IAChB,cAAc,KAAA;IACd,IAAI;KACF,SAAS;MAAE,GAAG,WAAW,IAAI;MAAG,GAAG;KAAQ;KAC3C,cAAc,mBAAmB,IAAI;IACvC,SAAS,OAAO;KAGd,cAAc;IAChB;GACF;EACF;EACA,QAAQ,UAAU;GAChB,IAAI,eACF,SAAS,QAAQ,OAAO,MAAM,KAAK;IACjC,UAAU,SAAS,CAAC,aAAa,IAAI,KAAK,kBAAkB,IAAI;IAGhE,QAAQ,EAAE,YAAY,MAAM;GAC9B,CAAC;EACL;EACA,SAAS,EACP,MAAM,OAAO;GAGX,MAAM,UAAU;IAAE,QAAQ;IAAM,WAAW;GAAQ,IAAI,SACrD,MAAM,QAAQ,KAAK,MAAM;IACvB,YAAY,QAAQ,KAAK,QAAQ;IACjC,MAAM,KAAK;GACb,CAAC,CACH;EACF,EACF;EACA,MAAM;GACJ,eAAe,YAAY;IACzB,OAAO,QAAQ,QAAQ,WAAW;IAClC,SAAS;KAAE,GAAG,WAAW,IAAI;KAAG,GAAG;IAAQ;IAC3C,cAAc,WAAW,YAAY;GACvC;GACA,SAAS;IACP,OAAO,EACL,SAAS,EACP,YAAY,iBACd,EACF;GACF;GACA,gBAAgB,QAAQ;IACtB,IAAI,QAAQ,IAAI,IAAI,mBAAmB,IAAI,CAAC,CAAC,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC;IAGzE,MAAM,cACJ,OAAO,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,SAAU,WAAW,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAE,CAAC;IACxF,MAAM;IACN,IAAI;IACJ,MAAM,WAAW,aAAqB;KACpC,IAAI,MAAM,IAAI,QAAQ,QAAQ,CAAC,GAAG;MAChC,aAAa,MAAM;MAInB,SAAS,iBAAiB;OACxB,IAAI;QACF,SAAS;SAAE,GAAG,WAAW,IAAI;SAAG,GAAG;QAAQ;OAC7C,SAAS,OAAO;QACd,MAAM,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;QACtE,OAAO,OAAO,OAAO,MAAM,MAAM,OAAO;QACxC,OAAO,GAAG,KAAK;SACb,MAAM;SACN,KAAK;UAAE,SAAS,MAAM;UAAS,OAAO,MAAM,SAAS;UAAI,QAAQ;SAAQ;QAC3E,CAAC;QACD;OACF;OACA,QAAQ,IAAI,IAAI,mBAAmB,IAAI,CAAC,CAAC,KAAK,SAAS,QAAQ,IAAI,CAAC,CAAC;OACrE,MAAM;OACN,IAAI,OAAO,cACT,KAAK,MAAM,eAAe,OAAO,OAAO,OAAO,YAAY,GACzD,YAAY,YAAY,cAAc;YACrC,OAAO,YAAY,cAAc;OACtC,OAAO,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC;MACxC,GAAG,EAAE;KACP;IACF;IACA,OAAO,QAAQ,GAAG,UAAU,OAAO,CAAC,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,GAAG,UAAU,OAAO;IAC5E,OAAO,YAAY,KAAK,eAAe,aAAa,MAAM,CAAC;GAG7D;EACF;EACA,UAAU,IAAI,UAAU;GACtB,IAAI,QAAQ,sBAAsB,SAAU,CAAC,GAAG,WAAW,GAAG,KAAK,CAAC,WAAW,EAAE,GAC/E,OAAO;GACT,MAAM,CAAC,MAAM,SAAS,QAAQ,EAAE;GAChC,MAAM,OAAO,WAAW,IAAK,IACzB,OACA,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,CAAC,CAAC,EAAE,IAAI,MAAM,IAAK;GAClE,MAAM,YAAY,kBAAkB,IAAI;GACxC,IAAI,CAAC,aAAa,cAAc,MAAM,OAAO;GAC7C,IAAI,KAAK,cAAc,aAAa,CAAC,YAAY,SAAS,GAAG,OAAO;GACpE,OAAO,YAAY;EACrB;EACA,iBAAiB,IAAI;GACnB,MAAM,WAAW,QAAQ,EAAE,CAAC,CAAC;GAC7B,OACE,CAAC,aAAa,QAAQ,MACrB,YAAY,QAAQ,KAAM,iBAAiB,kBAAkB,QAAQ;EAE1E;EACA,UAAU,QAAQ,IAAI;GACpB,MAAM,WAAW,QAAQ,EAAE,CAAC,CAAC;GAC7B,IAAI,aAAa,QAAQ,GAAG,OAAO;GACnC,MAAM,UAAU,YAAY,QAAQ;GACpC,IAAI,CAAC,WAAW,EAAE,iBAAiB,kBAAkB,QAAQ,IAAI,OAAO;GAIxE,IAAI,CAAC,aAAa,KAAK,MAAM,QAAQ,aAAa,KAAK,aAAa,IAAI;GACxE,IAAI;IACF,IAAI,gBAAgB,KAAA,GAAW,MAAM;IACrC,OAAO,UACH,UAAU,QAAQ;KAAE,GAAG;KAAQ;IAAS,CAAC,IACzC,gBAAgB,QAAQ,UAAU,KAAA,GAAW,KAAA,GAAW,OAAO,eAAe;GACpF,SAAS,OAAO;IACd,IAAI,KAAK,cAAc,WAAW,MAAM;IAGxC,KAAK,MAAM,iBAAiB,QAAQ,QAAQ,OAAO,KAAK,CAAC;IACzD,OAAO;KAAE,MAAM;KAAK,KAAK;IAAK;GAChC;EACF;CACF;AACF,CACF"}
@@ -1,12 +1,12 @@
1
- import { a as transform, i as originalPosition, n as generatedPosition, r as inferLanguage, t as TwillSyntaxError } from "./compiler-BdkU4Ruh.js";
2
- import { n as isTwillFile, t as extensions } from "./extensions-B1xTkoYP.js";
3
- import { n as loadConfig } from "./configuration-BVMf6Q_j.js";
4
- import { t as isDependency } from "./files-BW9geU0_.js";
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
+ import { n as loadConfig } from "./configuration-ppqhmuy4.js";
4
+ import { t as isDependency } from "./files-CgwJJ992.js";
5
5
  import MagicString from "magic-string";
6
6
  import { dirname, resolve } from "node:path";
7
7
  import ts from "typescript";
8
8
  import remapping from "@ampproject/remapping";
9
- //#region src/recovery.ts
9
+ // src/recovery.ts
10
10
  /** Editor-only recovery; build and CLI compilation always use strict parsing. */
11
11
  function recoverTransform(source, options, onSyntaxError) {
12
12
  const repaired = new MagicString(source);
@@ -85,8 +85,7 @@ function recoverTransform(source, options, onSyntaxError) {
85
85
  }
86
86
  return transform(source, options);
87
87
  }
88
- //#endregion
89
- //#region src/project.ts
88
+ // src/project.ts
90
89
  function lineStarts(text) {
91
90
  const starts = [0];
92
91
  const breaks = /\n/g;
@@ -438,7 +437,6 @@ var TwillProject = class {
438
437
  this.service.dispose();
439
438
  }
440
439
  };
441
- //#endregion
442
440
  export { sourceFilename as n, virtualFilename as r, TwillProject as t };
443
441
 
444
- //# sourceMappingURL=project-ZmlpFooa.js.map
442
+ //# sourceMappingURL=project-DYXf2Kgt.js.map