@marko/language-server 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -15,17 +15,31 @@ import {
15
15
  } from "vscode-languageserver/node";
16
16
 
17
17
  // src/utils/project.ts
18
+ import path from "path";
18
19
  import * as defaultCompiler from "@marko/compiler";
19
20
  import * as defaultTranslator from "@marko/translator-default";
20
- import lassoPackageRoot from "lasso-package-root";
21
21
  import resolveFrom from "resolve-from";
22
- var cwd = process.cwd();
23
- var kTaglib = Symbol("taglib");
22
+ var ignoreErrors = (_err) => {
23
+ };
24
24
  var projectsByDir = /* @__PURE__ */ new Map();
25
+ var projectsByCompiler = /* @__PURE__ */ new Map();
25
26
  var defaultProject = {
26
- rootDir: cwd,
27
27
  cache: /* @__PURE__ */ new Map(),
28
- lookup: defaultCompiler.taglib.buildLookup(cwd, defaultTranslator),
28
+ getLookup(dir) {
29
+ const key = `taglib:${dir}`;
30
+ let lookup = defaultProject.cache.get(key);
31
+ if (!lookup) {
32
+ defaultProject.cache.set(
33
+ key,
34
+ lookup = defaultCompiler.taglib.buildLookup(
35
+ dir,
36
+ defaultTranslator,
37
+ ignoreErrors
38
+ )
39
+ );
40
+ }
41
+ return lookup;
42
+ },
29
43
  compiler: defaultCompiler,
30
44
  translator: defaultTranslator
31
45
  };
@@ -41,55 +55,119 @@ function getMarkoProject(dir) {
41
55
  return project;
42
56
  }
43
57
  function getMarkoProjects() {
44
- return new Set(projectsByDir.values());
58
+ return projectsByCompiler.values();
59
+ }
60
+ function clearMarkoProjectCaches() {
61
+ for (const project of getMarkoProjects()) {
62
+ project.cache.clear();
63
+ project.compiler.taglib.clearCaches();
64
+ }
45
65
  }
46
66
  function loadProject(dir) {
47
- const rootDir = lassoPackageRoot.getRootDir(dir) || cwd;
48
- const pkgPath = resolveFrom.silent(rootDir, "@marko/compiler/package.json");
49
- const pkg = pkgPath && __require(pkgPath);
50
- const cache = /* @__PURE__ */ new Map();
51
- let translator = defaultTranslator;
52
- let compiler = defaultCompiler;
53
- if (pkg && /^5\./.test(pkg.version)) {
54
- try {
55
- let checkTranslator = [].concat(
56
- Object.keys(pkg.dependencies),
57
- Object.keys(pkg.peerDependencies),
58
- Object.keys(pkg.devDependencies)
59
- ).find((name) => /^marko$|^(@\/marko\/|marko-)translator-/.test(name));
60
- if (checkTranslator === "marko" || !checkTranslator) {
61
- checkTranslator = __require(resolveFrom(dir, "@marko/compiler/config")).translator;
67
+ try {
68
+ const compilerConfigPath = resolveFrom(dir, "@marko/compiler/config");
69
+ const cachedProject = projectsByCompiler.get(compilerConfigPath);
70
+ if (cachedProject)
71
+ return cachedProject;
72
+ const [compiler, translator] = [
73
+ __require(path.join(compilerConfigPath, "..")),
74
+ __require(resolveFrom(
75
+ dir,
76
+ interopDefault(__require(compilerConfigPath)).translator
77
+ ))
78
+ ];
79
+ const project = {
80
+ cache: /* @__PURE__ */ new Map(),
81
+ getLookup(dir2) {
82
+ const key = `taglib:${dir2}`;
83
+ let lookup = project.cache.get(key);
84
+ if (lookup === void 0) {
85
+ try {
86
+ lookup = compiler.taglib.buildLookup(dir2, translator, ignoreErrors);
87
+ } catch {
88
+ lookup = defaultProject.getLookup(dir2);
89
+ }
90
+ project.cache.set(key, lookup);
91
+ }
92
+ return lookup;
93
+ },
94
+ compiler,
95
+ translator
96
+ };
97
+ projectsByCompiler.set(compilerConfigPath, project);
98
+ return project;
99
+ } catch {
100
+ return defaultProject;
101
+ }
102
+ }
103
+ function interopDefault(mod) {
104
+ return mod.default || mod;
105
+ }
106
+
107
+ // src/utils/file.ts
108
+ import path2 from "path";
109
+ import { parse } from "@marko/language-tools";
110
+ import { URI } from "vscode-uri";
111
+ var processorCaches = /* @__PURE__ */ new WeakMap();
112
+ function getFSPath(doc) {
113
+ return URI.parse(doc.uri).fsPath;
114
+ }
115
+ function getMarkoFile(doc) {
116
+ const { uri } = doc;
117
+ const { fsPath: filename, scheme } = URI.parse(uri);
118
+ const dirname = filename && path2.dirname(filename);
119
+ const project = getMarkoProject(dirname);
120
+ const cache = project.cache;
121
+ let file = cache.get(doc);
122
+ if (!file) {
123
+ const { version } = doc;
124
+ const code = doc.getText();
125
+ const parsed = parse(code, filename);
126
+ const lookup = project.getLookup(dirname);
127
+ cache.set(
128
+ doc,
129
+ file = {
130
+ project,
131
+ uri,
132
+ scheme,
133
+ version,
134
+ lookup,
135
+ filename,
136
+ dirname,
137
+ parsed,
138
+ code
62
139
  }
63
- [compiler, translator] = [
64
- __require(resolveFrom(dir, "@marko/compiler")),
65
- __require(resolveFrom(dir, checkTranslator))
66
- ];
67
- } catch {
140
+ );
141
+ }
142
+ return file;
143
+ }
144
+ function clearMarkoCacheForFile(doc) {
145
+ const { fsPath: filename } = URI.parse(doc.uri);
146
+ const dirname = filename && path2.dirname(filename);
147
+ const project = getMarkoProject(dirname);
148
+ const cache = project.cache;
149
+ cache.delete(doc);
150
+ }
151
+ function processDoc(doc, process2) {
152
+ const file = getMarkoFile(doc);
153
+ const cache = processorCaches.get(file.parsed);
154
+ let result;
155
+ if (cache) {
156
+ result = cache.get(process2);
157
+ if (!result) {
158
+ result = process2(file);
159
+ cache.set(process2, result);
68
160
  }
161
+ } else {
162
+ result = process2(file);
163
+ processorCaches.set(file.parsed, /* @__PURE__ */ new Map([[process2, result]]));
69
164
  }
70
- return {
71
- rootDir,
72
- cache,
73
- get lookup() {
74
- let lookup = cache.get(kTaglib);
75
- if (lookup === void 0) {
76
- try {
77
- lookup = compiler.taglib.buildLookup(dir, translator);
78
- } catch {
79
- lookup = defaultProject.lookup;
80
- }
81
- cache.set(kTaglib, lookup);
82
- }
83
- return lookup;
84
- },
85
- compiler,
86
- translator
87
- };
165
+ return result;
88
166
  }
89
167
 
90
168
  // src/utils/text-documents.ts
91
169
  import fs from "fs";
92
- import { URI } from "vscode-uri";
170
+ import { URI as URI2 } from "vscode-uri";
93
171
  import { FileChangeType } from "vscode-languageserver";
94
172
  import { TextDocument } from "vscode-languageserver-textdocument";
95
173
  var docs = /* @__PURE__ */ new Map();
@@ -107,7 +185,7 @@ function get(uri) {
107
185
  const doc = docs.get(uri);
108
186
  if (doc)
109
187
  return doc;
110
- const { fsPath, scheme } = URI.parse(uri);
188
+ const { fsPath, scheme } = URI2.parse(uri);
111
189
  if (scheme === "file") {
112
190
  if (fileExists.get(uri) === false)
113
191
  return void 0;
@@ -130,7 +208,7 @@ function exists(uri) {
130
208
  const cached = fileExists.get(uri);
131
209
  if (cached !== void 0)
132
210
  return cached;
133
- const { fsPath, scheme } = URI.parse(uri);
211
+ const { fsPath, scheme } = URI2.parse(uri);
134
212
  if (scheme === "file") {
135
213
  try {
136
214
  fs.accessSync(fsPath);
@@ -184,7 +262,7 @@ function setup(connection4) {
184
262
  if (doc) {
185
263
  projectVersion++;
186
264
  openDocs.delete(doc);
187
- if (URI.parse(ref.uri).scheme !== "file") {
265
+ if (URI2.parse(ref.uri).scheme !== "file") {
188
266
  docs.delete(ref.uri);
189
267
  }
190
268
  }
@@ -287,62 +365,6 @@ function display(type, data) {
287
365
  setImmediate(() => connection2.sendNotification(type, msg));
288
366
  }
289
367
 
290
- // src/utils/file.ts
291
- import path from "path";
292
- import { parse } from "@marko/language-tools";
293
- import { URI as URI2 } from "vscode-uri";
294
- var processorCaches = /* @__PURE__ */ new WeakMap();
295
- function getFSDir(doc) {
296
- const filename = getFSPath(doc);
297
- return filename ? path.dirname(filename) : void 0;
298
- }
299
- function getFSPath(doc) {
300
- return URI2.parse(doc.uri).fsPath;
301
- }
302
- function getMarkoFile(doc) {
303
- const { uri } = doc;
304
- const { fsPath: filename, scheme } = URI2.parse(uri);
305
- const dirname = filename && path.dirname(filename);
306
- const project = getMarkoProject(dirname);
307
- const cache = project.cache;
308
- let file = cache.get(doc);
309
- if (!file) {
310
- const { version } = doc;
311
- const code = doc.getText();
312
- const parsed = parse(code, filename);
313
- cache.set(
314
- doc,
315
- file = {
316
- project,
317
- uri,
318
- scheme,
319
- version,
320
- filename,
321
- dirname,
322
- parsed,
323
- code
324
- }
325
- );
326
- }
327
- return file;
328
- }
329
- function processDoc(doc, process2) {
330
- const file = getMarkoFile(doc);
331
- const cache = processorCaches.get(file.parsed);
332
- let result;
333
- if (cache) {
334
- result = cache.get(process2);
335
- if (!result) {
336
- result = process2(file);
337
- cache.set(process2, result);
338
- }
339
- } else {
340
- result = process2(file);
341
- processorCaches.set(file.parsed, /* @__PURE__ */ new Map([[process2, result]]));
342
- }
343
- return result;
344
- }
345
-
346
368
  // src/service/index.ts
347
369
  import { MarkupContent, MarkupKind as MarkupKind3 } from "vscode-languageserver";
348
370
 
@@ -359,10 +381,7 @@ import {
359
381
  function AttrName({
360
382
  offset,
361
383
  node,
362
- file: {
363
- parsed,
364
- project: { lookup }
365
- }
384
+ file: { parsed, lookup }
366
385
  }) {
367
386
  let name = parsed.read(node);
368
387
  const modifierIndex = name.indexOf(":");
@@ -459,7 +478,7 @@ function isExternalModule(file) {
459
478
  }
460
479
 
461
480
  // src/service/marko/complete/AttrValue.ts
462
- import path2 from "path";
481
+ import path3 from "path";
463
482
  import {
464
483
  CompletionItemKind as CompletionItemKind2,
465
484
  TextEdit as TextEdit2
@@ -572,7 +591,7 @@ async function AttrValue({
572
591
  const resolved = resolveUrl(req, uri);
573
592
  if (resolved) {
574
593
  const result = [];
575
- const curFile = req === "." ? path2.basename(uri) : void 0;
594
+ const curFile = req === "." ? path3.basename(uri) : void 0;
576
595
  const replaceRange = parsed.locationAt({
577
596
  start: start + segmentStart + 1,
578
597
  end: start + rawValue.length
@@ -605,7 +624,7 @@ async function AttrValue({
605
624
  import { TextEdit as TextEdit4 } from "vscode-languageserver";
606
625
 
607
626
  // src/service/marko/util/get-tag-name-completion.ts
608
- import path3 from "path";
627
+ import path4 from "path";
609
628
  import {
610
629
  CompletionItemKind as CompletionItemKind3,
611
630
  CompletionItemTag,
@@ -634,7 +653,7 @@ function getTagNameCompletion({
634
653
  kind: MarkupKind2.Markdown,
635
654
  value: tag.html ? `Built in [<${tag.name}>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${tag.name}) HTML tag.` : isCoreTag ? `Core Marko <${tag.name}> tag.` : nodeModuleName ? `Custom Marko tag discovered from the ["${nodeModuleName}"](${fileURIForTag}) npm package.` : `Custom Marko tag discovered from:
636
655
 
637
- [${importer ? path3.relative(importer, fileForTag) : fileForTag}](${fileURIForTag})`
656
+ [${importer ? path4.relative(importer, fileForTag) : fileForTag}](${fileURIForTag})`
638
657
  };
639
658
  if (tag.description) {
640
659
  documentation.value += `
@@ -671,11 +690,7 @@ ${autocomplete.description}`;
671
690
  var importTagReg = /(['"])<((?:[^\1\\>]+|\\.)*)>?\1/;
672
691
  function Import({
673
692
  node,
674
- file: {
675
- parsed,
676
- filename,
677
- project: { lookup }
678
- }
693
+ file: { parsed, filename, lookup }
679
694
  }) {
680
695
  var _a;
681
696
  const value = parsed.read(node);
@@ -707,11 +722,7 @@ function Import({
707
722
  import { NodeType as NodeType2 } from "@marko/language-tools";
708
723
  function OpenTagName({
709
724
  node,
710
- file: {
711
- parsed,
712
- filename,
713
- project: { lookup }
714
- }
725
+ file: { parsed, filename, lookup }
715
726
  }) {
716
727
  var _a;
717
728
  const tag = node.parent;
@@ -832,14 +843,14 @@ var doComplete = async (doc, params) => {
832
843
  };
833
844
 
834
845
  // src/service/marko/validate.ts
835
- import path4 from "path";
846
+ import path5 from "path";
836
847
  import { DiagnosticSeverity } from "vscode-languageserver";
837
848
  var markoErrorRegExp = /^(.+?)\.marko(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
838
849
  var doValidate = (doc) => {
839
850
  const filename = getFSPath(doc);
840
851
  const diagnostics = [];
841
852
  const { compiler, translator, cache } = getMarkoProject(
842
- filename && path4.dirname(filename)
853
+ filename && path5.dirname(filename)
843
854
  );
844
855
  try {
845
856
  compiler.compileSync(doc.getText(), filename || "untitled.marko", {
@@ -895,11 +906,7 @@ var START_LOCATION = {
895
906
  // src/service/marko/hover/OpenTagName.ts
896
907
  function OpenTagName2({
897
908
  node,
898
- file: {
899
- parsed,
900
- filename,
901
- project: { lookup }
902
- }
909
+ file: { parsed, filename, lookup }
903
910
  }) {
904
911
  const tag = node.parent;
905
912
  const range = parsed.locationAt(node);
@@ -971,10 +978,7 @@ function escape(val) {
971
978
  // src/service/marko/definition/AttrName.ts
972
979
  function AttrName2({
973
980
  node,
974
- file: {
975
- parsed,
976
- project: { lookup }
977
- }
981
+ file: { parsed, lookup }
978
982
  }) {
979
983
  const tagName = node.parent.parent.nameText;
980
984
  const attrName = parsed.read(node);
@@ -1013,7 +1017,7 @@ function AttrName2({
1013
1017
 
1014
1018
  // src/service/marko/definition/OpenTagName.ts
1015
1019
  import fs4 from "fs";
1016
- import path5 from "path";
1020
+ import path6 from "path";
1017
1021
  import { URI as URI5 } from "vscode-uri";
1018
1022
  import {
1019
1023
  NodeType as NodeType5,
@@ -1022,10 +1026,7 @@ import {
1022
1026
  } from "@marko/language-tools";
1023
1027
  function OpenTagName3({
1024
1028
  node,
1025
- file: {
1026
- parsed,
1027
- project: { lookup }
1028
- }
1029
+ file: { parsed, lookup }
1029
1030
  }) {
1030
1031
  const tag = node.parent;
1031
1032
  let tagDef;
@@ -1042,7 +1043,7 @@ function OpenTagName3({
1042
1043
  return;
1043
1044
  }
1044
1045
  const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
1045
- if (!path5.isAbsolute(tagEntryFile)) {
1046
+ if (!path6.isAbsolute(tagEntryFile)) {
1046
1047
  return;
1047
1048
  }
1048
1049
  if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
@@ -1097,7 +1098,7 @@ function extractDocumentLinks({
1097
1098
  scheme,
1098
1099
  parsed,
1099
1100
  code,
1100
- project: { lookup }
1101
+ lookup
1101
1102
  }) {
1102
1103
  if (scheme !== "file") {
1103
1104
  return [];
@@ -1173,7 +1174,7 @@ function extractDocumentSymbols({
1173
1174
  uri,
1174
1175
  scheme,
1175
1176
  parsed,
1176
- project: { lookup }
1177
+ lookup
1177
1178
  }) {
1178
1179
  if (scheme !== "file") {
1179
1180
  return [];
@@ -1254,7 +1255,7 @@ var marko_default = {
1254
1255
  };
1255
1256
 
1256
1257
  // src/service/script/index.ts
1257
- import path9 from "path";
1258
+ import path10 from "path";
1258
1259
  import { relativeImportPath } from "relative-import-path";
1259
1260
  import ts from "typescript/lib/tsserverlibrary";
1260
1261
  import {
@@ -1267,12 +1268,13 @@ import {
1267
1268
  import { URI as URI6 } from "vscode-uri";
1268
1269
  import * as prettier2 from "prettier";
1269
1270
  import {
1271
+ NodeType as NodeType9,
1270
1272
  ScriptLang as ScriptLang3,
1271
1273
  extractScript as extractScript2
1272
1274
  } from "@marko/language-tools";
1273
1275
 
1274
1276
  // src/ts-plugin/host.ts
1275
- import path8 from "path";
1277
+ import path9 from "path";
1276
1278
  import {
1277
1279
  ScriptLang as ScriptLang2,
1278
1280
  extractScript,
@@ -1280,15 +1282,15 @@ import {
1280
1282
  } from "@marko/language-tools";
1281
1283
 
1282
1284
  // src/utils/get-runtime-types.ts
1283
- import path6 from "path";
1284
- var internalTypesFile = path6.join(__dirname, "marko.internal.d.ts");
1285
- var defaultMarkoTypesFile = path6.join(__dirname, "marko.runtime.d.ts");
1285
+ import path7 from "path";
1286
+ var internalTypesFile = path7.join(__dirname, "marko.internal.d.ts");
1287
+ var defaultMarkoTypesFile = path7.join(__dirname, "marko.runtime.d.ts");
1286
1288
  function getProjectTypeLibs(project, ts2, host) {
1287
1289
  let cached = project.cache.get(getProjectTypeLibs);
1288
1290
  if (cached === void 0) {
1289
1291
  const { resolvedTypeReferenceDirective } = ts2.resolveTypeReferenceDirective(
1290
1292
  project.translator.runtimeTypes || "marko",
1291
- path6.join(project.rootDir, "_.d.ts"),
1293
+ path7.join(host.getCurrentDirectory(), "_.d.ts"),
1292
1294
  host.getCompilationSettings(),
1293
1295
  host
1294
1296
  );
@@ -1327,21 +1329,19 @@ function getScriptLang(filename, ts2, host, projectScriptLang) {
1327
1329
  }
1328
1330
 
1329
1331
  // src/utils/get-component-filename.ts
1330
- import path7 from "path";
1331
- function getComponentFilename(from, host) {
1332
- const dir = path7.dirname(from);
1333
- const nameNoExt = path7.basename(from, ".marko");
1332
+ import fs5 from "fs";
1333
+ import path8 from "path";
1334
+ function getComponentFilename(from) {
1335
+ const dir = path8.dirname(from);
1336
+ const nameNoExt = path8.basename(from, ".marko");
1334
1337
  const isEntry = nameNoExt === "index";
1335
- const componentFull = path7.join(dir, `${nameNoExt}.component.`);
1336
- const componentBrowserFull = path7.join(
1337
- dir,
1338
- `${nameNoExt}.component-browser.`
1339
- );
1340
- const componentPartial = isEntry ? path7.join(dir, "component.") : void 0;
1341
- const componentBrowserPartial = isEntry ? path7.join(dir, "component-browser.") : void 0;
1342
- for (const entry of host.readDirectory(dir)) {
1338
+ const componentFull = `${nameNoExt}.component.`;
1339
+ const componentBrowserFull = `${nameNoExt}.component-browser.`;
1340
+ const componentPartial = isEntry ? "component." : void 0;
1341
+ const componentBrowserPartial = isEntry ? "component-browser." : void 0;
1342
+ for (const entry of fs5.readdirSync(dir)) {
1343
1343
  if (entry !== from && (isEntry && entry.startsWith(componentBrowserPartial) || entry.startsWith(componentPartial)) || entry.startsWith(componentBrowserFull) || entry.startsWith(componentFull)) {
1344
- return entry;
1344
+ return path8.join(dir, entry);
1345
1345
  }
1346
1346
  }
1347
1347
  }
@@ -1379,14 +1379,15 @@ function patch(ts2, scriptLang, cache, host) {
1379
1379
  let cached = cache.get(filename);
1380
1380
  if (!cached) {
1381
1381
  const code = host.readFile(filename, "utf-8") || "";
1382
- const markoProject = getMarkoProject(path8.dirname(filename));
1382
+ const dir = path9.dirname(filename);
1383
+ const markoProject = getMarkoProject(dir);
1383
1384
  cached = extractScript({
1384
1385
  ts: ts2,
1385
1386
  parsed: parse2(code, filename),
1386
- lookup: markoProject.lookup,
1387
+ lookup: markoProject.getLookup(dir),
1387
1388
  scriptLang: getScriptLang(filename, ts2, host, scriptLang),
1388
1389
  runtimeTypesCode: projectTypeLibs.markoTypesCode,
1389
- componentFilename: getComponentFilename(filename, host)
1390
+ componentFilename: getComponentFilename(filename)
1390
1391
  });
1391
1392
  cached.snapshot = ts2.ScriptSnapshot.fromString(cached.toString());
1392
1393
  cache.set(filename, cached);
@@ -1395,11 +1396,20 @@ function patch(ts2, scriptLang, cache, host) {
1395
1396
  }
1396
1397
  return getScriptSnapshot(filename);
1397
1398
  };
1399
+ if (host.getProjectVersion) {
1400
+ const getScriptVersion = host.getScriptVersion.bind(host);
1401
+ host.getScriptVersion = (filename) => {
1402
+ if (markoExtReg.test(filename)) {
1403
+ return host.getProjectVersion();
1404
+ }
1405
+ return getScriptVersion(filename);
1406
+ };
1407
+ }
1398
1408
  const readDirectory2 = (_b = host.readDirectory) == null ? void 0 : _b.bind(host);
1399
1409
  if (readDirectory2) {
1400
- host.readDirectory = (path10, extensions, exclude, include, depth) => {
1410
+ host.readDirectory = (path11, extensions, exclude, include, depth) => {
1401
1411
  return readDirectory2(
1402
- path10,
1412
+ path11,
1403
1413
  extensions == null ? void 0 : extensions.concat(markoExt),
1404
1414
  exclude,
1405
1415
  include,
@@ -1410,31 +1420,16 @@ function patch(ts2, scriptLang, cache, host) {
1410
1420
  const resolveModuleNames = (_c = host.resolveModuleNames) == null ? void 0 : _c.bind(host);
1411
1421
  if (resolveModuleNames) {
1412
1422
  host.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, options, sourceFile) => {
1413
- const resolvedModules = resolveModuleNames(
1414
- moduleNames,
1415
- containingFile,
1416
- reusedNames,
1417
- redirectedReference,
1418
- options,
1419
- sourceFile
1420
- );
1421
- for (let i = resolvedModules.length; i--; ) {
1423
+ let normalModuleNames = moduleNames;
1424
+ let resolvedModules;
1425
+ for (let i = 0; i < moduleNames.length; i++) {
1422
1426
  const moduleName = moduleNames[i];
1423
- if (!resolvedModules[i] && markoExtReg.test(moduleName)) {
1427
+ const shouldProcess = moduleName[0] !== "*" ? markoExtReg.test(moduleName) : void 0;
1428
+ if (shouldProcess) {
1429
+ let resolvedFileName;
1424
1430
  if (fsPathReg.test(moduleName)) {
1425
- const resolvedFileName = path8.resolve(
1426
- containingFile,
1427
- "..",
1428
- moduleName
1429
- );
1430
- if (host.fileExists(resolvedFileName)) {
1431
- resolvedModules[i] = {
1432
- resolvedFileName,
1433
- extension: isMarkoTSFile(resolvedFileName) ? ts2.Extension.Ts : ts2.Extension.Js,
1434
- isExternalLibraryImport: false
1435
- };
1436
- }
1437
- } else if (moduleName[0] !== "*") {
1431
+ resolvedFileName = path9.resolve(containingFile, "..", moduleName);
1432
+ } else {
1438
1433
  const [, nodeModuleName, relativeModulePath] = modulePartsReg.exec(moduleName);
1439
1434
  const { resolvedModule } = ts2.resolveModuleName(
1440
1435
  `${nodeModuleName}/package.json`,
@@ -1443,24 +1438,63 @@ function patch(ts2, scriptLang, cache, host) {
1443
1438
  host
1444
1439
  );
1445
1440
  if (resolvedModule) {
1446
- const resolvedFileName = path8.join(
1441
+ resolvedFileName = path9.join(
1447
1442
  resolvedModule.resolvedFileName,
1448
1443
  "..",
1449
1444
  relativeModulePath
1450
1445
  );
1451
- if (host.fileExists(resolvedFileName)) {
1452
- const isTS = isMarkoTSFile(resolvedFileName);
1453
- resolvedModules[i] = {
1454
- resolvedFileName,
1455
- extension: isTS ? ts2.Extension.Ts : ts2.Extension.Js,
1456
- isExternalLibraryImport: isTS
1457
- };
1458
- }
1446
+ }
1447
+ }
1448
+ if (!resolvedModules) {
1449
+ resolvedModules = [];
1450
+ normalModuleNames = [];
1451
+ for (let j = 0; j < i; j++) {
1452
+ resolvedModules.push(void 0);
1453
+ normalModuleNames.push(moduleNames[j]);
1454
+ }
1455
+ }
1456
+ resolvedModules.push(
1457
+ resolvedFileName && host.fileExists(resolvedFileName) ? {
1458
+ resolvedFileName,
1459
+ extension: isMarkoTSFile(resolvedFileName) ? ts2.Extension.Ts : ts2.Extension.Js,
1460
+ isExternalLibraryImport: false
1461
+ } : null
1462
+ );
1463
+ } else if (resolvedModules) {
1464
+ resolvedModules.push(void 0);
1465
+ }
1466
+ }
1467
+ const normalResolvedModules = normalModuleNames.length ? resolveModuleNames(
1468
+ normalModuleNames,
1469
+ containingFile,
1470
+ reusedNames,
1471
+ redirectedReference,
1472
+ options,
1473
+ sourceFile
1474
+ ) : void 0;
1475
+ if (resolvedModules) {
1476
+ if (normalResolvedModules) {
1477
+ for (let i = 0, j = 0; i < resolvedModules.length; i++) {
1478
+ switch (resolvedModules[i]) {
1479
+ case void 0:
1480
+ resolvedModules[i] = normalResolvedModules[j++];
1481
+ break;
1482
+ case null:
1483
+ resolvedModules[i] = void 0;
1484
+ break;
1485
+ }
1486
+ }
1487
+ } else {
1488
+ for (let i = resolvedModules.length; i--; ) {
1489
+ if (resolvedModules[i] === null) {
1490
+ resolvedModules[i] = void 0;
1459
1491
  }
1460
1492
  }
1461
1493
  }
1494
+ return resolvedModules;
1495
+ } else {
1496
+ return normalResolvedModules;
1462
1497
  }
1463
- return resolvedModules;
1464
1498
  };
1465
1499
  }
1466
1500
  return host;
@@ -1470,6 +1504,7 @@ function patch(ts2, scriptLang, cache, host) {
1470
1504
  var IGNORE_DIAG_REG = /^(?:Expression|Identifier|['"][^\w]['"]) expected.$/;
1471
1505
  var extractCache = /* @__PURE__ */ new Map();
1472
1506
  var snapshotCache = /* @__PURE__ */ new Map();
1507
+ var insertModuleStatementLocCache = /* @__PURE__ */ new WeakMap();
1473
1508
  var markoFileReg = /\.marko$/;
1474
1509
  var tsTriggerChars = /* @__PURE__ */ new Set([".", '"', "'", "`", "/", "@", "<", "#", " "]);
1475
1510
  var optionalModifierReg = /\boptional\b/;
@@ -1560,7 +1595,7 @@ var ScriptService = {
1560
1595
  let source = completion.source;
1561
1596
  if (source && completion.hasAction) {
1562
1597
  if (source[0] === ".") {
1563
- source = path9.resolve(fileName, "..", source);
1598
+ source = path10.resolve(fileName, "..", source);
1564
1599
  }
1565
1600
  detail = relativeImportPath(fileName, source);
1566
1601
  sortText = `\uFFFF${sortText}`;
@@ -1650,18 +1685,29 @@ var ScriptService = {
1650
1685
  for (const change of action.changes) {
1651
1686
  if (change.fileName !== fileName)
1652
1687
  continue;
1653
- for (const { span, newText } of change.textChanges) {
1654
- const sourceRange = /^\s*(?:import|export) /.test(newText) ? (
1655
- // Ensure import inserts are always in the program root.
1656
- // TODO: this could probably be updated to more closely reflect
1657
- // where typescript wants to put the import/export.
1658
- START_LOCATION
1659
- ) : sourceLocationAtTextSpan(extracted, span);
1660
- if (sourceRange) {
1661
- textEdits.push({
1662
- newText,
1663
- range: sourceRange
1664
- });
1688
+ for (const { span, newText: rawText } of change.textChanges) {
1689
+ let range;
1690
+ let newText = rawText;
1691
+ if (span.length === 0 && /^\s*(?:import|export) /.test(newText)) {
1692
+ const cached = insertModuleStatementLocCache.get(extracted);
1693
+ newText = newText.replace(/\n\s*$/, "\n");
1694
+ if (cached) {
1695
+ range = cached;
1696
+ } else {
1697
+ const { parsed } = getMarkoFile(doc);
1698
+ const offset = getInsertModuleStatementOffset(parsed);
1699
+ const start = parsed.positionAt(offset);
1700
+ range = {
1701
+ start,
1702
+ end: start
1703
+ };
1704
+ insertModuleStatementLocCache.set(extracted, range);
1705
+ }
1706
+ } else {
1707
+ range = sourceLocationAtTextSpan(extracted, span);
1708
+ }
1709
+ if (range) {
1710
+ textEdits.push({ newText, range });
1665
1711
  }
1666
1712
  }
1667
1713
  }
@@ -1853,19 +1899,57 @@ ${documentation}`;
1853
1899
  }
1854
1900
  };
1855
1901
  function processScript(doc, tsProject) {
1856
- return processDoc(doc, ({ parsed, filename, project: markoProject }) => {
1857
- var _a;
1858
- const { lookup } = markoProject;
1859
- const { host, markoScriptLang } = tsProject;
1860
- return extractScript2({
1861
- ts,
1862
- parsed,
1863
- lookup,
1864
- scriptLang: getScriptLang(filename, ts, host, markoScriptLang),
1865
- runtimeTypesCode: (_a = getProjectTypeLibs(markoProject, ts, host)) == null ? void 0 : _a.markoTypesCode,
1866
- componentFilename: getComponentFilename(filename, host)
1867
- });
1868
- });
1902
+ return processDoc(
1903
+ doc,
1904
+ ({ filename, parsed, lookup, project: markoProject }) => {
1905
+ var _a;
1906
+ const { host, markoScriptLang } = tsProject;
1907
+ return extractScript2({
1908
+ ts,
1909
+ parsed,
1910
+ lookup,
1911
+ scriptLang: getScriptLang(filename, ts, host, markoScriptLang),
1912
+ runtimeTypesCode: (_a = getProjectTypeLibs(markoProject, ts, host)) == null ? void 0 : _a.markoTypesCode,
1913
+ componentFilename: getComponentFilename(filename)
1914
+ });
1915
+ }
1916
+ );
1917
+ }
1918
+ function getInsertModuleStatementOffset(parsed) {
1919
+ const { program } = parsed;
1920
+ let firstNode;
1921
+ if (program.static.length) {
1922
+ let lastImport;
1923
+ for (const node of program.static) {
1924
+ switch (node.type) {
1925
+ case NodeType9.Export:
1926
+ return node.start;
1927
+ case NodeType9.Import:
1928
+ lastImport = node;
1929
+ break;
1930
+ }
1931
+ }
1932
+ if (lastImport) {
1933
+ return lastImport.end + 1;
1934
+ }
1935
+ firstNode = program.static[0];
1936
+ }
1937
+ if (program.body.length) {
1938
+ if (!firstNode || firstNode.start > program.body[0].start) {
1939
+ firstNode = program.body[0];
1940
+ }
1941
+ }
1942
+ if (firstNode) {
1943
+ return getOffsetAfterComments(firstNode);
1944
+ }
1945
+ return 0;
1946
+ }
1947
+ function getOffsetAfterComments(node) {
1948
+ const { comments } = node;
1949
+ if (comments) {
1950
+ return comments.at(-1).end + 1;
1951
+ }
1952
+ return Math.max(0, node.start - 1);
1869
1953
  }
1870
1954
  function sourceLocationAtTextSpan(extracted, { start, length }) {
1871
1955
  if (start === 0 && length === 0)
@@ -1898,7 +1982,7 @@ function getTSProject(docFsPath) {
1898
1982
  );
1899
1983
  }
1900
1984
  }
1901
- const rootDir = configPath && path9.dirname(configPath) || process.cwd();
1985
+ const rootDir = configPath && path10.dirname(configPath) || process.cwd();
1902
1986
  const markoProject = getMarkoProject(configPath && rootDir);
1903
1987
  let projectCache = markoProject.cache.get(getTSProject);
1904
1988
  let cached;
@@ -1912,7 +1996,8 @@ function getTSProject(docFsPath) {
1912
1996
  }
1913
1997
  const { fileNames, options, projectReferences } = ts.parseJsonConfigFileContent(
1914
1998
  configPath && ts.readConfigFile(configPath, ts.sys.readFile).config || {
1915
- compilerOptions: { lib: ["dom", "node", "esnext"] }
1999
+ compilerOptions: { lib: ["dom", "node", "esnext"] },
2000
+ include: []
1916
2001
  },
1917
2002
  ts.sys,
1918
2003
  rootDir,
@@ -1933,10 +2018,11 @@ function getTSProject(docFsPath) {
1933
2018
  options.rootDir ??= rootDir;
1934
2019
  options.module = ts.ModuleKind.ESNext;
1935
2020
  options.moduleResolution = ts.ModuleResolutionKind.NodeJs;
1936
- options.noEmit = options.allowJs = options.declaration = options.skipLibCheck = options.isolatedModules = options.resolveJsonModule = options.skipDefaultLibCheck = options.allowNonTsExtensions = true;
2021
+ options.declaration = false;
2022
+ options.noEmit = options.allowJs = options.skipLibCheck = options.isolatedModules = options.resolveJsonModule = options.skipDefaultLibCheck = options.allowNonTsExtensions = true;
1937
2023
  const tsPkgFile = configPath && ((_a = ts.resolveModuleName("typescript/package.json", configPath, options, ts.sys).resolvedModule) == null ? void 0 : _a.resolvedFileName);
1938
- const defaultLibFile = path9.join(
1939
- tsPkgFile ? path9.join(tsPkgFile, "../lib") : __dirname,
2024
+ const defaultLibFile = path10.join(
2025
+ tsPkgFile ? path10.join(tsPkgFile, "../lib") : __dirname,
1940
2026
  ts.getDefaultLibFileName(options)
1941
2027
  );
1942
2028
  const host = patch(
@@ -1990,12 +2076,16 @@ function getTSProject(docFsPath) {
1990
2076
  return `${((_a2 = get(filenameToURI(filename))) == null ? void 0 : _a2.version) ?? -1}`;
1991
2077
  },
1992
2078
  getScriptKind(filename) {
1993
- switch (path9.extname(filename)) {
2079
+ switch (path10.extname(filename)) {
1994
2080
  case ts.Extension.Js:
2081
+ case ts.Extension.Cjs:
2082
+ case ts.Extension.Mjs:
1995
2083
  return ts.ScriptKind.JS;
1996
2084
  case ts.Extension.Jsx:
1997
2085
  return ts.ScriptKind.JSX;
1998
2086
  case ts.Extension.Ts:
2087
+ case ts.Extension.Cts:
2088
+ case ts.Extension.Mts:
1999
2089
  return ts.ScriptKind.TS;
2000
2090
  case ts.Extension.Tsx:
2001
2091
  return ts.ScriptKind.TSX;
@@ -2497,7 +2587,7 @@ var StyleSheetService = {
2497
2587
  }
2498
2588
  };
2499
2589
  function processStyle(doc) {
2500
- return processDoc(doc, ({ uri, version, parsed, project: { lookup } }) => {
2590
+ return processDoc(doc, ({ uri, version, parsed, lookup }) => {
2501
2591
  var _a;
2502
2592
  const result = [];
2503
2593
  for (const [ext, extracted] of extractStyle({
@@ -2975,7 +3065,7 @@ setup(connection3);
2975
3065
  onFileChange((changeDoc) => {
2976
3066
  if (changeDoc) {
2977
3067
  queueDiagnostic();
2978
- getMarkoProject(getFSDir(changeDoc)).cache.delete(changeDoc);
3068
+ clearMarkoCacheForFile(changeDoc);
2979
3069
  } else {
2980
3070
  validateDocs();
2981
3071
  }
@@ -3072,10 +3162,7 @@ for (const command in service.commands) {
3072
3162
  }
3073
3163
  function validateDocs() {
3074
3164
  queueDiagnostic();
3075
- for (const project of getMarkoProjects()) {
3076
- project.cache.clear();
3077
- project.compiler.taglib.clearCaches();
3078
- }
3165
+ clearMarkoProjectCaches();
3079
3166
  }
3080
3167
  function queueDiagnostic() {
3081
3168
  clearTimeout(diagnosticTimeout);