@marko/language-server 0.12.17 → 1.0.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 (38) hide show
  1. package/dist/index.js +2021 -1565
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.mjs +2055 -1594
  4. package/dist/index.mjs.map +4 -4
  5. package/dist/service/marko/complete/AttrName.d.ts +2 -2
  6. package/dist/service/marko/complete/AttrValue.d.ts +2 -2
  7. package/dist/service/marko/complete/Import.d.ts +3 -0
  8. package/dist/service/marko/complete/OpenTagName.d.ts +2 -2
  9. package/dist/service/marko/complete/Tag.d.ts +2 -2
  10. package/dist/service/marko/complete/index.d.ts +5 -8
  11. package/dist/service/marko/definition/AttrName.d.ts +2 -2
  12. package/dist/service/marko/definition/OpenTagName.d.ts +2 -2
  13. package/dist/service/marko/definition/index.d.ts +5 -8
  14. package/dist/service/marko/hover/OpenTagName.d.ts +2 -2
  15. package/dist/service/marko/hover/index.d.ts +5 -8
  16. package/dist/service/marko/util/is-document-link-attr.d.ts +2 -3
  17. package/dist/service/script/index.d.ts +3 -0
  18. package/dist/service/types.d.ts +6 -4
  19. package/dist/ts-plugin/host.d.ts +5 -0
  20. package/dist/ts-plugin/index.d.ts +5 -0
  21. package/dist/utils/constants.d.ts +3 -0
  22. package/dist/utils/file.d.ts +21 -0
  23. package/dist/utils/get-component-filename.d.ts +2 -0
  24. package/dist/utils/get-runtime-types.d.ts +8 -0
  25. package/dist/utils/get-script-lang.d.ts +4 -0
  26. package/dist/utils/project.d.ts +11 -0
  27. package/dist/utils/text-documents.d.ts +10 -0
  28. package/dist/utils/workspace.d.ts +5 -0
  29. package/package.json +20 -16
  30. package/dist/service/marko/complete/Statement.d.ts +0 -3
  31. package/dist/service/stylesheet/extract.d.ts +0 -10
  32. package/dist/utils/compiler.d.ts +0 -21
  33. package/dist/utils/doc-file.d.ts +0 -3
  34. package/dist/utils/extractor.d.ts +0 -12
  35. package/dist/utils/get-node-at-offset.d.ts +0 -2
  36. package/dist/utils/parser.d.ts +0 -176
  37. package/dist/utils/utils.d.ts +0 -4
  38. /package/dist/service/{stylesheet → style}/index.d.ts +0 -0
package/dist/index.mjs CHANGED
@@ -7,578 +7,49 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
  });
8
8
 
9
9
  // src/index.ts
10
+ import { inspect as inspect2, isDeepStrictEqual } from "util";
10
11
  import {
11
- createConnection,
12
12
  ProposedFeatures,
13
- TextDocuments,
14
- TextDocumentSyncKind
13
+ TextDocumentSyncKind,
14
+ createConnection
15
15
  } from "vscode-languageserver/node";
16
- import { TextDocument as TextDocument3 } from "vscode-languageserver-textdocument";
17
- import { inspect as inspect2, isDeepStrictEqual } from "util";
18
16
 
19
- // src/utils/compiler.ts
20
- import resolveFrom from "resolve-from";
17
+ // src/utils/project.ts
18
+ import * as defaultCompiler from "@marko/compiler";
19
+ import * as defaultTranslator from "@marko/translator-default";
21
20
  import lassoPackageRoot from "lasso-package-root";
22
- import * as builtinCompiler from "@marko/compiler";
23
- import * as builtinTranslator from "@marko/translator-default";
24
-
25
- // src/utils/doc-file.ts
26
- import path from "path";
27
- import { URI } from "vscode-uri";
28
- function getDocDir(doc) {
29
- const filename = getDocFile(doc);
30
- return filename ? path.dirname(filename) : void 0;
31
- }
32
- function getDocFile(doc) {
33
- return URI.parse(doc.uri).fsPath;
34
- }
35
-
36
- // src/utils/parser.ts
37
- import { createParser, TagType, Range, Ranges } from "htmljs-parser";
38
-
39
- // src/utils/get-node-at-offset.ts
40
- function getNodeAtOffset(offset, program) {
41
- const bodyNode = childAtOffset(offset, program.body);
42
- if (bodyNode)
43
- return visitChildNode(offset, bodyNode);
44
- return childAtOffset(offset, program.static) || program;
45
- }
46
- function visitChildNode(offset, child) {
47
- switch (child.type) {
48
- case 1 /* Tag */:
49
- case 14 /* AttrTag */:
50
- return visitTag(offset, child);
51
- default:
52
- return child;
53
- }
54
- }
55
- function visitTag(offset, tag) {
56
- const { body } = tag;
57
- if (body && offset > tag.open.end) {
58
- const childNode = childAtOffset(offset, body);
59
- return childNode ? visitChildNode(offset, childNode) : tag;
60
- }
61
- const { attrs } = tag;
62
- if (attrs && offset > attrs[0].start) {
63
- const attrNode = childAtOffset(offset, attrs);
64
- return attrNode ? visitAttrNode(offset, attrNode) : tag;
65
- }
66
- const { var: tagVar } = tag;
67
- if (tagVar && offset > tagVar.start && offset <= tagVar.end) {
68
- return tagVar;
69
- }
70
- const { args } = tag;
71
- if (args && offset > args.start && offset <= args.end) {
72
- return args;
73
- }
74
- const { params } = tag;
75
- if (params && offset > params.start && offset <= params.end) {
76
- return params;
77
- }
78
- const { name } = tag;
79
- if (name && offset <= name.end) {
80
- return name;
81
- }
82
- return tag;
83
- }
84
- function visitAttrNode(offset, attr) {
85
- switch (attr.type) {
86
- case 14 /* AttrTag */:
87
- return visitTag(offset, attr);
88
- case 8 /* AttrNamed */: {
89
- const { value } = attr;
90
- if (value && offset > value.start) {
91
- return value;
92
- }
93
- const { name } = attr;
94
- if (offset > name.start && offset <= name.end) {
95
- return name;
96
- }
97
- break;
98
- }
99
- }
100
- return attr;
101
- }
102
- function childAtOffset(offset, children) {
103
- let max = children.length - 1;
104
- if (max === -1)
105
- return void 0;
106
- let min = 0;
107
- while (min < max) {
108
- const mid = 1 + min + max >>> 1;
109
- if (children[mid].start < offset) {
110
- min = mid;
111
- } else {
112
- max = mid - 1;
113
- }
114
- }
115
- const child = children[min];
116
- return offset > child.start && offset <= child.end ? child : void 0;
117
- }
118
-
119
- // src/utils/parser.ts
120
- var UNFINISHED = Number.MAX_SAFE_INTEGER;
121
- var NodeType = /* @__PURE__ */ ((NodeType2) => {
122
- NodeType2[NodeType2["Program"] = 0] = "Program";
123
- NodeType2[NodeType2["Tag"] = 1] = "Tag";
124
- NodeType2[NodeType2["OpenTagName"] = 2] = "OpenTagName";
125
- NodeType2[NodeType2["ShorthandId"] = 3] = "ShorthandId";
126
- NodeType2[NodeType2["ShorthandClassName"] = 4] = "ShorthandClassName";
127
- NodeType2[NodeType2["TagVar"] = 5] = "TagVar";
128
- NodeType2[NodeType2["TagArgs"] = 6] = "TagArgs";
129
- NodeType2[NodeType2["TagParams"] = 7] = "TagParams";
130
- NodeType2[NodeType2["AttrNamed"] = 8] = "AttrNamed";
131
- NodeType2[NodeType2["AttrName"] = 9] = "AttrName";
132
- NodeType2[NodeType2["AttrArgs"] = 10] = "AttrArgs";
133
- NodeType2[NodeType2["AttrValue"] = 11] = "AttrValue";
134
- NodeType2[NodeType2["AttrMethod"] = 12] = "AttrMethod";
135
- NodeType2[NodeType2["AttrSpread"] = 13] = "AttrSpread";
136
- NodeType2[NodeType2["AttrTag"] = 14] = "AttrTag";
137
- NodeType2[NodeType2["Text"] = 15] = "Text";
138
- NodeType2[NodeType2["CDATA"] = 16] = "CDATA";
139
- NodeType2[NodeType2["Doctype"] = 17] = "Doctype";
140
- NodeType2[NodeType2["Declaration"] = 18] = "Declaration";
141
- NodeType2[NodeType2["Comment"] = 19] = "Comment";
142
- NodeType2[NodeType2["Statement"] = 20] = "Statement";
143
- NodeType2[NodeType2["Placeholder"] = 21] = "Placeholder";
144
- NodeType2[NodeType2["Scriptlet"] = 22] = "Scriptlet";
145
- return NodeType2;
146
- })(NodeType || {});
147
- function parse(source) {
148
- const program = {
149
- type: 0 /* Program */,
150
- parent: void 0,
151
- static: [],
152
- body: [],
153
- start: 0,
154
- end: source.length
155
- };
156
- let curBodyType;
157
- let curOpenTagStart;
158
- let curParent = program;
159
- let curAttr = void 0;
160
- let curBody = program.body;
161
- const parser = createParser({
162
- onText(range) {
163
- curBody.push({
164
- type: 15 /* Text */,
165
- parent: curParent,
166
- start: range.start,
167
- end: range.end
168
- });
169
- },
170
- onCDATA(range) {
171
- curBody.push({
172
- type: 16 /* CDATA */,
173
- parent: curParent,
174
- value: range.value,
175
- start: range.start,
176
- end: range.end
177
- });
178
- },
179
- onDoctype(range) {
180
- curBody.push({
181
- type: 17 /* Doctype */,
182
- parent: curParent,
183
- value: range.value,
184
- start: range.start,
185
- end: range.end
186
- });
187
- },
188
- onDeclaration(range) {
189
- curBody.push({
190
- type: 18 /* Declaration */,
191
- parent: curParent,
192
- value: range.value,
193
- start: range.start,
194
- end: range.end
195
- });
196
- },
197
- onComment(range) {
198
- curBody.push({
199
- type: 19 /* Comment */,
200
- parent: curParent,
201
- value: range.value,
202
- start: range.start,
203
- end: range.end
204
- });
205
- },
206
- onPlaceholder(range) {
207
- curBody.push({
208
- type: 21 /* Placeholder */,
209
- parent: curParent,
210
- value: range.value,
211
- escape: range.escape,
212
- start: range.start,
213
- end: range.end
214
- });
215
- },
216
- onScriptlet(range) {
217
- curBody.push({
218
- type: 22 /* Scriptlet */,
219
- parent: curParent,
220
- value: range.value,
221
- block: range.block,
222
- start: range.start,
223
- end: range.end
224
- });
225
- },
226
- onOpenTagStart(range) {
227
- curOpenTagStart = range;
228
- },
229
- onOpenTagName(range) {
230
- let concise = true;
231
- let start = range.start;
232
- let type = 1 /* Tag */;
233
- let nameText = void 0;
234
- if (curOpenTagStart) {
235
- concise = false;
236
- start = curOpenTagStart.start;
237
- curOpenTagStart = void 0;
238
- }
239
- if (range.expressions.length) {
240
- curBodyType = TagType.html;
241
- } else {
242
- switch (nameText = parser.read(range)) {
243
- case "area":
244
- case "base":
245
- case "br":
246
- case "col":
247
- case "embed":
248
- case "hr":
249
- case "img":
250
- case "input":
251
- case "link":
252
- case "meta":
253
- case "param":
254
- case "source":
255
- case "track":
256
- case "wbr":
257
- curBodyType = TagType.void;
258
- break;
259
- case "html-comment":
260
- case "script":
261
- case "style":
262
- case "textarea":
263
- curBodyType = TagType.text;
264
- break;
265
- case "class":
266
- case "export":
267
- case "import":
268
- case "static": {
269
- let i = program.body.length;
270
- for (; i--; ) {
271
- const prev = program.body[i];
272
- if (prev.type === 19 /* Comment */) {
273
- program.static.push(prev);
274
- } else {
275
- break;
276
- }
277
- }
278
- program.body.length = i + 1;
279
- program.static.push(
280
- curParent = {
281
- type: 20 /* Statement */,
282
- parent: program,
283
- start: range.start,
284
- end: UNFINISHED
285
- }
286
- );
287
- return curBodyType = TagType.statement;
288
- }
289
- default:
290
- if (nameText[0] === "@") {
291
- type = 14 /* AttrTag */;
292
- }
293
- curBodyType = TagType.html;
294
- break;
295
- }
296
- }
297
- const parent = curParent;
298
- const end = UNFINISHED;
299
- const name = {
300
- type: 2 /* OpenTagName */,
301
- parent: void 0,
302
- quasis: range.quasis,
303
- expressions: range.expressions,
304
- start: range.start,
305
- end: range.end
306
- };
307
- const tag = curParent = name.parent = {
308
- type,
309
- parent,
310
- owner: void 0,
311
- concise,
312
- open: { start, end },
313
- nameText,
314
- name,
315
- var: void 0,
316
- args: void 0,
317
- params: void 0,
318
- shorthandId: void 0,
319
- shorthandClassNames: void 0,
320
- attrs: void 0,
321
- selfClosed: false,
322
- bodyType: curBodyType,
323
- body: void 0,
324
- close: void 0,
325
- start,
326
- end
327
- };
328
- if (tag.type === 14 /* AttrTag */) {
329
- let owner = parent;
330
- outer:
331
- do {
332
- switch (owner.type) {
333
- case 14 /* AttrTag */:
334
- break;
335
- case 1 /* Tag */:
336
- if (isTransparentTag(owner)) {
337
- owner = owner.parent;
338
- continue outer;
339
- }
340
- break;
341
- default:
342
- break outer;
343
- }
344
- tag.owner = owner;
345
- tag.nameText = resolveAttrTagName(tag);
346
- pushAttr(owner, tag);
347
- } while (false);
348
- }
349
- curBody.push(tag);
350
- curOpenTagStart = void 0;
351
- return curBodyType;
352
- },
353
- onTagShorthandId(range) {
354
- curParent.shorthandId = {
355
- type: 3 /* ShorthandId */,
356
- parent: curParent,
357
- quasis: range.quasis,
358
- expressions: range.expressions,
359
- start: range.start,
360
- end: range.end
361
- };
362
- },
363
- onTagShorthandClass(range) {
364
- const shorthandClassName = {
365
- type: 4 /* ShorthandClassName */,
366
- parent: curParent,
367
- quasis: range.quasis,
368
- expressions: range.expressions,
369
- start: range.start,
370
- end: range.end
371
- };
372
- if (curParent.shorthandClassNames) {
373
- curParent.shorthandClassNames.push(shorthandClassName);
374
- } else {
375
- curParent.shorthandClassNames = [shorthandClassName];
376
- }
377
- },
378
- onTagVar(range) {
379
- curParent.var = {
380
- type: 5 /* TagVar */,
381
- parent: curParent,
382
- value: range.value,
383
- start: range.start,
384
- end: range.end
385
- };
386
- },
387
- onTagParams(range) {
388
- curParent.params = {
389
- type: 7 /* TagParams */,
390
- parent: curParent,
391
- value: range.value,
392
- start: range.start,
393
- end: range.end
394
- };
395
- },
396
- onTagArgs(range) {
397
- curParent.args = {
398
- type: 6 /* TagArgs */,
399
- parent: curParent,
400
- value: range.value,
401
- start: range.start,
402
- end: range.end
403
- };
404
- },
405
- onAttrName(range) {
406
- const parent = curParent;
407
- const name = {
408
- type: 9 /* AttrName */,
409
- parent: void 0,
410
- start: range.start,
411
- end: range.end
412
- };
413
- pushAttr(
414
- parent,
415
- curAttr = name.parent = {
416
- type: 8 /* AttrNamed */,
417
- parent,
418
- name,
419
- value: void 0,
420
- args: void 0,
421
- start: range.start,
422
- end: range.end
423
- }
424
- );
425
- },
426
- onAttrArgs(range) {
427
- curAttr.args = {
428
- type: 10 /* AttrArgs */,
429
- parent: curAttr,
430
- value: range.value,
431
- start: range.start,
432
- end: range.end
433
- };
434
- },
435
- onAttrValue(range) {
436
- curAttr.value = {
437
- type: 11 /* AttrValue */,
438
- parent: curAttr,
439
- value: range.value,
440
- bound: range.bound,
441
- start: range.start,
442
- end: range.end
443
- };
444
- curAttr.end = range.end;
445
- },
446
- onAttrMethod(range) {
447
- curAttr.value = {
448
- type: 12 /* AttrMethod */,
449
- parent: curAttr,
450
- params: range.params,
451
- body: range.body,
452
- start: range.start,
453
- end: range.end
454
- };
455
- curAttr.end = range.end;
456
- },
457
- onAttrSpread(range) {
458
- pushAttr(curParent, {
459
- type: 13 /* AttrSpread */,
460
- parent: curParent,
461
- value: range.value,
462
- start: range.start,
463
- end: range.end
464
- });
465
- },
466
- onOpenTagEnd(range) {
467
- curAttr = void 0;
468
- if (curBodyType === TagType.statement) {
469
- curParent.end = range.end;
470
- curParent = curParent.parent;
471
- } else {
472
- const tag = curParent;
473
- tag.open.end = range.end;
474
- if (range.selfClosed || curBodyType === TagType.void) {
475
- curParent = tag.parent;
476
- tag.selfClosed = range.selfClosed;
477
- tag.end = range.end;
478
- } else {
479
- curBody = tag.body = [];
480
- }
481
- }
482
- },
483
- onCloseTagStart(range) {
484
- curParent.close = {
485
- start: range.start,
486
- end: Number.MAX_SAFE_INTEGER
487
- };
488
- },
489
- onCloseTagEnd(range) {
490
- if (hasCloseTag(curParent))
491
- curParent.close.end = range.end;
492
- curParent.end = range.end;
493
- curBody = (curParent = curParent.parent).body;
494
- }
495
- });
496
- parser.parse(source);
497
- return {
498
- read: parser.read,
499
- locationAt: parser.locationAt,
500
- positionAt: parser.positionAt,
501
- nodeAt: (offset) => getNodeAtOffset(offset, program),
502
- program
503
- };
504
- }
505
- function pushAttr(parent, node) {
506
- if (parent.attrs) {
507
- parent.attrs.push(node);
508
- } else {
509
- parent.attrs = [node];
510
- }
511
- }
512
- function hasCloseTag(parent) {
513
- return parent.close !== void 0;
514
- }
515
- function resolveAttrTagName(tag) {
516
- let name = tag.nameText;
517
- let parentTag = tag.owner;
518
- do {
519
- switch (parentTag.type) {
520
- case 1 /* Tag */:
521
- return parentTag.nameText ? `${parentTag.nameText}:${name}` : void 0;
522
- case 14 /* AttrTag */:
523
- name = `${parentTag.nameText}:${name}`;
524
- parentTag = parentTag.owner;
525
- break;
526
- default:
527
- return;
528
- }
529
- } while (parentTag);
530
- }
531
- function isTransparentTag(node) {
532
- return node.nameText !== void 0 && /^(?:if|else(?:-if)?|for|while)$/.test(node.nameText);
533
- }
534
-
535
- // src/utils/compiler.ts
536
- var lookupKey = Symbol("lookup");
537
- var compilerInfoByDir = /* @__PURE__ */ new Map();
538
- var builtinInfo = {
21
+ import resolveFrom from "resolve-from";
22
+ var cwd = process.cwd();
23
+ var kTaglib = Symbol("taglib");
24
+ var projectsByDir = /* @__PURE__ */ new Map();
25
+ var defaultProject = {
26
+ rootDir: cwd,
539
27
  cache: /* @__PURE__ */ new Map(),
540
- lookup: builtinCompiler.taglib.buildLookup(__dirname, builtinTranslator),
541
- compiler: builtinCompiler,
542
- translator: builtinTranslator
28
+ lookup: defaultCompiler.taglib.buildLookup(cwd, defaultTranslator),
29
+ compiler: defaultCompiler,
30
+ translator: defaultTranslator
543
31
  };
544
- builtinCompiler.configure({ translator: builtinTranslator });
545
- function parse2(doc) {
546
- const compilerInfo = getCompilerInfo(doc);
547
- let parsed = compilerInfo.cache.get(doc);
548
- if (!parsed) {
549
- const source = doc.getText();
550
- compilerInfo.cache.set(doc, parsed = parse(source));
551
- }
552
- return parsed;
553
- }
554
- function getCompilerInfo(doc) {
555
- const dir = getDocDir(doc);
32
+ defaultCompiler.configure({ translator: defaultTranslator });
33
+ function getMarkoProject(dir) {
556
34
  if (!dir)
557
- return builtinInfo;
558
- let info = compilerInfoByDir.get(dir);
559
- if (!info) {
560
- info = loadCompilerInfo(dir);
561
- compilerInfoByDir.set(dir, info);
35
+ return defaultProject;
36
+ let project = projectsByDir.get(dir);
37
+ if (!project) {
38
+ project = loadProject(dir);
39
+ projectsByDir.set(dir, project);
562
40
  }
563
- return info;
41
+ return project;
564
42
  }
565
- function clearCompilerCache(doc) {
566
- if (doc) {
567
- getCompilerInfo(doc).cache.delete(doc);
568
- } else {
569
- for (const [, info] of compilerInfoByDir) {
570
- info.cache.clear();
571
- info.compiler.taglib.clearCaches();
572
- }
573
- }
43
+ function getMarkoProjects() {
44
+ return new Set(projectsByDir.values());
574
45
  }
575
- function loadCompilerInfo(dir) {
576
- const rootDir = lassoPackageRoot.getRootDir(dir);
577
- const pkgPath = rootDir && resolveFrom.silent(rootDir, "@marko/compiler/package.json");
46
+ function loadProject(dir) {
47
+ const rootDir = lassoPackageRoot.getRootDir(dir) || cwd;
48
+ const pkgPath = resolveFrom.silent(rootDir, "@marko/compiler/package.json");
578
49
  const pkg = pkgPath && __require(pkgPath);
579
- const cache4 = /* @__PURE__ */ new Map();
580
- let translator = builtinTranslator;
581
- let compiler = builtinCompiler;
50
+ const cache = /* @__PURE__ */ new Map();
51
+ let translator = defaultTranslator;
52
+ let compiler = defaultCompiler;
582
53
  if (pkg && /^5\./.test(pkg.version)) {
583
54
  try {
584
55
  let checkTranslator = [].concat(
@@ -597,16 +68,17 @@ function loadCompilerInfo(dir) {
597
68
  }
598
69
  }
599
70
  return {
600
- cache: cache4,
71
+ rootDir,
72
+ cache,
601
73
  get lookup() {
602
- let lookup = cache4.get(lookupKey);
74
+ let lookup = cache.get(kTaglib);
603
75
  if (lookup === void 0) {
604
76
  try {
605
77
  lookup = compiler.taglib.buildLookup(dir, translator);
606
78
  } catch {
607
- lookup = builtinInfo.lookup;
79
+ lookup = defaultProject.lookup;
608
80
  }
609
- cache4.set(lookupKey, lookup);
81
+ cache.set(kTaglib, lookup);
610
82
  }
611
83
  return lookup;
612
84
  },
@@ -615,208 +87,284 @@ function loadCompilerInfo(dir) {
615
87
  };
616
88
  }
617
89
 
618
- // src/utils/messages.ts
619
- import { inspect } from "util";
620
- var connection;
621
- function setup(_) {
622
- connection = _;
90
+ // src/utils/text-documents.ts
91
+ import fs from "fs";
92
+ import { URI } from "vscode-uri";
93
+ import { FileChangeType } from "vscode-languageserver";
94
+ import { TextDocument } from "vscode-languageserver-textdocument";
95
+ var docs = /* @__PURE__ */ new Map();
96
+ var openDocs = /* @__PURE__ */ new Set();
97
+ var fileExists = /* @__PURE__ */ new Map();
98
+ var fileChangeHandlers = /* @__PURE__ */ new Set();
99
+ var projectVersion = 0;
100
+ function onFileChange(handler) {
101
+ fileChangeHandlers.add(handler);
623
102
  }
624
- function displayError(data) {
625
- display("showError", data);
103
+ function getAllOpen() {
104
+ return openDocs;
626
105
  }
627
- function display(type, data) {
628
- const msg = typeof data === "string" ? data : inspect(data, { colors: false });
629
- setImmediate(() => connection.sendNotification(type, msg));
106
+ function get(uri) {
107
+ const doc = docs.get(uri);
108
+ if (doc)
109
+ return doc;
110
+ const { fsPath, scheme } = URI.parse(uri);
111
+ if (scheme === "file") {
112
+ if (fileExists.get(uri) === false)
113
+ return void 0;
114
+ try {
115
+ const newDoc = TextDocument.create(
116
+ uri,
117
+ getLanguageId(uri),
118
+ fs.statSync(fsPath).mtimeMs,
119
+ fs.readFileSync(fsPath, "utf-8")
120
+ );
121
+ docs.set(uri, newDoc);
122
+ fileExists.set(uri, true);
123
+ return newDoc;
124
+ } catch {
125
+ fileExists.set(uri, false);
126
+ }
127
+ }
630
128
  }
631
-
632
- // src/service/index.ts
633
- import {
634
- CompletionList as CompletionList3
635
- } from "vscode-languageserver";
636
-
637
- // src/service/marko/complete/index.ts
638
- import {
639
- CompletionList
640
- } from "vscode-languageserver";
641
-
642
- // src/service/marko/complete/Tag.ts
643
- import {
644
- CompletionItemKind,
645
- InsertTextFormat,
646
- TextEdit
647
- } from "vscode-languageserver";
648
- var partialCloseTagReg = /<\/(?:[^><]*>)?/iy;
649
- function Tag(event) {
650
- const { node } = event;
651
- const isClosed = node.end !== UNFINISHED;
652
- if (isClosed || node.concise)
653
- return;
654
- const { offset, parsed, code } = event;
655
- const closingTagStr = `</${node.nameText}>`;
656
- if (offset === node.open.end) {
657
- return [
658
- {
659
- label: closingTagStr,
660
- kind: CompletionItemKind.Class,
661
- insertTextFormat: InsertTextFormat.Snippet,
662
- insertText: `
663
- $0
664
- ${closingTagStr}`
129
+ function exists(uri) {
130
+ const cached = fileExists.get(uri);
131
+ if (cached !== void 0)
132
+ return cached;
133
+ const { fsPath, scheme } = URI.parse(uri);
134
+ if (scheme === "file") {
135
+ try {
136
+ fs.accessSync(fsPath);
137
+ fileExists.set(uri, true);
138
+ return true;
139
+ } catch {
140
+ fileExists.set(uri, false);
141
+ return false;
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+ function isOpen(doc) {
147
+ return openDocs.has(doc);
148
+ }
149
+ function setup(connection4) {
150
+ connection4.onDidOpenTextDocument((params) => {
151
+ const ref = params.textDocument;
152
+ const existingDoc = docs.get(ref.uri);
153
+ projectVersion++;
154
+ if (existingDoc) {
155
+ if (existingDoc.version === ref.version) {
156
+ openDocs.add(existingDoc);
157
+ return;
665
158
  }
666
- ];
667
- } else if (node.close && offset >= node.close.start) {
668
- const start = node.close.start;
669
- partialCloseTagReg.lastIndex = start;
670
- const [{ length }] = partialCloseTagReg.exec(code);
671
- const end = start + length;
672
- return [
673
- {
674
- label: closingTagStr,
675
- kind: CompletionItemKind.Class,
676
- insertTextFormat: InsertTextFormat.Snippet,
677
- textEdit: TextEdit.replace(
678
- parsed.locationAt({
679
- start,
680
- end
681
- }),
682
- closingTagStr
683
- )
159
+ openDocs.delete(existingDoc);
160
+ docs.delete(ref.uri);
161
+ }
162
+ const newDoc = TextDocument.create(
163
+ ref.uri,
164
+ ref.languageId,
165
+ ref.version,
166
+ ref.text
167
+ );
168
+ openDocs.add(newDoc);
169
+ fileExists.set(ref.uri, true);
170
+ docs.set(ref.uri, newDoc);
171
+ });
172
+ connection4.onDidChangeTextDocument((params) => {
173
+ const ref = params.textDocument;
174
+ const changes = params.contentChanges;
175
+ const doc = docs.get(ref.uri);
176
+ if (changes.length > 0 && ref.version != null && doc) {
177
+ TextDocument.update(doc, changes, ref.version);
178
+ emitFileChange(doc);
179
+ }
180
+ });
181
+ connection4.onDidCloseTextDocument((params) => {
182
+ const ref = params.textDocument;
183
+ const doc = docs.get(ref.uri);
184
+ if (doc) {
185
+ projectVersion++;
186
+ openDocs.delete(doc);
187
+ if (URI.parse(ref.uri).scheme !== "file") {
188
+ docs.delete(ref.uri);
684
189
  }
685
- ];
190
+ }
191
+ });
192
+ connection4.onDidChangeWatchedFiles(async (params) => {
193
+ for (const change of params.changes) {
194
+ switch (change.type) {
195
+ case FileChangeType.Created:
196
+ fileExists.set(change.uri, true);
197
+ break;
198
+ case FileChangeType.Deleted:
199
+ case FileChangeType.Changed: {
200
+ fileExists.set(change.uri, change.type === FileChangeType.Changed);
201
+ const doc = docs.get(change.uri);
202
+ if (doc && !openDocs.has(doc)) {
203
+ docs.delete(change.uri);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ emitFileChange(void 0);
209
+ });
210
+ }
211
+ function getLanguageId(uri) {
212
+ const ext = uri.slice(uri.lastIndexOf(".") + 1);
213
+ switch (ext) {
214
+ case "cjs":
215
+ case "mjs":
216
+ case "js":
217
+ return "javascript";
218
+ case "cts":
219
+ case "mts":
220
+ case "ts":
221
+ return "typescript";
222
+ default:
223
+ return ext;
686
224
  }
687
225
  }
688
-
689
- // src/service/marko/util/get-tag-name-completion.ts
690
- import path2 from "path";
691
- import {
692
- CompletionItemKind as CompletionItemKind2,
693
- CompletionItemTag,
694
- InsertTextFormat as InsertTextFormat2,
695
- MarkupKind,
696
- TextEdit as TextEdit2
697
- } from "vscode-languageserver";
698
- import { URI as URI2 } from "vscode-uri";
699
- var deprecated = [CompletionItemTag.Deprecated];
700
- function getTagNameCompletion({
701
- tag,
702
- range,
703
- showAutoComplete,
704
- importer
705
- }) {
706
- var _a;
707
- let label = tag.isNestedTag ? `@${tag.name}` : tag.name;
708
- const fileForTag = tag.template || tag.renderer || tag.filePath;
709
- const fileURIForTag = URI2.file(fileForTag).toString();
710
- const nodeModuleMatch = /\/node_modules\/((?:@[^/]+\/)?[^/]+)/.exec(
711
- fileForTag
712
- );
713
- const nodeModuleName = nodeModuleMatch && nodeModuleMatch[1];
714
- const isCoreTag = /^@?marko[/-]/.test(tag.taglibId) || nodeModuleName === "marko";
715
- const documentation = {
716
- kind: MarkupKind.Markdown,
717
- value: tag.html ? `Built in [&lt;${tag.name}&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${tag.name}) HTML tag.` : isCoreTag ? `Core Marko &lt;${tag.name}&gt; tag.` : nodeModuleName ? `Custom Marko tag discovered from the ["${nodeModuleName}"](${fileURIForTag}) npm package.` : `Custom Marko tag discovered from:
718
-
719
- [${importer ? path2.relative(importer, fileForTag) : fileForTag}](${fileURIForTag})`
720
- };
721
- if (tag.description) {
722
- documentation.value += `
723
-
724
- ${tag.description}`;
226
+ function emitFileChange(doc) {
227
+ projectVersion++;
228
+ for (const handler of fileChangeHandlers) {
229
+ handler(doc);
725
230
  }
726
- const autocomplete = showAutoComplete ? (_a = tag.autocomplete) == null ? void 0 : _a[0] : void 0;
727
- if (autocomplete) {
728
- if (autocomplete.displayText) {
729
- label = autocomplete.displayText;
730
- }
731
- if (autocomplete.description) {
732
- documentation.value += `
231
+ }
733
232
 
734
- ${autocomplete.description}`;
233
+ // src/utils/workspace.ts
234
+ var connection;
235
+ var configChangeHandlers = /* @__PURE__ */ new Set();
236
+ var settingsCache = /* @__PURE__ */ new Map();
237
+ async function getConfig(section) {
238
+ let cached = settingsCache.get(section);
239
+ if (!cached) {
240
+ try {
241
+ cached = await connection.workspace.getConfiguration(section) || {};
242
+ settingsCache.set(section, cached);
243
+ } catch {
735
244
  }
736
- if (autocomplete.descriptionMoreURL) {
737
- documentation.value += `
245
+ }
246
+ return cached;
247
+ }
248
+ function onConfigChange(handler) {
249
+ configChangeHandlers.add(handler);
250
+ }
251
+ function setup2(_) {
252
+ connection = _;
253
+ connection.onDidChangeConfiguration(() => {
254
+ settingsCache.clear();
255
+ emitConfigChange();
256
+ });
257
+ }
258
+ function emitConfigChange() {
259
+ for (const handler of configChangeHandlers) {
260
+ handler();
261
+ }
262
+ }
738
263
 
739
- [More Info](${autocomplete.descriptionMoreURL})`;
264
+ // src/utils/messages.ts
265
+ import { inspect } from "util";
266
+ var connection2;
267
+ var previousMessagesByType = /* @__PURE__ */ new Map();
268
+ function setup3(_) {
269
+ connection2 = _;
270
+ }
271
+ function displayError(data) {
272
+ display("showError", data);
273
+ }
274
+ function display(type, data) {
275
+ const msg = typeof data === "string" ? data : inspect(data, { colors: false });
276
+ const previousMessages = previousMessagesByType.get(type);
277
+ if (previousMessages) {
278
+ if (previousMessages.includes(msg))
279
+ return;
280
+ previousMessages.push(msg);
281
+ if (previousMessages.length > 3) {
282
+ previousMessages.unshift();
740
283
  }
284
+ } else {
285
+ previousMessagesByType.set(type, [msg]);
741
286
  }
742
- return {
743
- label,
744
- documentation,
745
- tags: tag.deprecated ? deprecated : void 0,
746
- insertTextFormat: autocomplete ? InsertTextFormat2.Snippet : void 0,
747
- kind: tag.html ? CompletionItemKind2.Property : CompletionItemKind2.Class,
748
- textEdit: range && TextEdit2.replace(range, (autocomplete == null ? void 0 : autocomplete.snippet) || label)
749
- };
287
+ setImmediate(() => connection2.sendNotification(type, msg));
750
288
  }
751
-
752
- // src/service/marko/complete/OpenTagName.ts
753
- function OpenTagName({
754
- document,
755
- lookup,
756
- parsed,
757
- node
758
- }) {
759
- var _a;
760
- const importer = getDocFile(document);
761
- const tag = node.parent;
762
- const range = parsed.locationAt(node);
763
- const isAttrTag = tag.type === 14 /* AttrTag */;
764
- const result = [];
765
- if (isAttrTag) {
766
- let parentTag = tag.owner;
767
- while ((parentTag == null ? void 0 : parentTag.type) === 14 /* AttrTag */)
768
- parentTag = parentTag.owner;
769
- const parentTagDef = parentTag && parentTag.nameText && lookup.getTag(parentTag.nameText);
770
- if (parentTagDef) {
771
- const { nestedTags } = parentTagDef;
772
- for (const key in nestedTags) {
773
- if (key !== "*") {
774
- const tag2 = nestedTags[key];
775
- result.push(
776
- getTagNameCompletion({
777
- tag: tag2,
778
- range,
779
- importer,
780
- showAutoComplete: true
781
- })
782
- );
783
- }
289
+
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
784
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);
785
338
  }
786
339
  } else {
787
- const skipStatements = !(tag.concise && tag.parent.type === 0 /* Program */);
788
- for (const tag2 of lookup.getTagsSorted()) {
789
- if (!(tag2.name === "*" || tag2.isNestedTag || skipStatements && ((_a = tag2.parseOptions) == null ? void 0 : _a.statement) || tag2.name[0] === "_" && /^@?marko[/-]|[\\/]node_modules[\\/]/.test(tag2.filePath))) {
790
- result.push(
791
- getTagNameCompletion({
792
- tag: tag2,
793
- range,
794
- importer,
795
- showAutoComplete: true
796
- })
797
- );
798
- }
799
- }
340
+ result = process2(file);
341
+ processorCaches.set(file.parsed, /* @__PURE__ */ new Map([[process2, result]]));
800
342
  }
801
343
  return result;
802
344
  }
803
345
 
346
+ // src/service/index.ts
347
+ import { MarkupContent, MarkupKind as MarkupKind3 } from "vscode-languageserver";
348
+
349
+ // src/service/marko/complete/index.ts
350
+ import { NodeType as NodeType3 } from "@marko/language-tools";
351
+
804
352
  // src/service/marko/complete/AttrName.ts
805
353
  import {
806
- CompletionItemKind as CompletionItemKind3,
807
- MarkupKind as MarkupKind2,
808
- InsertTextFormat as InsertTextFormat3,
809
- TextEdit as TextEdit3
354
+ CompletionItemKind,
355
+ InsertTextFormat,
356
+ MarkupKind,
357
+ TextEdit
810
358
  } from "vscode-languageserver";
811
359
  function AttrName({
812
360
  offset,
813
361
  node,
814
- parsed,
815
- lookup
362
+ file: {
363
+ parsed,
364
+ project: { lookup }
365
+ }
816
366
  }) {
817
367
  let name = parsed.read(node);
818
- if (name[0] === "{")
819
- return;
820
368
  const modifierIndex = name.indexOf(":");
821
369
  const hasModifier = modifierIndex !== -1;
822
370
  if (hasModifier) {
@@ -824,12 +372,12 @@ function AttrName({
824
372
  return [
825
373
  {
826
374
  label: "scoped",
827
- kind: CompletionItemKind3.Keyword,
375
+ kind: CompletionItemKind.Keyword,
828
376
  detail: "Use to prefix with a unique ID"
829
377
  },
830
378
  {
831
379
  label: "no-update",
832
- kind: CompletionItemKind3.Keyword,
380
+ kind: CompletionItemKind.Keyword,
833
381
  detail: "Use to skip future updates to this attribute"
834
382
  }
835
383
  ];
@@ -847,25 +395,19 @@ function AttrName({
847
395
  const tagName = node.parent.parent.nameText || "";
848
396
  const tagDef = tagName && lookup.getTag(tagName);
849
397
  const nestedTagAttrs = {};
850
- const neverAttrs = /* @__PURE__ */ new Set();
851
398
  if (tagDef && tagDef.nestedTags) {
852
399
  for (const key in tagDef.nestedTags) {
853
400
  const nestedTagDef = tagDef.nestedTags[key];
854
401
  nestedTagAttrs[nestedTagDef.targetProperty] = true;
855
402
  }
856
403
  }
857
- lookup.forEachAttribute(tagName, (attr) => {
858
- if (attr.type === "never") {
859
- neverAttrs.add(attr.name);
860
- }
861
- });
862
404
  lookup.forEachAttribute(tagName, (attr, parent) => {
863
- if (attr.deprecated || nestedTagAttrs[attr.name] || attr.name === "*" || neverAttrs.has(attr.name) || attr.name[0] === "_" && /\/node_modules\//.test(attr.filePath || parent.filePath)) {
405
+ if (attr.deprecated || nestedTagAttrs[attr.name] || attr.name === "*" || attr.type === "never" || attr.name[0] === "_" && isExternalModule(attr.filePath || parent.filePath)) {
864
406
  return;
865
407
  }
866
408
  const type = attr.type || (attr.html ? "string" : null);
867
409
  const documentation = {
868
- kind: MarkupKind2.Markdown,
410
+ kind: MarkupKind.Markdown,
869
411
  value: attr.description || ""
870
412
  };
871
413
  let label = attr.name;
@@ -905,23 +447,26 @@ function AttrName({
905
447
  completions.push({
906
448
  label,
907
449
  documentation: documentation.value ? documentation : void 0,
908
- kind: CompletionItemKind3.Property,
909
- insertTextFormat: InsertTextFormat3.Snippet,
910
- textEdit: TextEdit3.replace(attrNameLoc, snippet)
450
+ kind: CompletionItemKind.Property,
451
+ insertTextFormat: InsertTextFormat.Snippet,
452
+ textEdit: TextEdit.replace(attrNameLoc, snippet)
911
453
  });
912
454
  });
913
455
  return completions;
914
456
  }
457
+ function isExternalModule(file) {
458
+ return /[/\\]node_modules[/\\]/.test(file) || !/^(?:[A-Za-z]:\\|[./\\])/.test(file);
459
+ }
915
460
 
916
461
  // src/service/marko/complete/AttrValue.ts
917
- import path3 from "path";
462
+ import path2 from "path";
918
463
  import {
919
- CompletionItemKind as CompletionItemKind4,
920
- Range as Range2,
921
- TextEdit as TextEdit4
464
+ CompletionItemKind as CompletionItemKind2,
465
+ TextEdit as TextEdit2
922
466
  } from "vscode-languageserver";
923
467
 
924
468
  // src/service/marko/util/is-document-link-attr.ts
469
+ import { NodeType } from "@marko/language-tools";
925
470
  var linkedAttrs = /* @__PURE__ */ new Map([
926
471
  [
927
472
  "src",
@@ -941,15 +486,15 @@ var linkedAttrs = /* @__PURE__ */ new Map([
941
486
  ["data", /* @__PURE__ */ new Set(["object"])],
942
487
  ["poster", /* @__PURE__ */ new Set(["video"])]
943
488
  ]);
944
- function isDocumentLinkAttr(doc, tag, attr) {
489
+ function isDocumentLinkAttr(code, tag, attr) {
945
490
  var _a, _b;
946
- return tag.nameText && attr.type === 8 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 11 /* AttrValue */ && /^['"]$/.test(doc.getText()[attr.value.value.start]) && ((_b = linkedAttrs.get(doc.getText().slice(attr.name.start, attr.name.end))) == null ? void 0 : _b.has(tag.nameText)) || false;
491
+ return tag.nameText && attr.type === NodeType.AttrNamed && ((_a = attr.value) == null ? void 0 : _a.type) === NodeType.AttrValue && /^['"]$/.test(code[attr.value.value.start]) && ((_b = linkedAttrs.get(code.slice(attr.name.start, attr.name.end))) == null ? void 0 : _b.has(tag.nameText)) || false;
947
492
  }
948
493
 
949
494
  // src/utils/file-system.ts
950
- import fs from "fs/promises";
951
- import { FileType } from "vscode-css-languageservice";
495
+ import fs2 from "fs/promises";
952
496
  import { fileURLToPath } from "url";
497
+ import { FileType } from "vscode-css-languageservice";
953
498
  var file_system_default = {
954
499
  stat,
955
500
  readDirectory
@@ -960,7 +505,7 @@ async function stat(uri) {
960
505
  let mtime = -1;
961
506
  let size = -1;
962
507
  try {
963
- const stat2 = await fs.stat(fileURLToPath(uri));
508
+ const stat2 = await fs2.stat(fileURLToPath(uri));
964
509
  if (stat2.isDirectory())
965
510
  type = FileType.Directory;
966
511
  else if (stat2.isFile())
@@ -978,17 +523,18 @@ async function stat(uri) {
978
523
  };
979
524
  }
980
525
  async function readDirectory(uri) {
526
+ const result = [];
981
527
  try {
982
- const entries = await fs.readdir(fileURLToPath(uri));
983
- const base = uri.at(-1) === "/" ? uri : `${uri}/`;
984
- return (await Promise.all(
985
- entries.map(
986
- async (entry) => [entry, (await stat(new URL(entry, base).toString())).type]
987
- )
988
- )).filter(([, type]) => type !== FileType.Unknown);
528
+ for await (const entry of await fs2.opendir(fileURLToPath(uri))) {
529
+ if (entry.isFile()) {
530
+ result.push([entry.name, FileType.File]);
531
+ } else if (entry.isDirectory()) {
532
+ result.push([entry.name, FileType.Directory]);
533
+ }
534
+ }
989
535
  } catch {
990
- return [];
991
536
  }
537
+ return result;
992
538
  }
993
539
 
994
540
  // src/utils/resolve-url.ts
@@ -1004,14 +550,12 @@ function resolveUrl(to, base) {
1004
550
 
1005
551
  // src/service/marko/complete/AttrValue.ts
1006
552
  async function AttrValue({
1007
- document,
1008
553
  offset,
1009
554
  node,
1010
- parsed,
1011
- code
555
+ file: { uri, parsed, code }
1012
556
  }) {
1013
557
  const attr = node.parent;
1014
- if (isDocumentLinkAttr(document, attr.parent, attr)) {
558
+ if (isDocumentLinkAttr(code, attr.parent, attr)) {
1015
559
  const start = node.value.start + 1;
1016
560
  if (code[start] !== ".")
1017
561
  return;
@@ -1025,29 +569,29 @@ async function AttrValue({
1025
569
  if (segmentStart === -1)
1026
570
  return;
1027
571
  const req = rawValue.slice(0, segmentStart);
1028
- const uri = resolveUrl(req, document.uri);
1029
- if (uri) {
572
+ const resolved = resolveUrl(req, uri);
573
+ if (resolved) {
1030
574
  const result = [];
1031
- const curFile = req === "." ? path3.basename(document.uri) : void 0;
1032
- const replaceRange = Range2.create(
1033
- document.positionAt(start + segmentStart + 1),
1034
- document.positionAt(start + rawValue.length)
1035
- );
1036
- for (const [entry, type] of await file_system_default.readDirectory(uri)) {
575
+ const curFile = req === "." ? path2.basename(uri) : void 0;
576
+ const replaceRange = parsed.locationAt({
577
+ start: start + segmentStart + 1,
578
+ end: start + rawValue.length
579
+ });
580
+ for (const [entry, type] of await file_system_default.readDirectory(resolved)) {
1037
581
  if (entry[0] !== "." && entry !== curFile) {
1038
582
  result.push(
1039
583
  type === FileType.Directory ? {
1040
584
  label: `${entry}/`,
1041
- kind: CompletionItemKind4.Folder,
1042
- textEdit: TextEdit4.replace(replaceRange, `${entry}/`),
585
+ kind: CompletionItemKind2.Folder,
586
+ textEdit: TextEdit2.replace(replaceRange, `${entry}/`),
1043
587
  command: {
1044
588
  title: "Suggest",
1045
589
  command: "editor.action.triggerSuggest"
1046
590
  }
1047
591
  } : {
1048
592
  label: entry,
1049
- kind: CompletionItemKind4.File,
1050
- textEdit: TextEdit4.replace(replaceRange, entry)
593
+ kind: CompletionItemKind2.File,
594
+ textEdit: TextEdit2.replace(replaceRange, entry)
1051
595
  }
1052
596
  );
1053
597
  }
@@ -1057,42 +601,209 @@ async function AttrValue({
1057
601
  }
1058
602
  }
1059
603
 
1060
- // src/service/marko/complete/Statement.ts
1061
- import { TextEdit as TextEdit5 } from "vscode-languageserver";
1062
- var importTagReg = /(['"])<((?:[^\1\\>]+|\\.)*)>?\1/g;
1063
- function Statement({
1064
- code,
604
+ // src/service/marko/complete/Import.ts
605
+ import { TextEdit as TextEdit4 } from "vscode-languageserver";
606
+
607
+ // src/service/marko/util/get-tag-name-completion.ts
608
+ import path3 from "path";
609
+ import {
610
+ CompletionItemKind as CompletionItemKind3,
611
+ CompletionItemTag,
612
+ InsertTextFormat as InsertTextFormat2,
613
+ MarkupKind as MarkupKind2,
614
+ TextEdit as TextEdit3
615
+ } from "vscode-languageserver";
616
+ import { URI as URI3 } from "vscode-uri";
617
+ var deprecated = [CompletionItemTag.Deprecated];
618
+ function getTagNameCompletion({
619
+ tag,
620
+ range,
621
+ showAutoComplete,
622
+ importer
623
+ }) {
624
+ var _a;
625
+ let label = tag.isNestedTag ? `@${tag.name}` : tag.name;
626
+ const fileForTag = tag.template || tag.renderer || tag.filePath;
627
+ const fileURIForTag = URI3.file(fileForTag).toString();
628
+ const nodeModuleMatch = /\/node_modules\/((?:@[^/]+\/)?[^/]+)/.exec(
629
+ fileForTag
630
+ );
631
+ const nodeModuleName = nodeModuleMatch && nodeModuleMatch[1];
632
+ const isCoreTag = /^@?marko[/-]/.test(tag.taglibId || tag.filePath) || nodeModuleName === "marko";
633
+ const documentation = {
634
+ kind: MarkupKind2.Markdown,
635
+ value: tag.html ? `Built in [&lt;${tag.name}&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${tag.name}) HTML tag.` : isCoreTag ? `Core Marko &lt;${tag.name}&gt; tag.` : nodeModuleName ? `Custom Marko tag discovered from the ["${nodeModuleName}"](${fileURIForTag}) npm package.` : `Custom Marko tag discovered from:
636
+
637
+ [${importer ? path3.relative(importer, fileForTag) : fileForTag}](${fileURIForTag})`
638
+ };
639
+ if (tag.description) {
640
+ documentation.value += `
641
+
642
+ ${tag.description}`;
643
+ }
644
+ const autocomplete = showAutoComplete ? (_a = tag.autocomplete) == null ? void 0 : _a[0] : void 0;
645
+ if (autocomplete) {
646
+ if (autocomplete.displayText) {
647
+ label = autocomplete.displayText;
648
+ }
649
+ if (autocomplete.description) {
650
+ documentation.value += `
651
+
652
+ ${autocomplete.description}`;
653
+ }
654
+ if (autocomplete.descriptionMoreURL) {
655
+ documentation.value += `
656
+
657
+ [More Info](${autocomplete.descriptionMoreURL})`;
658
+ }
659
+ }
660
+ return {
661
+ label,
662
+ documentation,
663
+ tags: tag.deprecated ? deprecated : void 0,
664
+ insertTextFormat: autocomplete ? InsertTextFormat2.Snippet : void 0,
665
+ kind: tag.html ? CompletionItemKind3.Property : CompletionItemKind3.Class,
666
+ textEdit: range && TextEdit3.replace(range, (autocomplete == null ? void 0 : autocomplete.snippet) || label)
667
+ };
668
+ }
669
+
670
+ // src/service/marko/complete/Import.ts
671
+ var importTagReg = /(['"])<((?:[^\1\\>]+|\\.)*)>?\1/;
672
+ function Import({
1065
673
  node,
1066
- parsed,
1067
- lookup,
1068
- document
674
+ file: {
675
+ parsed,
676
+ filename,
677
+ project: { lookup }
678
+ }
1069
679
  }) {
1070
680
  var _a;
1071
- if (code[node.start] === "i") {
1072
- importTagReg.lastIndex = 0;
1073
- const value = parsed.read(node);
1074
- const match = importTagReg.exec(value);
1075
- if (match) {
1076
- const importer = getDocFile(document);
1077
- const [{ length }] = match;
1078
- const range = parsed.locationAt({
1079
- start: node.start + match.index + 1,
1080
- end: node.start + match.index + length - 1
1081
- });
1082
- const result = [];
1083
- for (const tag of lookup.getTagsSorted()) {
1084
- if ((tag.template || tag.renderer) && !(tag.html || tag.parser || tag.translator || tag.isNestedTag || tag.name === "*" || ((_a = tag.parseOptions) == null ? void 0 : _a.statement) || /^@?marko[/-]/.test(tag.taglibId) || tag.name[0] === "_" && /[\\/]node_modules[\\/]/.test(tag.filePath))) {
1085
- const completion = getTagNameCompletion({
1086
- tag,
1087
- importer
1088
- });
1089
- completion.label = `<${completion.label}>`;
1090
- completion.textEdit = TextEdit5.replace(range, completion.label);
1091
- result.push(completion);
681
+ const value = parsed.read(node);
682
+ const match = importTagReg.exec(value);
683
+ if (match) {
684
+ const [{ length }] = match;
685
+ const fromStart = node.start + match.index;
686
+ const range = parsed.locationAt({
687
+ start: fromStart + 1,
688
+ end: fromStart + length - 1
689
+ });
690
+ const result = [];
691
+ for (const tag of lookup.getTagsSorted()) {
692
+ if ((tag.template || tag.renderer) && !(tag.html || tag.parser || tag.translator || tag.isNestedTag || tag.name === "*" || ((_a = tag.parseOptions) == null ? void 0 : _a.statement) || /^@?marko[/-]/.test(tag.taglibId) || tag.name[0] === "_" && /[\\/]node_modules[\\/]/.test(tag.filePath))) {
693
+ const completion = getTagNameCompletion({
694
+ tag,
695
+ importer: filename
696
+ });
697
+ completion.label = `<${completion.label}>`;
698
+ completion.textEdit = TextEdit4.replace(range, completion.label);
699
+ result.push(completion);
700
+ }
701
+ }
702
+ return result;
703
+ }
704
+ }
705
+
706
+ // src/service/marko/complete/OpenTagName.ts
707
+ import { NodeType as NodeType2 } from "@marko/language-tools";
708
+ function OpenTagName({
709
+ node,
710
+ file: {
711
+ parsed,
712
+ filename,
713
+ project: { lookup }
714
+ }
715
+ }) {
716
+ var _a;
717
+ const tag = node.parent;
718
+ const range = parsed.locationAt(node);
719
+ const isAttrTag = tag.type === NodeType2.AttrTag;
720
+ const result = [];
721
+ if (isAttrTag) {
722
+ let parentTag = tag.owner;
723
+ while ((parentTag == null ? void 0 : parentTag.type) === NodeType2.AttrTag)
724
+ parentTag = parentTag.owner;
725
+ const parentTagDef = parentTag && parentTag.nameText && lookup.getTag(parentTag.nameText);
726
+ if (parentTagDef) {
727
+ const { nestedTags } = parentTagDef;
728
+ for (const key in nestedTags) {
729
+ if (key !== "*") {
730
+ const tag2 = nestedTags[key];
731
+ result.push(
732
+ getTagNameCompletion({
733
+ tag: tag2,
734
+ range,
735
+ importer: filename,
736
+ showAutoComplete: true
737
+ })
738
+ );
1092
739
  }
1093
740
  }
1094
- return result;
1095
741
  }
742
+ } else {
743
+ const skipStatements = !(tag.concise && tag.parent.type === NodeType2.Program);
744
+ for (const tag2 of lookup.getTagsSorted()) {
745
+ if (!(tag2.name === "*" || tag2.isNestedTag || skipStatements && ((_a = tag2.parseOptions) == null ? void 0 : _a.statement) || tag2.name[0] === "_" && /^@?marko[/-]|[\\/]node_modules[\\/]/.test(tag2.filePath))) {
746
+ const completion = getTagNameCompletion({
747
+ tag: tag2,
748
+ range,
749
+ importer: filename,
750
+ showAutoComplete: true
751
+ });
752
+ completion.sortText = `0${completion.label}`;
753
+ result.push(completion);
754
+ }
755
+ }
756
+ }
757
+ return result;
758
+ }
759
+
760
+ // src/service/marko/complete/Tag.ts
761
+ import {
762
+ CompletionItemKind as CompletionItemKind4,
763
+ InsertTextFormat as InsertTextFormat3,
764
+ TextEdit as TextEdit5
765
+ } from "vscode-languageserver";
766
+ import { UNFINISHED } from "@marko/language-tools";
767
+ var partialCloseTagReg = /<\/(?:[^><]*>)?/iy;
768
+ function Tag({
769
+ node,
770
+ offset,
771
+ file: { parsed, code }
772
+ }) {
773
+ const isClosed = node.end !== UNFINISHED;
774
+ if (isClosed || node.concise)
775
+ return;
776
+ const closingTagStr = `</${node.nameText || ""}>`;
777
+ if (offset === node.open.end) {
778
+ return [
779
+ {
780
+ label: closingTagStr,
781
+ kind: CompletionItemKind4.Class,
782
+ insertTextFormat: InsertTextFormat3.Snippet,
783
+ insertText: `
784
+ $0
785
+ ${closingTagStr}`
786
+ }
787
+ ];
788
+ } else if (node.close && offset >= node.close.start) {
789
+ const start = node.close.start;
790
+ partialCloseTagReg.lastIndex = start;
791
+ const [{ length }] = partialCloseTagReg.exec(code);
792
+ const end = start + length;
793
+ return [
794
+ {
795
+ label: closingTagStr,
796
+ kind: CompletionItemKind4.Class,
797
+ insertTextFormat: InsertTextFormat3.Snippet,
798
+ textEdit: TextEdit5.replace(
799
+ parsed.locationAt({
800
+ start,
801
+ end
802
+ }),
803
+ closingTagStr
804
+ )
805
+ }
806
+ ];
1096
807
  }
1097
808
  }
1098
809
 
@@ -1102,37 +813,37 @@ var handlers = {
1102
813
  OpenTagName,
1103
814
  AttrName,
1104
815
  AttrValue,
1105
- Statement
816
+ Import
1106
817
  };
1107
818
  var doComplete = async (doc, params) => {
1108
819
  var _a;
1109
- const parsed = parse2(doc);
820
+ const file = getMarkoFile(doc);
1110
821
  const offset = doc.offsetAt(params.position);
1111
- const node = parsed.nodeAt(offset);
1112
- return CompletionList.create(
1113
- await ((_a = handlers[NodeType[node.type]]) == null ? void 0 : _a.call(handlers, {
1114
- document: doc,
822
+ const node = file.parsed.nodeAt(offset);
823
+ return {
824
+ items: await ((_a = handlers[NodeType3[node.type]]) == null ? void 0 : _a.call(handlers, {
825
+ file,
1115
826
  params,
1116
- parsed,
1117
827
  offset,
1118
- node,
1119
- code: doc.getText(),
1120
- ...getCompilerInfo(doc)
828
+ node
1121
829
  })) || [],
1122
- true
1123
- );
830
+ isIncomplete: true
831
+ };
1124
832
  };
1125
833
 
1126
834
  // src/service/marko/validate.ts
835
+ import path4 from "path";
1127
836
  import { DiagnosticSeverity } from "vscode-languageserver";
1128
837
  var markoErrorRegExp = /^(.+?)\.marko(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
1129
838
  var doValidate = (doc) => {
1130
- const fsPath = getDocFile(doc);
839
+ const filename = getFSPath(doc);
1131
840
  const diagnostics = [];
1132
- const { compiler, translator, cache: cache4 } = getCompilerInfo(doc);
841
+ const { compiler, translator, cache } = getMarkoProject(
842
+ filename && path4.dirname(filename)
843
+ );
1133
844
  try {
1134
- compiler.compileSync(doc.getText(), fsPath || "untitled.marko", {
1135
- cache: cache4,
845
+ compiler.compileSync(doc.getText(), filename || "untitled.marko", {
846
+ cache,
1136
847
  translator,
1137
848
  code: false,
1138
849
  output: "source",
@@ -1168,42 +879,43 @@ var doValidate = (doc) => {
1168
879
  return diagnostics;
1169
880
  };
1170
881
 
1171
- // src/utils/utils.ts
1172
- import fs2 from "fs";
1173
- import { URI as URI3 } from "vscode-uri";
1174
- import { Position, Range as Range3 } from "vscode-languageserver";
1175
- import { TextDocument } from "vscode-languageserver-textdocument";
1176
- var START_OF_FILE = Range3.create(
1177
- Position.create(0, 0),
1178
- Position.create(0, 0)
1179
- );
1180
- function createTextDocument(filename) {
1181
- const uri = URI3.file(filename).toString();
1182
- const content = fs2.readFileSync(filename, "utf-8");
1183
- return TextDocument.create(uri, "plaintext", 0, content);
1184
- }
882
+ // src/service/marko/hover/index.ts
883
+ import { NodeType as NodeType4 } from "@marko/language-tools";
884
+
885
+ // src/utils/constants.ts
886
+ var START_POSITION = {
887
+ line: 0,
888
+ character: 0
889
+ };
890
+ var START_LOCATION = {
891
+ start: START_POSITION,
892
+ end: START_POSITION
893
+ };
1185
894
 
1186
895
  // src/service/marko/hover/OpenTagName.ts
1187
896
  function OpenTagName2({
1188
- document,
1189
- lookup,
1190
- parsed,
1191
- node
897
+ node,
898
+ file: {
899
+ parsed,
900
+ filename,
901
+ project: { lookup }
902
+ }
1192
903
  }) {
1193
- const importer = getDocFile(document);
1194
904
  const tag = node.parent;
1195
905
  const range = parsed.locationAt(node);
1196
906
  const tagDef = tag.nameText && lookup.getTag(tag.nameText);
1197
907
  if (tagDef) {
1198
908
  const completion = getTagNameCompletion({
1199
909
  tag: tagDef,
1200
- range: START_OF_FILE,
1201
- importer
910
+ range: START_LOCATION,
911
+ importer: filename
1202
912
  });
1203
- return {
1204
- range,
1205
- contents: completion.documentation
1206
- };
913
+ if (completion.documentation) {
914
+ return {
915
+ range,
916
+ contents: completion.documentation
917
+ };
918
+ }
1207
919
  }
1208
920
  }
1209
921
 
@@ -1213,24 +925,24 @@ var handlers2 = {
1213
925
  };
1214
926
  var doHover = async (doc, params) => {
1215
927
  var _a;
1216
- const parsed = parse2(doc);
928
+ const file = getMarkoFile(doc);
1217
929
  const offset = doc.offsetAt(params.position);
1218
- const node = parsed.nodeAt(offset);
1219
- return await ((_a = handlers2[NodeType[node.type]]) == null ? void 0 : _a.call(handlers2, {
1220
- document: doc,
930
+ const node = file.parsed.nodeAt(offset);
931
+ return await ((_a = handlers2[NodeType4[node.type]]) == null ? void 0 : _a.call(handlers2, {
932
+ file,
1221
933
  params,
1222
- parsed,
1223
934
  offset,
1224
- node,
1225
- code: doc.getText(),
1226
- ...getCompilerInfo(doc)
935
+ node
1227
936
  }));
1228
937
  };
1229
938
 
1230
- // src/service/marko/definition/OpenTagName.ts
1231
- import path4 from "path";
939
+ // src/service/marko/definition/index.ts
940
+ import { NodeType as NodeType6 } from "@marko/language-tools";
941
+
942
+ // src/service/marko/definition/AttrName.ts
943
+ import fs3 from "fs";
1232
944
  import { URI as URI4 } from "vscode-uri";
1233
- import { Range as Range4, LocationLink } from "vscode-languageserver";
945
+ import { getLines, getLocation } from "@marko/language-tools";
1234
946
 
1235
947
  // src/utils/regexp-builder.ts
1236
948
  function RegExpBuilder(strings, ...expressions) {
@@ -1256,18 +968,71 @@ function escape(val) {
1256
968
  return String(val).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
1257
969
  }
1258
970
 
971
+ // src/service/marko/definition/AttrName.ts
972
+ function AttrName2({
973
+ node,
974
+ file: {
975
+ parsed,
976
+ project: { lookup }
977
+ }
978
+ }) {
979
+ const tagName = node.parent.parent.nameText;
980
+ const attrName = parsed.read(node);
981
+ const tagDef = tagName ? lookup.getTag(tagName) : void 0;
982
+ const attrDef = lookup.getAttribute(tagName || "", attrName);
983
+ let range = START_LOCATION;
984
+ if (!attrDef) {
985
+ return;
986
+ }
987
+ const attrEntryFile = attrDef.filePath || (tagDef == null ? void 0 : tagDef.filePath);
988
+ if (!attrEntryFile) {
989
+ return;
990
+ }
991
+ if (/\.json$/.test(attrEntryFile)) {
992
+ const tagDefSource = fs3.readFileSync(attrEntryFile, "utf-8");
993
+ const match = RegExpBuilder`/"@${attrName}"\s*:\s*[^\r\n,]+/g`.exec(
994
+ tagDefSource
995
+ );
996
+ if (match && match.index) {
997
+ range = getLocation(
998
+ getLines(tagDefSource),
999
+ match.index,
1000
+ match.index + match[0].length
1001
+ );
1002
+ }
1003
+ return [
1004
+ {
1005
+ targetUri: URI4.file(attrEntryFile).toString(),
1006
+ targetRange: range,
1007
+ targetSelectionRange: range,
1008
+ originSelectionRange: parsed.locationAt(node)
1009
+ }
1010
+ ];
1011
+ }
1012
+ }
1013
+
1259
1014
  // src/service/marko/definition/OpenTagName.ts
1015
+ import fs4 from "fs";
1016
+ import path5 from "path";
1017
+ import { URI as URI5 } from "vscode-uri";
1018
+ import {
1019
+ NodeType as NodeType5,
1020
+ getLines as getLines2,
1021
+ getLocation as getLocation2
1022
+ } from "@marko/language-tools";
1260
1023
  function OpenTagName3({
1261
- lookup,
1262
- parsed,
1263
- node
1024
+ node,
1025
+ file: {
1026
+ parsed,
1027
+ project: { lookup }
1028
+ }
1264
1029
  }) {
1265
1030
  const tag = node.parent;
1266
1031
  let tagDef;
1267
- let range = START_OF_FILE;
1268
- if (tag.type === 14 /* AttrTag */) {
1032
+ let range = START_LOCATION;
1033
+ if (tag.type === NodeType5.AttrTag) {
1269
1034
  let parentTag = tag.owner;
1270
- while ((parentTag == null ? void 0 : parentTag.type) === 14 /* AttrTag */)
1035
+ while ((parentTag == null ? void 0 : parentTag.type) === NodeType5.AttrTag)
1271
1036
  parentTag = parentTag.owner;
1272
1037
  tagDef = parentTag && parentTag.nameText ? lookup.getTag(parentTag.nameText) : void 0;
1273
1038
  } else {
@@ -1277,72 +1042,29 @@ function OpenTagName3({
1277
1042
  return;
1278
1043
  }
1279
1044
  const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
1280
- if (!path4.isAbsolute(tagEntryFile)) {
1045
+ if (!path5.isAbsolute(tagEntryFile)) {
1281
1046
  return;
1282
1047
  }
1283
1048
  if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
1284
- const tagDefDoc = createTextDocument(tagEntryFile);
1049
+ const tagDefSource = fs4.readFileSync(tagEntryFile, "utf-8");
1285
1050
  const match = RegExpBuilder`/"(?:<${tag.nameText}>|${tag.nameText})"\s*:\s*[^\r\n,]+/g`.exec(
1286
- tagDefDoc.getText()
1051
+ tagDefSource
1287
1052
  );
1288
1053
  if (match && match.index) {
1289
- range = Range4.create(
1290
- tagDefDoc.positionAt(match.index),
1291
- tagDefDoc.positionAt(match.index + match[0].length)
1054
+ range = getLocation2(
1055
+ getLines2(tagDefSource),
1056
+ match.index,
1057
+ match.index + match[0].length
1292
1058
  );
1293
1059
  }
1294
1060
  }
1295
1061
  return [
1296
- LocationLink.create(
1297
- URI4.file(tagEntryFile).toString(),
1298
- range,
1299
- range,
1300
- parsed.locationAt(node)
1301
- )
1302
- ];
1303
- }
1304
-
1305
- // src/service/marko/definition/AttrName.ts
1306
- import { URI as URI5 } from "vscode-uri";
1307
- import { Range as Range5, LocationLink as LocationLink2 } from "vscode-languageserver";
1308
- function AttrName2({
1309
- lookup,
1310
- parsed,
1311
- node
1312
- }) {
1313
- const tagName = node.parent.parent.nameText;
1314
- const attrName = parsed.read(node);
1315
- if (attrName[0] === "{")
1316
- return;
1317
- const tagDef = tagName && lookup.getTag(tagName);
1318
- const attrDef = lookup.getAttribute(tagName || "", attrName);
1319
- let range = START_OF_FILE;
1320
- if (!attrDef) {
1321
- return;
1322
- }
1323
- const attrEntryFile = attrDef.filePath || tagDef && tagDef.filePath;
1324
- if (!attrEntryFile) {
1325
- return;
1326
- }
1327
- if (/\/marko(?:-tag)?\.json$/.test(attrEntryFile)) {
1328
- const tagDefDoc = createTextDocument(attrEntryFile);
1329
- const match = RegExpBuilder`/"@${attrName}"\s*:\s*[^\r\n,]+/g`.exec(
1330
- tagDefDoc.getText()
1331
- );
1332
- if (match && match.index) {
1333
- range = Range5.create(
1334
- tagDefDoc.positionAt(match.index),
1335
- tagDefDoc.positionAt(match.index + match[0].length)
1336
- );
1062
+ {
1063
+ targetUri: URI5.file(tagEntryFile).toString(),
1064
+ targetRange: range,
1065
+ targetSelectionRange: range,
1066
+ originSelectionRange: parsed.locationAt(node)
1337
1067
  }
1338
- }
1339
- return [
1340
- LocationLink2.create(
1341
- URI5.file(attrEntryFile).toString(),
1342
- range,
1343
- range,
1344
- parsed.locationAt(node)
1345
- )
1346
1068
  ];
1347
1069
  }
1348
1070
 
@@ -1353,66 +1075,57 @@ var handlers3 = {
1353
1075
  };
1354
1076
  var findDefinition = async (doc, params) => {
1355
1077
  var _a;
1356
- const parsed = parse2(doc);
1078
+ const file = getMarkoFile(doc);
1357
1079
  const offset = doc.offsetAt(params.position);
1358
- const node = parsed.nodeAt(offset);
1359
- return await ((_a = handlers3[NodeType[node.type]]) == null ? void 0 : _a.call(handlers3, {
1360
- document: doc,
1080
+ const node = file.parsed.nodeAt(offset);
1081
+ return await ((_a = handlers3[NodeType6[node.type]]) == null ? void 0 : _a.call(handlers3, {
1082
+ file,
1361
1083
  params,
1362
- parsed,
1363
1084
  offset,
1364
- node,
1365
- code: doc.getText(),
1366
- ...getCompilerInfo(doc)
1085
+ node
1367
1086
  })) || [];
1368
1087
  };
1369
1088
 
1370
1089
  // src/service/marko/document-links.ts
1371
- import { DocumentLink } from "vscode-languageserver";
1372
- import { URI as URI6 } from "vscode-uri";
1090
+ import { NodeType as NodeType7 } from "@marko/language-tools";
1373
1091
  var importTagReg2 = /(['"])<((?:[^\1\\>]+|\\.)*)>?\1/g;
1374
- var cache = /* @__PURE__ */ new WeakMap();
1375
1092
  var findDocumentLinks = async (doc) => {
1376
- const parsed = parse2(doc);
1377
- let result = cache.get(parsed);
1378
- if (!result) {
1379
- result = extractDocumentLinks(doc, parsed, getCompilerInfo(doc).lookup);
1380
- cache.set(parsed, result);
1381
- }
1382
- return result;
1093
+ return processDoc(doc, extractDocumentLinks);
1383
1094
  };
1384
- function extractDocumentLinks(doc, parsed, lookup) {
1385
- if (URI6.parse(doc.uri).scheme === "untitled") {
1095
+ function extractDocumentLinks({
1096
+ uri,
1097
+ scheme,
1098
+ parsed,
1099
+ code,
1100
+ project: { lookup }
1101
+ }) {
1102
+ if (scheme !== "file") {
1386
1103
  return [];
1387
1104
  }
1388
1105
  const links = [];
1389
- const { program } = parsed;
1390
- const code = doc.getText();
1391
- const read = (range) => code.slice(range.start, range.end);
1106
+ const { program, read } = parsed;
1392
1107
  const visit = (node) => {
1393
1108
  switch (node.type) {
1394
- case 14 /* AttrTag */:
1109
+ case NodeType7.AttrTag:
1395
1110
  if (node.body) {
1396
1111
  for (const child of node.body) {
1397
1112
  visit(child);
1398
1113
  }
1399
1114
  }
1400
1115
  break;
1401
- case 1 /* Tag */:
1116
+ case NodeType7.Tag:
1402
1117
  if (node.attrs && node.nameText) {
1403
1118
  for (const attr of node.attrs) {
1404
- if (isDocumentLinkAttr(doc, node, attr)) {
1119
+ if (isDocumentLinkAttr(code, node, attr)) {
1405
1120
  const resolved = resolveUrl(
1406
1121
  read(attr.value.value).slice(1, -1),
1407
- doc.uri
1122
+ uri
1408
1123
  );
1409
1124
  if (resolved) {
1410
- links.push(
1411
- DocumentLink.create(
1412
- parsed.locationAt(attr.value.value),
1413
- resolveUrl(read(attr.value.value).slice(1, -1), doc.uri)
1414
- )
1415
- );
1125
+ links.push({
1126
+ range: parsed.locationAt(attr.value.value),
1127
+ target: resolveUrl(read(attr.value.value).slice(1, -1), uri)
1128
+ });
1416
1129
  }
1417
1130
  }
1418
1131
  }
@@ -1425,50 +1138,44 @@ function extractDocumentLinks(doc, parsed, lookup) {
1425
1138
  break;
1426
1139
  }
1427
1140
  };
1428
- for (const item of program.static) {
1429
- if (item.type === 20 /* Statement */ && code[item.start] === "i") {
1141
+ for (const node of program.static) {
1142
+ if (node.type === NodeType7.Import) {
1430
1143
  importTagReg2.lastIndex = 0;
1431
- const value = parsed.read(item);
1144
+ const value = parsed.read(node);
1432
1145
  const match = importTagReg2.exec(value);
1433
1146
  if (match) {
1434
1147
  const [{ length }, , tagName] = match;
1435
1148
  const tagDef = lookup.getTag(tagName);
1436
1149
  const fileForTag = tagDef && (tagDef.template || tagDef.renderer);
1437
1150
  if (fileForTag) {
1438
- links.push(
1439
- DocumentLink.create(
1440
- parsed.locationAt({
1441
- start: item.start + match.index,
1442
- end: item.start + match.index + length
1443
- }),
1444
- fileForTag
1445
- )
1446
- );
1151
+ links.push({
1152
+ range: parsed.locationAt({
1153
+ start: node.start + match.index,
1154
+ end: node.start + match.index + length
1155
+ }),
1156
+ target: fileForTag
1157
+ });
1447
1158
  }
1448
1159
  }
1449
1160
  }
1450
1161
  }
1451
- for (const item of program.body) {
1452
- visit(item);
1162
+ for (const node of program.body) {
1163
+ visit(node);
1453
1164
  }
1454
1165
  return links;
1455
1166
  }
1456
1167
 
1457
1168
  // src/service/marko/document-symbols.ts
1458
- import { URI as URI7 } from "vscode-uri";
1459
- import { SymbolInformation, SymbolKind } from "vscode-languageserver";
1460
- var cache2 = /* @__PURE__ */ new WeakMap();
1461
- var findDocumentSymbols = async (doc) => {
1462
- const parsed = parse2(doc);
1463
- let result = cache2.get(parsed);
1464
- if (!result) {
1465
- result = extractDocumentSymbols(doc, parsed, getCompilerInfo(doc).lookup);
1466
- cache2.set(parsed, result);
1467
- }
1468
- return result;
1469
- };
1470
- function extractDocumentSymbols(doc, parsed, lookup) {
1471
- if (URI7.parse(doc.uri).scheme === "untitled") {
1169
+ import { SymbolKind } from "vscode-languageserver";
1170
+ import { NodeType as NodeType8 } from "@marko/language-tools";
1171
+ var findDocumentSymbols = async (doc) => processDoc(doc, extractDocumentSymbols);
1172
+ function extractDocumentSymbols({
1173
+ uri,
1174
+ scheme,
1175
+ parsed,
1176
+ project: { lookup }
1177
+ }) {
1178
+ if (scheme !== "file") {
1472
1179
  return [];
1473
1180
  }
1474
1181
  const symbols = [];
@@ -1476,16 +1183,16 @@ function extractDocumentSymbols(doc, parsed, lookup) {
1476
1183
  const visit = (node) => {
1477
1184
  var _a, _b;
1478
1185
  switch (node.type) {
1479
- case 1 /* Tag */:
1480
- case 14 /* AttrTag */:
1481
- symbols.push(
1482
- SymbolInformation.create(
1483
- (node.type === 14 /* AttrTag */ ? (_a = node.nameText) == null ? void 0 : _a.slice(node.nameText.indexOf("@")) : node.nameText) || "<${...}>",
1484
- node.nameText && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html) && SymbolKind.Property || SymbolKind.Class,
1485
- parsed.locationAt(node),
1486
- doc.uri
1487
- )
1488
- );
1186
+ case NodeType8.Tag:
1187
+ case NodeType8.AttrTag:
1188
+ symbols.push({
1189
+ name: (node.type === NodeType8.AttrTag ? (_a = node.nameText) == null ? void 0 : _a.slice(node.nameText.indexOf("@")) : node.nameText) || "<${...}>",
1190
+ kind: node.nameText && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html) && SymbolKind.Property || SymbolKind.Class,
1191
+ location: {
1192
+ uri,
1193
+ range: parsed.locationAt(node)
1194
+ }
1195
+ });
1489
1196
  if (node.body) {
1490
1197
  for (const child of node.body) {
1491
1198
  visit(child);
@@ -1501,32 +1208,35 @@ function extractDocumentSymbols(doc, parsed, lookup) {
1501
1208
  }
1502
1209
 
1503
1210
  // src/service/marko/format.ts
1504
- import { Range as Range6, TextEdit as TextEdit6 } from "vscode-languageserver";
1505
- import { URI as URI8 } from "vscode-uri";
1211
+ import { TextEdit as TextEdit6 } from "vscode-languageserver";
1506
1212
  import * as prettier from "prettier";
1507
1213
  import * as markoPrettier from "prettier-plugin-marko";
1508
1214
  var format2 = async (doc, params, cancel) => {
1509
1215
  try {
1510
- const { fsPath, scheme } = URI8.parse(doc.uri);
1216
+ const filepath = getFSPath(doc);
1511
1217
  const text = doc.getText();
1512
1218
  const options = {
1513
1219
  parser: "marko",
1514
- filepath: fsPath,
1220
+ filepath,
1515
1221
  plugins: [markoPrettier],
1516
1222
  tabWidth: params.options.tabSize,
1517
1223
  useTabs: params.options.insertSpaces === false,
1518
- ...scheme === "file" ? await prettier.resolveConfig(fsPath, {
1224
+ ...filepath ? await prettier.resolveConfig(filepath, {
1519
1225
  editorconfig: true
1520
1226
  }).catch(() => null) : null
1521
1227
  };
1522
1228
  if (cancel.isCancellationRequested)
1523
1229
  return;
1524
- return [
1230
+ const ret = [
1525
1231
  TextEdit6.replace(
1526
- Range6.create(doc.positionAt(0), doc.positionAt(text.length)),
1232
+ {
1233
+ start: START_POSITION,
1234
+ end: doc.positionAt(text.length)
1235
+ },
1527
1236
  prettier.format(text, options)
1528
1237
  )
1529
1238
  ];
1239
+ return ret;
1530
1240
  } catch (e) {
1531
1241
  displayError(e);
1532
1242
  }
@@ -1543,189 +1253,951 @@ var marko_default = {
1543
1253
  format: format2
1544
1254
  };
1545
1255
 
1546
- // src/service/stylesheet/index.ts
1256
+ // src/service/script/index.ts
1257
+ import path9 from "path";
1258
+ import { relativeImportPath } from "relative-import-path";
1259
+ import ts from "typescript/lib/tsserverlibrary";
1547
1260
  import {
1548
- CompletionList as CompletionList2,
1549
- Range as Range8,
1550
- TextDocumentEdit
1261
+ CompletionItemKind as CompletionItemKind5,
1262
+ CompletionItemTag as CompletionItemTag2,
1263
+ DiagnosticSeverity as DiagnosticSeverity2,
1264
+ DiagnosticTag,
1265
+ InsertTextFormat as InsertTextFormat4
1551
1266
  } from "vscode-languageserver";
1267
+ import { URI as URI6 } from "vscode-uri";
1268
+ import * as prettier2 from "prettier";
1552
1269
  import {
1553
- getCSSLanguageService,
1554
- getLESSLanguageService,
1555
- getSCSSLanguageService
1556
- } from "vscode-css-languageservice";
1557
- import { TextDocument as TextDocument2 } from "vscode-languageserver-textdocument";
1270
+ ScriptLang as ScriptLang3,
1271
+ extractScript as extractScript2
1272
+ } from "@marko/language-tools";
1558
1273
 
1559
- // src/utils/extractor.ts
1560
- function createExtractor(code) {
1561
- let generated = "";
1562
- const generatedMap = [];
1563
- return {
1564
- write(strs, ...exprs) {
1565
- const len = exprs.length;
1566
- for (let i = 0; i < len; i++) {
1567
- const expr = exprs[i];
1568
- generated += strs[i];
1569
- if (typeof expr === "string") {
1570
- generated += expr;
1571
- } else {
1572
- generatedMap.push(generated.length, expr.start, expr.end);
1573
- generated += code.slice(expr.start, expr.end);
1574
- }
1274
+ // src/ts-plugin/host.ts
1275
+ import path8 from "path";
1276
+ import {
1277
+ ScriptLang as ScriptLang2,
1278
+ extractScript,
1279
+ parse as parse2
1280
+ } from "@marko/language-tools";
1281
+
1282
+ // 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");
1286
+ function getProjectTypeLibs(project, ts2, host) {
1287
+ let cached = project.cache.get(getProjectTypeLibs);
1288
+ if (cached === void 0) {
1289
+ const { resolvedTypeReferenceDirective } = ts2.resolveTypeReferenceDirective(
1290
+ project.translator.runtimeTypes || "marko",
1291
+ path6.join(project.rootDir, "_.d.ts"),
1292
+ host.getCompilationSettings(),
1293
+ host
1294
+ );
1295
+ const markoTypesFile = (resolvedTypeReferenceDirective == null ? void 0 : resolvedTypeReferenceDirective.resolvedFileName) || defaultMarkoTypesFile;
1296
+ cached = {
1297
+ internalTypesFile,
1298
+ markoTypesFile,
1299
+ markoTypesCode: host.readFile(markoTypesFile, "utf-8") || ""
1300
+ };
1301
+ project.cache.set(getProjectTypeLibs, cached);
1302
+ }
1303
+ return cached;
1304
+ }
1305
+
1306
+ // src/utils/get-script-lang.ts
1307
+ import { ScriptLang } from "@marko/language-tools";
1308
+ function getScriptLang(filename, ts2, host, projectScriptLang) {
1309
+ const configPath = ts2.findConfigFile(
1310
+ filename,
1311
+ host.fileExists.bind(host),
1312
+ "marko.json"
1313
+ );
1314
+ if (configPath) {
1315
+ try {
1316
+ const markoConfig = JSON.parse(
1317
+ host.readFile(configPath, "utf-8") || "{}"
1318
+ );
1319
+ const scriptLang = markoConfig["script-lang"] || markoConfig.scriptLang;
1320
+ if (scriptLang !== void 0) {
1321
+ return scriptLang === ScriptLang.ts ? ScriptLang.ts : ScriptLang.js;
1575
1322
  }
1576
- generated += strs[len];
1577
- },
1578
- end() {
1579
- const sourceMap = generatedMap.slice();
1580
- (function sort(left, right) {
1581
- if (left < right) {
1582
- let next = left;
1583
- for (let i = left; i <= right; i += 3) {
1584
- if (sourceMap[i] <= sourceMap[right]) {
1585
- [sourceMap[next - 1], sourceMap[i - 1]] = [
1586
- sourceMap[i - 1],
1587
- sourceMap[next - 1]
1588
- ];
1589
- [sourceMap[next], sourceMap[i]] = [sourceMap[i], sourceMap[next]];
1590
- [sourceMap[next + 1], sourceMap[i + 1]] = [
1591
- sourceMap[i + 1],
1592
- sourceMap[next + 1]
1593
- ];
1594
- next += 3;
1595
- }
1596
- }
1597
- next -= 3;
1598
- sort(left, next - 3);
1599
- sort(next + 3, right);
1600
- }
1601
- })(1, sourceMap.length - 2);
1602
- return {
1603
- generated,
1604
- sourceOffsetAt(generatedOffset) {
1605
- let max = generatedMap.length / 3;
1606
- let min = 0;
1607
- while (min < max) {
1608
- const mid = 1 + min + max >>> 1;
1609
- if (generatedMap[mid * 3] <= generatedOffset) {
1610
- min = mid;
1611
- } else {
1612
- max = mid - 1;
1323
+ } catch {
1324
+ }
1325
+ }
1326
+ return /[/\\]node_modules[/\\]/.test(filename) ? ScriptLang.js : projectScriptLang;
1327
+ }
1328
+
1329
+ // 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");
1334
+ 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)) {
1343
+ if (entry !== from && (isEntry && entry.startsWith(componentBrowserPartial) || entry.startsWith(componentPartial)) || entry.startsWith(componentBrowserFull) || entry.startsWith(componentFull)) {
1344
+ return entry;
1345
+ }
1346
+ }
1347
+ }
1348
+
1349
+ // src/ts-plugin/host.ts
1350
+ var markoExt = ".marko";
1351
+ var markoExtReg = /\.marko$/;
1352
+ var modulePartsReg = /^((?:@(?:[^/]+)\/)?(?:[^/]+))(.*)$/;
1353
+ var fsPathReg = /^(?:[./\\]|[A-Z]:)/i;
1354
+ function patch(ts2, scriptLang, cache, host) {
1355
+ var _a, _b, _c;
1356
+ const projectTypeLibs = getProjectTypeLibs(
1357
+ getMarkoProject(host.getCurrentDirectory()),
1358
+ ts2,
1359
+ host
1360
+ );
1361
+ const isMarkoTSFile = (fileName) => getScriptLang(fileName, ts2, host, scriptLang) === ScriptLang2.ts;
1362
+ const getScriptFileNames = host.getScriptFileNames.bind(host);
1363
+ host.getScriptFileNames = () => [
1364
+ .../* @__PURE__ */ new Set([
1365
+ ...getScriptFileNames(),
1366
+ projectTypeLibs.internalTypesFile,
1367
+ projectTypeLibs.markoTypesFile
1368
+ ])
1369
+ ];
1370
+ const getScriptKind = (_a = host.getScriptKind) == null ? void 0 : _a.bind(host);
1371
+ if (getScriptKind) {
1372
+ host.getScriptKind = (fileName) => {
1373
+ return markoExtReg.test(fileName) ? isMarkoTSFile(fileName) ? ts2.ScriptKind.TS : ts2.ScriptKind.JS : getScriptKind(fileName);
1374
+ };
1375
+ }
1376
+ const getScriptSnapshot = host.getScriptSnapshot.bind(host);
1377
+ host.getScriptSnapshot = (filename) => {
1378
+ if (markoExtReg.test(filename)) {
1379
+ let cached = cache.get(filename);
1380
+ if (!cached) {
1381
+ const code = host.readFile(filename, "utf-8") || "";
1382
+ const markoProject = getMarkoProject(path8.dirname(filename));
1383
+ cached = extractScript({
1384
+ ts: ts2,
1385
+ parsed: parse2(code, filename),
1386
+ lookup: markoProject.lookup,
1387
+ scriptLang: getScriptLang(filename, ts2, host, scriptLang),
1388
+ runtimeTypesCode: projectTypeLibs.markoTypesCode,
1389
+ componentFilename: getComponentFilename(filename, host)
1390
+ });
1391
+ cached.snapshot = ts2.ScriptSnapshot.fromString(cached.toString());
1392
+ cache.set(filename, cached);
1393
+ }
1394
+ return cached.snapshot;
1395
+ }
1396
+ return getScriptSnapshot(filename);
1397
+ };
1398
+ const readDirectory2 = (_b = host.readDirectory) == null ? void 0 : _b.bind(host);
1399
+ if (readDirectory2) {
1400
+ host.readDirectory = (path10, extensions, exclude, include, depth) => {
1401
+ return readDirectory2(
1402
+ path10,
1403
+ extensions == null ? void 0 : extensions.concat(markoExt),
1404
+ exclude,
1405
+ include,
1406
+ depth
1407
+ );
1408
+ };
1409
+ }
1410
+ const resolveModuleNames = (_c = host.resolveModuleNames) == null ? void 0 : _c.bind(host);
1411
+ if (resolveModuleNames) {
1412
+ 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--; ) {
1422
+ const moduleName = moduleNames[i];
1423
+ if (!resolvedModules[i] && markoExtReg.test(moduleName)) {
1424
+ 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
+ };
1613
1436
  }
1614
- }
1615
- const key = min * 3;
1616
- const generatedStart = generatedMap[key];
1617
- const sourceStart = generatedMap[key + 1];
1618
- const sourceEnd = generatedMap[key + 2];
1619
- return sourceEnd - sourceStart < generatedOffset - generatedStart ? void 0 : sourceStart + (generatedOffset - generatedStart);
1620
- },
1621
- generatedOffsetAt(sourceOffset) {
1622
- let max = sourceMap.length / 3;
1623
- let min = 0;
1624
- while (min < max) {
1625
- const mid = 1 + min + max >>> 1;
1626
- if (sourceMap[mid * 3 + 1] <= sourceOffset) {
1627
- min = mid;
1628
- } else {
1629
- max = mid - 1;
1437
+ } else if (moduleName[0] !== "*") {
1438
+ const [, nodeModuleName, relativeModulePath] = modulePartsReg.exec(moduleName);
1439
+ const { resolvedModule } = ts2.resolveModuleName(
1440
+ `${nodeModuleName}/package.json`,
1441
+ containingFile,
1442
+ options,
1443
+ host
1444
+ );
1445
+ if (resolvedModule) {
1446
+ const resolvedFileName = path8.join(
1447
+ resolvedModule.resolvedFileName,
1448
+ "..",
1449
+ relativeModulePath
1450
+ );
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
+ }
1630
1459
  }
1631
1460
  }
1632
- const key = min * 3;
1633
- const sourceStart = sourceMap[key + 1];
1634
- const sourceEnd = sourceMap[key + 2];
1635
- if (sourceOffset < sourceStart || sourceOffset > sourceEnd)
1636
- return void 0;
1637
- const generatedStart = sourceMap[key];
1638
- return generatedStart + (sourceOffset - sourceStart);
1639
1461
  }
1640
- };
1641
- }
1642
- };
1462
+ }
1463
+ return resolvedModules;
1464
+ };
1465
+ }
1466
+ return host;
1643
1467
  }
1644
1468
 
1645
- // src/service/stylesheet/extract.ts
1646
- function extractStyleSheets(code, program, lookup) {
1647
- let placeholderId = 0;
1648
- const extractorsByExt = {};
1649
- const read = (range) => code.slice(range.start, range.end);
1650
- const getExtractor = (ext) => extractorsByExt[ext] || (extractorsByExt[ext] = createExtractor(code));
1651
- const getFileExtFromTag = (tag) => {
1652
- const prefixEnd = tag.shorthandClassNames ? tag.shorthandClassNames.at(-1).end : tag.name.end;
1653
- return tag.shorthandClassNames ? read({
1654
- start: tag.shorthandClassNames[0].start,
1655
- end: prefixEnd
1656
- }).replace(/^.*\./, "") : "css";
1657
- };
1658
- const visit = (node) => {
1659
- var _a, _b;
1660
- switch (node.type) {
1661
- case 14 /* AttrTag */:
1662
- if (node.body) {
1663
- for (const child of node.body) {
1664
- visit(child);
1665
- }
1469
+ // src/service/script/index.ts
1470
+ var IGNORE_DIAG_REG = /^(?:Expression|Identifier|['"][^\w]['"]) expected.$/;
1471
+ var extractCache = /* @__PURE__ */ new Map();
1472
+ var snapshotCache = /* @__PURE__ */ new Map();
1473
+ var markoFileReg = /\.marko$/;
1474
+ var tsTriggerChars = /* @__PURE__ */ new Set([".", '"', "'", "`", "/", "@", "<", "#", " "]);
1475
+ var optionalModifierReg = /\boptional\b/;
1476
+ var deprecatedModifierReg = /\bdeprecated\b/;
1477
+ var colorModifierReg = /\bcolor\b/;
1478
+ var localInternalsPrefix = "__marko_internal_";
1479
+ var ScriptService = {
1480
+ commands: {
1481
+ "$/showScriptOutput": async (uri) => {
1482
+ const doc = get(uri);
1483
+ if ((doc == null ? void 0 : doc.languageId) !== "marko")
1484
+ return;
1485
+ const filename = getFSPath(doc);
1486
+ if (!filename)
1487
+ return;
1488
+ const project = getTSProject(filename);
1489
+ const extracted = processScript(doc, project);
1490
+ const lang = getScriptLang(
1491
+ filename,
1492
+ ts,
1493
+ project.host,
1494
+ project.markoScriptLang
1495
+ );
1496
+ const generated = extracted.toString();
1497
+ const content = (() => {
1498
+ try {
1499
+ return prettier2.format(generated, {
1500
+ parser: lang === ScriptLang3.ts ? "typescript" : "babel"
1501
+ });
1502
+ } catch {
1503
+ return generated;
1666
1504
  }
1667
- break;
1668
- case 1 /* Tag */:
1669
- if (node.nameText === "style" && node.concise && node.attrs) {
1670
- const block = node.attrs.at(-1);
1671
- if (block.type === 8 /* AttrNamed */ && code[block.start] === "{") {
1672
- getExtractor(getFileExtFromTag(node)).write`${{
1673
- start: block.start + 1,
1674
- end: block.end - 1
1675
- }}`;
1676
- break;
1505
+ })();
1506
+ return {
1507
+ language: lang === ScriptLang3.ts ? "typescript" : "javascript",
1508
+ content
1509
+ };
1510
+ }
1511
+ },
1512
+ async initialize() {
1513
+ onConfigChange(() => {
1514
+ snapshotCache.clear();
1515
+ });
1516
+ onFileChange((doc) => {
1517
+ if (doc) {
1518
+ const filename = getFSPath(doc);
1519
+ extractCache.delete(filename);
1520
+ snapshotCache.delete(filename);
1521
+ } else {
1522
+ extractCache.clear();
1523
+ snapshotCache.clear();
1524
+ }
1525
+ });
1526
+ },
1527
+ async doComplete(doc, params) {
1528
+ var _a;
1529
+ const fileName = getFSPath(doc);
1530
+ if (!fileName)
1531
+ return;
1532
+ const project = getTSProject(fileName);
1533
+ const extracted = processScript(doc, project);
1534
+ const sourceOffset = doc.offsetAt(params.position);
1535
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1536
+ if (generatedOffset === void 0)
1537
+ return;
1538
+ const completions = project.service.getCompletionsAtPosition(
1539
+ fileName,
1540
+ generatedOffset,
1541
+ {
1542
+ ...await getPreferences(project.markoScriptLang),
1543
+ ...params.context,
1544
+ triggerCharacter: getTSTriggerChar((_a = params.context) == null ? void 0 : _a.triggerCharacter)
1545
+ }
1546
+ );
1547
+ if (!(completions == null ? void 0 : completions.entries.length))
1548
+ return;
1549
+ const result = [];
1550
+ for (const completion of completions.entries) {
1551
+ let { name: label, insertText, sortText } = completion;
1552
+ if (label.startsWith(localInternalsPrefix))
1553
+ continue;
1554
+ const { replacementSpan } = completion;
1555
+ let textEdit;
1556
+ let detail;
1557
+ let kind;
1558
+ let tags;
1559
+ let labelDetails;
1560
+ let source = completion.source;
1561
+ if (source && completion.hasAction) {
1562
+ if (source[0] === ".") {
1563
+ source = path9.resolve(fileName, "..", source);
1564
+ }
1565
+ detail = relativeImportPath(fileName, source);
1566
+ sortText = `\uFFFF${sortText}`;
1567
+ } else if (completion.sourceDisplay) {
1568
+ const description = ts.displayPartsToString(completion.sourceDisplay);
1569
+ if (description !== label) {
1570
+ labelDetails = { description };
1571
+ }
1572
+ }
1573
+ if (completion.kindModifiers) {
1574
+ if (optionalModifierReg.test(completion.kindModifiers)) {
1575
+ insertText = label;
1576
+ label += "?";
1577
+ }
1578
+ if (deprecatedModifierReg.test(completion.kindModifiers)) {
1579
+ tags = [CompletionItemTag2.Deprecated];
1580
+ }
1581
+ if (colorModifierReg.test(completion.kindModifiers)) {
1582
+ kind = CompletionItemKind5.Color;
1583
+ }
1584
+ }
1585
+ if (replacementSpan) {
1586
+ const sourceRange = sourceLocationAtTextSpan(
1587
+ extracted,
1588
+ replacementSpan
1589
+ );
1590
+ if (sourceRange) {
1591
+ textEdit = {
1592
+ range: sourceRange,
1593
+ newText: insertText || label
1594
+ };
1595
+ } else {
1596
+ continue;
1597
+ }
1598
+ }
1599
+ result.push({
1600
+ tags,
1601
+ label,
1602
+ detail,
1603
+ textEdit,
1604
+ sortText,
1605
+ insertText,
1606
+ labelDetails,
1607
+ filterText: insertText,
1608
+ preselect: completion.isRecommended || void 0,
1609
+ kind: kind || convertCompletionItemKind(completion.kind),
1610
+ insertTextFormat: completion.isSnippet ? InsertTextFormat4.Snippet : void 0,
1611
+ data: completion.data && {
1612
+ originalData: completion.data,
1613
+ originalName: completion.name,
1614
+ originalSource: source,
1615
+ generatedOffset,
1616
+ fileName
1617
+ }
1618
+ });
1619
+ }
1620
+ return {
1621
+ isIncomplete: true,
1622
+ items: result
1623
+ };
1624
+ },
1625
+ async doCompletionResolve(item) {
1626
+ const { data } = item;
1627
+ if (!data)
1628
+ return;
1629
+ const { fileName } = data;
1630
+ if (!fileName)
1631
+ return;
1632
+ const doc = get(filenameToURI(fileName));
1633
+ if (!doc)
1634
+ return;
1635
+ const project = getTSProject(fileName);
1636
+ const detail = project.service.getCompletionEntryDetails(
1637
+ fileName,
1638
+ data.generatedOffset,
1639
+ data.originalName,
1640
+ {},
1641
+ data.originalSource,
1642
+ await getPreferences(project.markoScriptLang),
1643
+ data.originalData
1644
+ );
1645
+ if (!(detail == null ? void 0 : detail.codeActions))
1646
+ return;
1647
+ const extracted = processScript(doc, project);
1648
+ const textEdits = item.additionalTextEdits = item.additionalTextEdits || [];
1649
+ for (const action of detail.codeActions) {
1650
+ for (const change of action.changes) {
1651
+ if (change.fileName !== fileName)
1652
+ 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
+ });
1677
1665
  }
1678
1666
  }
1679
- if (node.body) {
1680
- if (node.nameText === "style") {
1681
- const ext = getFileExtFromTag(node);
1682
- for (const child of node.body) {
1683
- switch (child.type) {
1684
- case 15 /* Text */:
1685
- getExtractor(ext).write`${child}`;
1686
- break;
1687
- case 21 /* Placeholder */:
1688
- getExtractor(ext).write`${`var(--_${placeholderId++})`}`;
1689
- break;
1690
- }
1691
- }
1667
+ }
1668
+ }
1669
+ return item;
1670
+ },
1671
+ findDefinition(doc, params) {
1672
+ const fileName = getFSPath(doc);
1673
+ if (!fileName)
1674
+ return;
1675
+ const project = getTSProject(fileName);
1676
+ const extracted = processScript(doc, project);
1677
+ const sourceOffset = doc.offsetAt(params.position);
1678
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1679
+ if (generatedOffset === void 0)
1680
+ return;
1681
+ const boundary = project.service.getDefinitionAndBoundSpan(
1682
+ fileName,
1683
+ generatedOffset
1684
+ );
1685
+ if (!(boundary == null ? void 0 : boundary.definitions))
1686
+ return;
1687
+ const originSelectionRange = sourceLocationAtTextSpan(
1688
+ extracted,
1689
+ boundary.textSpan
1690
+ );
1691
+ let result;
1692
+ for (const def of boundary.definitions) {
1693
+ const targetUri = filenameToURI(def.fileName);
1694
+ const defDoc = get(targetUri);
1695
+ if (!defDoc)
1696
+ continue;
1697
+ let link;
1698
+ if (markoFileReg.test(targetUri)) {
1699
+ const extracted2 = processScript(defDoc, project);
1700
+ const targetSelectionRange = sourceLocationAtTextSpan(extracted2, def.textSpan) || START_LOCATION;
1701
+ const targetRange = def.contextSpan && sourceLocationAtTextSpan(extracted2, def.contextSpan) || START_LOCATION;
1702
+ link = {
1703
+ targetUri,
1704
+ targetRange,
1705
+ targetSelectionRange,
1706
+ originSelectionRange
1707
+ };
1708
+ } else {
1709
+ link = {
1710
+ targetUri,
1711
+ targetRange: def.contextSpan ? docLocationAtTextSpan(defDoc, def.contextSpan) : START_LOCATION,
1712
+ targetSelectionRange: docLocationAtTextSpan(defDoc, def.textSpan),
1713
+ originSelectionRange
1714
+ };
1715
+ }
1716
+ if (link) {
1717
+ if (result) {
1718
+ if (Array.isArray(result)) {
1719
+ result.push(link);
1692
1720
  } else {
1693
- for (const child of node.body) {
1694
- visit(child);
1695
- }
1721
+ result = [result, link];
1696
1722
  }
1723
+ } else {
1724
+ result = link;
1725
+ }
1726
+ }
1727
+ }
1728
+ return result;
1729
+ },
1730
+ doHover(doc, params) {
1731
+ const fileName = getFSPath(doc);
1732
+ if (!fileName)
1733
+ return;
1734
+ const project = getTSProject(fileName);
1735
+ const extracted = processScript(doc, project);
1736
+ const sourceOffset = doc.offsetAt(params.position);
1737
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1738
+ if (generatedOffset === void 0)
1739
+ return;
1740
+ const quickInfo = project.service.getQuickInfoAtPosition(
1741
+ fileName,
1742
+ generatedOffset
1743
+ );
1744
+ if (!quickInfo)
1745
+ return;
1746
+ const sourceRange = sourceLocationAtTextSpan(extracted, quickInfo.textSpan);
1747
+ if (!sourceRange)
1748
+ return;
1749
+ let contents = "";
1750
+ const displayParts = ts.displayPartsToString(quickInfo.displayParts);
1751
+ if (displayParts) {
1752
+ contents += `\`\`\`typescript
1753
+ ${displayParts}
1754
+ \`\`\``;
1755
+ }
1756
+ const documentation = printDocumentation(
1757
+ quickInfo.documentation,
1758
+ quickInfo.tags
1759
+ );
1760
+ if (documentation) {
1761
+ contents += `
1762
+ ---
1763
+ ${documentation}`;
1764
+ }
1765
+ return {
1766
+ range: sourceRange,
1767
+ contents
1768
+ };
1769
+ },
1770
+ doRename(doc, params) {
1771
+ const fileName = getFSPath(doc);
1772
+ if (!fileName)
1773
+ return;
1774
+ const project = getTSProject(fileName);
1775
+ const extracted = processScript(doc, project);
1776
+ const sourceOffset = doc.offsetAt(params.position);
1777
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1778
+ if (generatedOffset === void 0)
1779
+ return;
1780
+ const renameLocations = project.service.findRenameLocations(
1781
+ fileName,
1782
+ generatedOffset,
1783
+ false,
1784
+ false,
1785
+ false
1786
+ );
1787
+ if (!renameLocations)
1788
+ return;
1789
+ const changes = {};
1790
+ for (const rename of renameLocations) {
1791
+ const renameURI = filenameToURI(rename.fileName);
1792
+ const renameDoc = get(renameURI);
1793
+ let edit;
1794
+ if (!renameDoc)
1795
+ continue;
1796
+ if (markoFileReg.test(renameURI)) {
1797
+ const extracted2 = processScript(renameDoc, project);
1798
+ const sourceRange = sourceLocationAtTextSpan(
1799
+ extracted2,
1800
+ rename.textSpan
1801
+ );
1802
+ if (sourceRange) {
1803
+ edit = {
1804
+ newText: params.newName,
1805
+ range: sourceRange
1806
+ };
1807
+ }
1808
+ } else {
1809
+ edit = {
1810
+ newText: params.newName,
1811
+ range: docLocationAtTextSpan(renameDoc, rename.textSpan)
1812
+ };
1813
+ }
1814
+ if (edit) {
1815
+ if (changes[renameURI]) {
1816
+ changes[renameURI].push(edit);
1817
+ } else {
1818
+ changes[renameURI] = [edit];
1819
+ }
1820
+ }
1821
+ }
1822
+ return {
1823
+ changes
1824
+ };
1825
+ },
1826
+ doValidate(doc) {
1827
+ const fileName = getFSPath(doc);
1828
+ if (!fileName)
1829
+ return;
1830
+ const project = getTSProject(fileName);
1831
+ const extracted = processScript(doc, project);
1832
+ let results;
1833
+ for (const tsDiag of project.service.getSuggestionDiagnostics(fileName)) {
1834
+ addDiag(tsDiag);
1835
+ }
1836
+ for (const tsDiag of project.service.getSyntacticDiagnostics(fileName)) {
1837
+ addDiag(tsDiag);
1838
+ }
1839
+ for (const tsDiag of project.service.getSemanticDiagnostics(fileName)) {
1840
+ addDiag(tsDiag);
1841
+ }
1842
+ return results;
1843
+ function addDiag(tsDiag) {
1844
+ const diag = convertDiag(extracted, tsDiag);
1845
+ if (diag && !IGNORE_DIAG_REG.test(diag.message)) {
1846
+ if (results) {
1847
+ results.push(diag);
1848
+ } else {
1849
+ results = [diag];
1850
+ }
1851
+ }
1852
+ }
1853
+ }
1854
+ };
1855
+ 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
+ });
1869
+ }
1870
+ function sourceLocationAtTextSpan(extracted, { start, length }) {
1871
+ if (start === 0 && length === 0)
1872
+ return START_LOCATION;
1873
+ return extracted.sourceLocationAt(start, start + length);
1874
+ }
1875
+ function docLocationAtTextSpan(doc, { start, length }) {
1876
+ return {
1877
+ start: doc.positionAt(start),
1878
+ end: doc.positionAt(start + length)
1879
+ };
1880
+ }
1881
+ function getTSProject(docFsPath) {
1882
+ var _a;
1883
+ let configPath;
1884
+ let markoScriptLang = ScriptLang3.js;
1885
+ if (docFsPath) {
1886
+ configPath = ts.findConfigFile(
1887
+ docFsPath,
1888
+ ts.sys.fileExists,
1889
+ "tsconfig.json"
1890
+ );
1891
+ if (configPath) {
1892
+ markoScriptLang = ScriptLang3.ts;
1893
+ } else {
1894
+ configPath = ts.findConfigFile(
1895
+ docFsPath,
1896
+ ts.sys.fileExists,
1897
+ "jsconfig.json"
1898
+ );
1899
+ }
1900
+ }
1901
+ const rootDir = configPath && path9.dirname(configPath) || process.cwd();
1902
+ const markoProject = getMarkoProject(configPath && rootDir);
1903
+ let projectCache = markoProject.cache.get(getTSProject);
1904
+ let cached;
1905
+ if (projectCache) {
1906
+ cached = projectCache.get(rootDir);
1907
+ if (cached)
1908
+ return cached;
1909
+ } else {
1910
+ projectCache = /* @__PURE__ */ new Map();
1911
+ markoProject.cache.set(getTSProject, projectCache);
1912
+ }
1913
+ const { fileNames, options, projectReferences } = ts.parseJsonConfigFileContent(
1914
+ configPath && ts.readConfigFile(configPath, ts.sys.readFile).config || {
1915
+ compilerOptions: { lib: ["dom", "node", "esnext"] }
1916
+ },
1917
+ ts.sys,
1918
+ rootDir,
1919
+ void 0,
1920
+ configPath,
1921
+ void 0,
1922
+ [
1923
+ {
1924
+ extension: ".marko",
1925
+ isMixedContent: false,
1926
+ scriptKind: ts.ScriptKind.Deferred
1927
+ }
1928
+ ]
1929
+ );
1930
+ const potentialGlobalFiles = new Set(
1931
+ fileNames.filter((file) => /\.[cm]?ts$/.test(file))
1932
+ );
1933
+ options.rootDir ??= rootDir;
1934
+ options.module = ts.ModuleKind.ESNext;
1935
+ options.moduleResolution = ts.ModuleResolutionKind.NodeJs;
1936
+ options.noEmit = options.allowJs = options.declaration = options.skipLibCheck = options.isolatedModules = options.resolveJsonModule = options.skipDefaultLibCheck = options.allowNonTsExtensions = true;
1937
+ 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,
1940
+ ts.getDefaultLibFileName(options)
1941
+ );
1942
+ const host = patch(
1943
+ ts,
1944
+ markoScriptLang,
1945
+ extractCache,
1946
+ {
1947
+ getNewLine() {
1948
+ return ts.sys.newLine;
1949
+ },
1950
+ useCaseSensitiveFileNames() {
1951
+ return ts.sys.useCaseSensitiveFileNames;
1952
+ },
1953
+ getCompilationSettings() {
1954
+ return options;
1955
+ },
1956
+ getCurrentDirectory() {
1957
+ return options.rootDir;
1958
+ },
1959
+ getProjectVersion() {
1960
+ return projectVersion.toString(32);
1961
+ },
1962
+ getDefaultLibFileName() {
1963
+ return defaultLibFile;
1964
+ },
1965
+ getProjectReferences() {
1966
+ return projectReferences;
1967
+ },
1968
+ resolveModuleNames(moduleNames, containingFile) {
1969
+ return moduleNames.map((moduleName) => {
1970
+ return ts.resolveModuleName(moduleName, containingFile, options, host).resolvedModule;
1971
+ });
1972
+ },
1973
+ readDirectory: ts.sys.readDirectory,
1974
+ readFile: (filename) => {
1975
+ var _a2;
1976
+ return (_a2 = get(filenameToURI(filename))) == null ? void 0 : _a2.getText();
1977
+ },
1978
+ fileExists: (filename) => exists(filenameToURI(filename)),
1979
+ getScriptFileNames() {
1980
+ const result = new Set(potentialGlobalFiles);
1981
+ for (const doc of getAllOpen()) {
1982
+ const { scheme, fsPath } = URI6.parse(doc.uri);
1983
+ if (scheme === "file")
1984
+ result.add(fsPath);
1697
1985
  }
1698
- if (node.attrs) {
1699
- for (const attr of node.attrs) {
1700
- if (attr.type === 8 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 11 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])) {
1701
- const name = read(attr.name);
1702
- if (name === "#style" || name === "style" && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
1703
- getExtractor("css").write`:root{${{
1704
- start: attr.value.value.start + 1,
1705
- end: attr.value.value.end - 1
1706
- }}}`;
1707
- }
1708
- }
1709
- }
1986
+ return [...result];
1987
+ },
1988
+ getScriptVersion(filename) {
1989
+ var _a2;
1990
+ return `${((_a2 = get(filenameToURI(filename))) == null ? void 0 : _a2.version) ?? -1}`;
1991
+ },
1992
+ getScriptKind(filename) {
1993
+ switch (path9.extname(filename)) {
1994
+ case ts.Extension.Js:
1995
+ return ts.ScriptKind.JS;
1996
+ case ts.Extension.Jsx:
1997
+ return ts.ScriptKind.JSX;
1998
+ case ts.Extension.Ts:
1999
+ return ts.ScriptKind.TS;
2000
+ case ts.Extension.Tsx:
2001
+ return ts.ScriptKind.TSX;
2002
+ case ts.Extension.Json:
2003
+ return ts.ScriptKind.JSON;
2004
+ default:
2005
+ return ts.ScriptKind.Unknown;
1710
2006
  }
1711
- break;
2007
+ },
2008
+ getScriptSnapshot(filename) {
2009
+ let snapshot = snapshotCache.get(filename);
2010
+ if (!snapshot) {
2011
+ const doc = get(filenameToURI(filename));
2012
+ if (!doc)
2013
+ return;
2014
+ snapshot = ts.ScriptSnapshot.fromString(doc.getText());
2015
+ snapshotCache.set(filename, snapshot);
2016
+ }
2017
+ return snapshot;
2018
+ }
1712
2019
  }
2020
+ );
2021
+ const tsProject = {
2022
+ host,
2023
+ rootDir: options.rootDir,
2024
+ service: ts.createLanguageService(host),
2025
+ markoProject,
2026
+ markoScriptLang,
2027
+ markoProjectTypeLibs: getProjectTypeLibs(markoProject, ts, host)
1713
2028
  };
1714
- for (const node of program.body)
1715
- visit(node);
1716
- const resultsByExt = {};
1717
- for (const ext in extractorsByExt) {
1718
- resultsByExt[ext] = extractorsByExt[ext].end();
2029
+ projectCache.set(rootDir, tsProject);
2030
+ return tsProject;
2031
+ }
2032
+ function filenameToURI(filename) {
2033
+ return URI6.file(filename).toString();
2034
+ }
2035
+ async function getPreferences(scriptLang) {
2036
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2037
+ const configName = scriptLang === ScriptLang3.js ? "javascript" : "typescript";
2038
+ const [preferencesConfig, suggestConfig, inlayHintsConfig] = await Promise.all([
2039
+ getConfig(`${configName}.preferences`),
2040
+ getConfig(`${configName}.suggest`),
2041
+ getConfig(`${configName}.inlayHints`)
2042
+ ]);
2043
+ return {
2044
+ disableSuggestions: suggestConfig.enabled === false,
2045
+ quotePreference: preferencesConfig.quoteStyle || "auto",
2046
+ includeCompletionsForModuleExports: suggestConfig.autoImports ?? true,
2047
+ includeCompletionsForImportStatements: suggestConfig.includeCompletionsForImportStatements ?? true,
2048
+ includeCompletionsWithSnippetText: suggestConfig.includeCompletionsWithSnippetText ?? true,
2049
+ includeAutomaticOptionalChainCompletions: suggestConfig.includeAutomaticOptionalChainCompletions ?? true,
2050
+ includeCompletionsWithInsertText: true,
2051
+ includeCompletionsWithClassMemberSnippets: ((_a = suggestConfig.classMemberSnippets) == null ? void 0 : _a.enabled) ?? true,
2052
+ includeCompletionsWithObjectLiteralMethodSnippets: ((_b = suggestConfig.objectLiteralMethodSnippets) == null ? void 0 : _b.enabled) ?? true,
2053
+ useLabelDetailsInCompletionEntries: true,
2054
+ allowIncompleteCompletions: true,
2055
+ importModuleSpecifierPreference: preferencesConfig.importModuleSpecifierPreference,
2056
+ importModuleSpecifierEnding: preferencesConfig.importModuleSpecifierEnding || "auto",
2057
+ allowTextChangesInNewFiles: true,
2058
+ providePrefixAndSuffixTextForRename: true,
2059
+ includePackageJsonAutoImports: preferencesConfig.includePackageJsonAutoImports ?? true,
2060
+ provideRefactorNotApplicableReason: true,
2061
+ jsxAttributeCompletionStyle: preferencesConfig.jsxAttributeCompletionStyle ?? "auto",
2062
+ includeInlayParameterNameHints: ((_c = inlayHintsConfig.parameterNames) == null ? void 0 : _c.enabled) ?? "none",
2063
+ includeInlayParameterNameHintsWhenArgumentMatchesName: !((_d = inlayHintsConfig.parameterNames) == null ? void 0 : _d.suppressWhenArgumentMatchesName),
2064
+ includeInlayFunctionParameterTypeHints: ((_e = inlayHintsConfig.parameterTypes) == null ? void 0 : _e.enabled) ?? true,
2065
+ includeInlayVariableTypeHints: ((_f = inlayHintsConfig.variableTypes) == null ? void 0 : _f.enabled) ?? true,
2066
+ includeInlayPropertyDeclarationTypeHints: ((_g = inlayHintsConfig.propertyDeclarationTypes) == null ? void 0 : _g.enabled) ?? true,
2067
+ includeInlayFunctionLikeReturnTypeHints: ((_h = inlayHintsConfig.functionLikeReturnTypes) == null ? void 0 : _h.enabled) ?? true,
2068
+ includeInlayEnumMemberValueHints: ((_i = inlayHintsConfig.enumMemberValues) == null ? void 0 : _i.enabled) ?? true
2069
+ };
2070
+ }
2071
+ function printDocumentation(docs2, tags) {
2072
+ let result = "";
2073
+ if (docs2) {
2074
+ result += ts.displayPartsToString(docs2);
2075
+ }
2076
+ if (tags) {
2077
+ for (const tag of tags) {
2078
+ const text = ts.displayPartsToString(tag.text);
2079
+ result += `*@${tag.name}*${text ? /\n/.test(text) ? `
2080
+ ${text}` : `- ${text}` : ""}`;
2081
+ }
2082
+ }
2083
+ return result;
2084
+ }
2085
+ function convertDiag(extracted, tsDiag) {
2086
+ const sourceRange = tsDiag.start === void 0 ? START_LOCATION : sourceLocationAtTextSpan(extracted, tsDiag);
2087
+ if (sourceRange) {
2088
+ return {
2089
+ range: sourceRange,
2090
+ source: "script",
2091
+ code: tsDiag.code,
2092
+ tags: convertDiagTags(tsDiag),
2093
+ severity: convertDiagSeverity(tsDiag),
2094
+ message: ts.flattenDiagnosticMessageText(tsDiag.messageText, "\n")
2095
+ };
2096
+ }
2097
+ }
2098
+ function convertDiagSeverity(tsDiag) {
2099
+ switch (tsDiag.category) {
2100
+ case ts.DiagnosticCategory.Error:
2101
+ return DiagnosticSeverity2.Error;
2102
+ case ts.DiagnosticCategory.Warning:
2103
+ return DiagnosticSeverity2.Warning;
2104
+ case ts.DiagnosticCategory.Suggestion:
2105
+ return DiagnosticSeverity2.Hint;
2106
+ default:
2107
+ return DiagnosticSeverity2.Information;
2108
+ }
2109
+ }
2110
+ function convertDiagTags(tsDiag) {
2111
+ let tags;
2112
+ if (tsDiag.reportsDeprecated) {
2113
+ tags = [DiagnosticTag.Deprecated];
2114
+ }
2115
+ if (tsDiag.reportsUnnecessary) {
2116
+ if (tags)
2117
+ tags.push(DiagnosticTag.Unnecessary);
2118
+ else
2119
+ tags = [DiagnosticTag.Unnecessary];
2120
+ }
2121
+ return tags;
2122
+ }
2123
+ function convertCompletionItemKind(kind) {
2124
+ switch (kind) {
2125
+ case ts.ScriptElementKind.warning:
2126
+ case ts.ScriptElementKind.linkText:
2127
+ return CompletionItemKind5.Text;
2128
+ case ts.ScriptElementKind.keyword:
2129
+ case ts.ScriptElementKind.primitiveType:
2130
+ return CompletionItemKind5.Keyword;
2131
+ case ts.ScriptElementKind.scriptElement:
2132
+ return CompletionItemKind5.File;
2133
+ case ts.ScriptElementKind.directory:
2134
+ return CompletionItemKind5.Folder;
2135
+ case ts.ScriptElementKind.label:
2136
+ case ts.ScriptElementKind.string:
2137
+ return CompletionItemKind5.Constant;
2138
+ case ts.ScriptElementKind.moduleElement:
2139
+ case ts.ScriptElementKind.externalModuleName:
2140
+ return CompletionItemKind5.Module;
2141
+ case ts.ScriptElementKind.typeElement:
2142
+ case ts.ScriptElementKind.classElement:
2143
+ case ts.ScriptElementKind.localClassElement:
2144
+ return CompletionItemKind5.Class;
2145
+ case ts.ScriptElementKind.interfaceElement:
2146
+ return CompletionItemKind5.Interface;
2147
+ case ts.ScriptElementKind.enumElement:
2148
+ return CompletionItemKind5.Enum;
2149
+ case ts.ScriptElementKind.enumMemberElement:
2150
+ return CompletionItemKind5.EnumMember;
2151
+ case ts.ScriptElementKind.alias:
2152
+ case ts.ScriptElementKind.letElement:
2153
+ case ts.ScriptElementKind.constElement:
2154
+ case ts.ScriptElementKind.variableElement:
2155
+ case ts.ScriptElementKind.parameterElement:
2156
+ case ts.ScriptElementKind.localVariableElement:
2157
+ return CompletionItemKind5.Variable;
2158
+ case ts.ScriptElementKind.functionElement:
2159
+ case ts.ScriptElementKind.localFunctionElement:
2160
+ return CompletionItemKind5.Function;
2161
+ case ts.ScriptElementKind.callSignatureElement:
2162
+ case ts.ScriptElementKind.memberFunctionElement:
2163
+ case ts.ScriptElementKind.indexSignatureElement:
2164
+ case ts.ScriptElementKind.constructSignatureElement:
2165
+ return CompletionItemKind5.Method;
2166
+ case ts.ScriptElementKind.memberGetAccessorElement:
2167
+ case ts.ScriptElementKind.memberSetAccessorElement:
2168
+ case ts.ScriptElementKind.memberVariableElement:
2169
+ return CompletionItemKind5.Field;
2170
+ case ts.ScriptElementKind.constructorImplementationElement:
2171
+ return CompletionItemKind5.Constructor;
2172
+ case ts.ScriptElementKind.typeParameterElement:
2173
+ return CompletionItemKind5.TypeParameter;
2174
+ case ts.ScriptElementKind.link:
2175
+ case ts.ScriptElementKind.linkName:
2176
+ return CompletionItemKind5.Reference;
2177
+ default:
2178
+ return CompletionItemKind5.Property;
1719
2179
  }
1720
- return resultsByExt;
2180
+ }
2181
+ function getTSTriggerChar(char) {
2182
+ if (char && tsTriggerChars.has(char))
2183
+ return char;
1721
2184
  }
1722
2185
 
1723
- // src/service/stylesheet/index.ts
1724
- var cache3 = /* @__PURE__ */ new WeakMap();
2186
+ // src/service/style/index.ts
2187
+ import {
2188
+ getCSSLanguageService,
2189
+ getLESSLanguageService,
2190
+ getSCSSLanguageService
2191
+ } from "vscode-css-languageservice";
2192
+ import {
2193
+ TextDocumentEdit
2194
+ } from "vscode-languageserver";
2195
+ import { TextDocument as TextDocument2 } from "vscode-languageserver-textdocument";
2196
+ import { extractStyle } from "@marko/language-tools";
1725
2197
  var services = {
1726
- css: getCSSLanguageService,
1727
- less: getLESSLanguageService,
1728
- scss: getSCSSLanguageService
2198
+ ".css": getCSSLanguageService,
2199
+ ".less": getLESSLanguageService,
2200
+ ".scss": getSCSSLanguageService
1729
2201
  };
1730
2202
  var clientCapabilities;
1731
2203
  var StyleSheetService = {
@@ -1733,70 +2205,58 @@ var StyleSheetService = {
1733
2205
  clientCapabilities = params.capabilities;
1734
2206
  },
1735
2207
  async doComplete(doc, params) {
1736
- const infoByExt = getStyleSheetInfo(doc);
1737
2208
  const sourceOffset = doc.offsetAt(params.position);
1738
- for (const ext in infoByExt) {
1739
- const info = infoByExt[ext];
1740
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
1741
- if (generatedOffset === void 0)
2209
+ for (const style of processStyle(doc)) {
2210
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2211
+ if (generatedPos === void 0)
1742
2212
  continue;
1743
- const { service: service2, virtualDoc } = info;
1744
- const result = await service2.doComplete2(
1745
- virtualDoc,
1746
- virtualDoc.positionAt(generatedOffset),
1747
- info.parsed,
2213
+ const result = await style.service.doComplete2(
2214
+ style.virtualDoc,
2215
+ generatedPos,
2216
+ style.parsed,
1748
2217
  { resolveReference: resolveUrl }
1749
2218
  );
1750
2219
  if (result.itemDefaults) {
1751
2220
  const { editRange } = result.itemDefaults;
1752
2221
  if (editRange) {
1753
2222
  if ("start" in editRange) {
1754
- result.itemDefaults.editRange = getSourceRange(
1755
- doc,
1756
- info,
1757
- editRange
1758
- );
2223
+ result.itemDefaults.editRange = getSourceRange(style, editRange);
1759
2224
  } else {
1760
- editRange.insert = getSourceRange(doc, info, editRange.insert);
1761
- editRange.replace = getSourceRange(doc, info, editRange.replace);
2225
+ editRange.insert = getSourceRange(style, editRange.insert);
2226
+ editRange.replace = getSourceRange(style, editRange.replace);
1762
2227
  }
1763
2228
  }
1764
2229
  }
1765
2230
  for (const item of result.items) {
1766
2231
  if (item.textEdit) {
1767
- item.textEdit = getSourceInsertReplaceEdit(doc, info, item.textEdit);
2232
+ item.textEdit = getSourceInsertReplaceEdit(style, item.textEdit);
1768
2233
  }
1769
2234
  if (item.additionalTextEdits) {
1770
2235
  item.additionalTextEdits = getSourceEdits(
1771
- doc,
1772
- info,
2236
+ style,
1773
2237
  item.additionalTextEdits
1774
2238
  );
1775
2239
  }
1776
2240
  }
1777
2241
  return result;
1778
2242
  }
1779
- return CompletionList2.create([], true);
1780
2243
  },
1781
2244
  findDefinition(doc, params) {
1782
- const infoByExt = getStyleSheetInfo(doc);
1783
2245
  const sourceOffset = doc.offsetAt(params.position);
1784
- for (const ext in infoByExt) {
1785
- const info = infoByExt[ext];
1786
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
1787
- if (generatedOffset === void 0)
2246
+ for (const style of processStyle(doc)) {
2247
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2248
+ if (generatedPos === void 0)
1788
2249
  continue;
1789
- const { service: service2, virtualDoc } = info;
1790
- const result = service2.findDefinition(
1791
- virtualDoc,
1792
- virtualDoc.positionAt(generatedOffset),
1793
- info.parsed
2250
+ const result = style.service.findDefinition(
2251
+ style.virtualDoc,
2252
+ generatedPos,
2253
+ style.parsed
1794
2254
  );
1795
2255
  if (result) {
1796
- const range = getSourceRange(doc, info, result.range);
1797
- if (range) {
2256
+ const sourceRange = getSourceRange(style, result.range);
2257
+ if (sourceRange) {
1798
2258
  return {
1799
- range,
2259
+ range: sourceRange,
1800
2260
  uri: doc.uri
1801
2261
  };
1802
2262
  }
@@ -1805,24 +2265,21 @@ var StyleSheetService = {
1805
2265
  }
1806
2266
  },
1807
2267
  findReferences(doc, params) {
1808
- const infoByExt = getStyleSheetInfo(doc);
1809
2268
  const sourceOffset = doc.offsetAt(params.position);
1810
- for (const ext in infoByExt) {
1811
- const info = infoByExt[ext];
1812
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
1813
- if (generatedOffset === void 0)
2269
+ for (const style of processStyle(doc)) {
2270
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2271
+ if (generatedPos === void 0)
1814
2272
  continue;
1815
- const { service: service2, virtualDoc } = info;
1816
2273
  const result = [];
1817
- for (const location of service2.findReferences(
1818
- virtualDoc,
1819
- virtualDoc.positionAt(generatedOffset),
1820
- info.parsed
2274
+ for (const location of style.service.findReferences(
2275
+ style.virtualDoc,
2276
+ generatedPos,
2277
+ style.parsed
1821
2278
  )) {
1822
- const range = getSourceRange(doc, info, location.range);
1823
- if (range) {
2279
+ const sourceRange = getSourceRange(style, location.range);
2280
+ if (sourceRange) {
1824
2281
  result.push({
1825
- range,
2282
+ range: sourceRange,
1826
2283
  uri: location.uri
1827
2284
  });
1828
2285
  }
@@ -1831,25 +2288,22 @@ var StyleSheetService = {
1831
2288
  }
1832
2289
  },
1833
2290
  findDocumentSymbols(doc) {
1834
- const infoByExt = getStyleSheetInfo(doc);
1835
2291
  const result = [];
1836
- for (const ext in infoByExt) {
1837
- const info = infoByExt[ext];
1838
- const { service: service2, virtualDoc } = info;
1839
- for (const symbol of service2.findDocumentSymbols(
1840
- virtualDoc,
1841
- info.parsed
2292
+ for (const extracted of processStyle(doc)) {
2293
+ for (const symbol of extracted.service.findDocumentSymbols(
2294
+ extracted.virtualDoc,
2295
+ extracted.parsed
1842
2296
  )) {
1843
2297
  if (symbol.location.uri === doc.uri) {
1844
- const range = getSourceRange(doc, info, symbol.location.range);
1845
- if (range) {
2298
+ const sourceRange = getSourceRange(extracted, symbol.location.range);
2299
+ if (sourceRange) {
1846
2300
  result.push({
1847
2301
  kind: symbol.kind,
1848
2302
  name: symbol.name,
1849
2303
  tags: symbol.tags,
1850
2304
  deprecated: symbol.deprecated,
1851
2305
  containerName: symbol.containerName,
1852
- location: { uri: doc.uri, range }
2306
+ location: { uri: doc.uri, range: sourceRange }
1853
2307
  });
1854
2308
  }
1855
2309
  } else {
@@ -1860,20 +2314,17 @@ var StyleSheetService = {
1860
2314
  return result.length ? result : void 0;
1861
2315
  },
1862
2316
  async findDocumentLinks(doc) {
1863
- const infoByExt = getStyleSheetInfo(doc);
1864
2317
  const result = [];
1865
- for (const ext in infoByExt) {
1866
- const info = infoByExt[ext];
1867
- const { service: service2, virtualDoc } = info;
1868
- for (const link of await service2.findDocumentLinks2(
1869
- virtualDoc,
1870
- info.parsed,
2318
+ for (const extracted of processStyle(doc)) {
2319
+ for (const link of await extracted.service.findDocumentLinks2(
2320
+ extracted.virtualDoc,
2321
+ extracted.parsed,
1871
2322
  { resolveReference: resolveUrl }
1872
2323
  )) {
1873
- const range = getSourceRange(doc, info, link.range);
1874
- if (range) {
2324
+ const sourceRange = getSourceRange(extracted, link.range);
2325
+ if (sourceRange) {
1875
2326
  result.push({
1876
- range,
2327
+ range: sourceRange,
1877
2328
  target: link.target,
1878
2329
  tooltip: link.tooltip,
1879
2330
  data: link.data
@@ -1884,24 +2335,21 @@ var StyleSheetService = {
1884
2335
  return result.length ? result : void 0;
1885
2336
  },
1886
2337
  findDocumentHighlights(doc, params) {
1887
- const infoByExt = getStyleSheetInfo(doc);
1888
2338
  const sourceOffset = doc.offsetAt(params.position);
1889
- for (const ext in infoByExt) {
1890
- const info = infoByExt[ext];
1891
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
1892
- if (generatedOffset === void 0)
2339
+ for (const style of processStyle(doc)) {
2340
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2341
+ if (generatedPos === void 0)
1893
2342
  continue;
1894
- const { service: service2, virtualDoc } = info;
1895
2343
  const result = [];
1896
- for (const highlight of service2.findDocumentHighlights(
1897
- virtualDoc,
1898
- virtualDoc.positionAt(generatedOffset),
1899
- info.parsed
2344
+ for (const highlight of style.service.findDocumentHighlights(
2345
+ style.virtualDoc,
2346
+ generatedPos,
2347
+ style.parsed
1900
2348
  )) {
1901
- const range = getSourceRange(doc, info, highlight.range);
1902
- if (range) {
2349
+ const sourceRange = getSourceRange(style, highlight.range);
2350
+ if (sourceRange) {
1903
2351
  result.push({
1904
- range,
2352
+ range: sourceRange,
1905
2353
  kind: highlight.kind
1906
2354
  });
1907
2355
  }
@@ -1910,19 +2358,16 @@ var StyleSheetService = {
1910
2358
  }
1911
2359
  },
1912
2360
  findDocumentColors(doc) {
1913
- const infoByExt = getStyleSheetInfo(doc);
1914
2361
  const result = [];
1915
- for (const ext in infoByExt) {
1916
- const info = infoByExt[ext];
1917
- const { service: service2, virtualDoc } = info;
1918
- for (const colorInfo of service2.findDocumentColors(
1919
- virtualDoc,
1920
- info.parsed
2362
+ for (const extracted of processStyle(doc)) {
2363
+ for (const colorInfo of extracted.service.findDocumentColors(
2364
+ extracted.virtualDoc,
2365
+ extracted.parsed
1921
2366
  )) {
1922
- const range = getSourceRange(doc, info, colorInfo.range);
1923
- if (range) {
2367
+ const sourceRange = getSourceRange(extracted, colorInfo.range);
2368
+ if (sourceRange) {
1924
2369
  result.push({
1925
- range,
2370
+ range: sourceRange,
1926
2371
  color: colorInfo.color
1927
2372
  });
1928
2373
  }
@@ -1931,31 +2376,19 @@ var StyleSheetService = {
1931
2376
  return result.length ? result : void 0;
1932
2377
  },
1933
2378
  getColorPresentations(doc, params) {
1934
- const infoByExt = getStyleSheetInfo(doc);
1935
- const sourceOffset = doc.offsetAt(params.range.start);
1936
- for (const ext in infoByExt) {
1937
- const info = infoByExt[ext];
1938
- const generatedOffsetStart = info.generatedOffsetAt(sourceOffset);
1939
- if (generatedOffsetStart === void 0)
1940
- continue;
1941
- const generatedOffsetEnd = info.generatedOffsetAt(
1942
- doc.offsetAt(params.range.end)
1943
- );
1944
- if (generatedOffsetEnd === void 0)
2379
+ for (const extracted of processStyle(doc)) {
2380
+ const generatedRange = getGeneratedRange(doc, extracted, params.range);
2381
+ if (generatedRange === void 0)
1945
2382
  continue;
1946
- const { service: service2, virtualDoc } = info;
1947
2383
  const result = [];
1948
- for (const colorPresentation of service2.getColorPresentations(
1949
- virtualDoc,
1950
- info.parsed,
2384
+ for (const colorPresentation of extracted.service.getColorPresentations(
2385
+ extracted.virtualDoc,
2386
+ extracted.parsed,
1951
2387
  params.color,
1952
- Range8.create(
1953
- virtualDoc.positionAt(generatedOffsetStart),
1954
- virtualDoc.positionAt(generatedOffsetEnd)
1955
- )
2388
+ generatedRange
1956
2389
  )) {
1957
- const textEdit = colorPresentation.textEdit && getSourceEdit(doc, info, colorPresentation.textEdit);
1958
- const additionalTextEdits = colorPresentation.additionalTextEdits && getSourceEdits(doc, info, colorPresentation.additionalTextEdits);
2390
+ const textEdit = colorPresentation.textEdit && getSourceEdit(extracted, colorPresentation.textEdit);
2391
+ const additionalTextEdits = colorPresentation.additionalTextEdits && getSourceEdits(extracted, colorPresentation.additionalTextEdits);
1959
2392
  if (textEdit || additionalTextEdits) {
1960
2393
  result.push({
1961
2394
  label: colorPresentation.label,
@@ -1968,25 +2401,22 @@ var StyleSheetService = {
1968
2401
  }
1969
2402
  },
1970
2403
  doHover(doc, params) {
1971
- const infoByExt = getStyleSheetInfo(doc);
1972
2404
  const sourceOffset = doc.offsetAt(params.position);
1973
- for (const ext in infoByExt) {
1974
- const info = infoByExt[ext];
1975
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
1976
- if (generatedOffset === void 0)
2405
+ for (const style of processStyle(doc)) {
2406
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2407
+ if (generatedPos === void 0)
1977
2408
  continue;
1978
- const { service: service2, virtualDoc } = info;
1979
- const result = service2.doHover(
1980
- virtualDoc,
1981
- virtualDoc.positionAt(generatedOffset),
1982
- info.parsed
2409
+ const result = style.service.doHover(
2410
+ style.virtualDoc,
2411
+ generatedPos,
2412
+ style.parsed
1983
2413
  );
1984
2414
  if (result) {
1985
2415
  if (result.range) {
1986
- const range = getSourceRange(doc, info, result.range);
1987
- if (range) {
2416
+ const sourceRange = getSourceRange(style, result.range);
2417
+ if (sourceRange) {
1988
2418
  return {
1989
- range,
2419
+ range: sourceRange,
1990
2420
  contents: result.contents
1991
2421
  };
1992
2422
  }
@@ -1997,24 +2427,21 @@ var StyleSheetService = {
1997
2427
  }
1998
2428
  },
1999
2429
  async doRename(doc, params) {
2000
- const infoByExt = getStyleSheetInfo(doc);
2001
2430
  const sourceOffset = doc.offsetAt(params.position);
2002
- for (const ext in infoByExt) {
2003
- const info = infoByExt[ext];
2004
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
2431
+ for (const style of processStyle(doc)) {
2432
+ const generatedOffset = style.extracted.generatedOffsetAt(sourceOffset);
2005
2433
  if (generatedOffset === void 0)
2006
2434
  continue;
2007
- const { service: service2, virtualDoc } = info;
2008
- const result = service2.doRename(
2009
- virtualDoc,
2010
- virtualDoc.positionAt(generatedOffset),
2435
+ const result = style.service.doRename(
2436
+ style.virtualDoc,
2437
+ style.virtualDoc.positionAt(generatedOffset),
2011
2438
  params.newName,
2012
- info.parsed
2439
+ style.parsed
2013
2440
  );
2014
2441
  if (result.changes) {
2015
2442
  for (const uri in result.changes) {
2016
2443
  if (uri === doc.uri) {
2017
- result.changes[uri] = getSourceEdits(doc, info, result.changes[uri]) || [];
2444
+ result.changes[uri] = getSourceEdits(style, result.changes[uri]) || [];
2018
2445
  }
2019
2446
  }
2020
2447
  }
@@ -2022,7 +2449,7 @@ var StyleSheetService = {
2022
2449
  for (const change of result.documentChanges) {
2023
2450
  if (TextDocumentEdit.is(change)) {
2024
2451
  if (change.textDocument.uri === doc.uri) {
2025
- change.edits = getSourceEdits(doc, info, change.edits) || [];
2452
+ change.edits = getSourceEdits(style, change.edits) || [];
2026
2453
  }
2027
2454
  }
2028
2455
  }
@@ -2032,49 +2459,36 @@ var StyleSheetService = {
2032
2459
  },
2033
2460
  doCodeActions(doc, params) {
2034
2461
  var _a;
2035
- const infoByExt = getStyleSheetInfo(doc);
2036
- const sourceOffset = doc.offsetAt(params.range.start);
2037
- for (const ext in infoByExt) {
2038
- const info = infoByExt[ext];
2039
- const generatedOffsetStart = info.generatedOffsetAt(sourceOffset);
2040
- if (generatedOffsetStart === void 0)
2041
- continue;
2042
- const generatedOffsetEnd = info.generatedOffsetAt(
2043
- doc.offsetAt(params.range.end)
2044
- );
2045
- if (generatedOffsetEnd === void 0)
2462
+ for (const extracted of processStyle(doc)) {
2463
+ const generatedRange = getGeneratedRange(doc, extracted, params.range);
2464
+ if (generatedRange === void 0)
2046
2465
  continue;
2047
- const { service: service2, virtualDoc } = info;
2048
- const result = service2.doCodeActions(
2049
- virtualDoc,
2050
- Range8.create(
2051
- virtualDoc.positionAt(generatedOffsetStart),
2052
- virtualDoc.positionAt(generatedOffsetEnd)
2053
- ),
2466
+ const result = extracted.service.doCodeActions(
2467
+ extracted.virtualDoc,
2468
+ generatedRange,
2054
2469
  params.context,
2055
- info.parsed
2470
+ extracted.parsed
2056
2471
  );
2057
2472
  for (const command of result) {
2058
2473
  const edits = (_a = command.arguments) == null ? void 0 : _a[2];
2059
2474
  if (edits && Array.isArray(edits) && isTextEdit(edits[0])) {
2060
- command.arguments[2] = getSourceEdits(doc, info, edits);
2475
+ command.arguments[2] = getSourceEdits(extracted, edits);
2061
2476
  }
2062
2477
  }
2063
2478
  return result;
2064
2479
  }
2065
2480
  },
2066
2481
  doValidate(doc) {
2067
- const infoByExt = getStyleSheetInfo(doc);
2068
2482
  const result = [];
2069
- for (const ext in infoByExt) {
2070
- const info = infoByExt[ext];
2071
- for (const diag of info.service.doValidation(
2072
- info.virtualDoc,
2073
- info.parsed
2483
+ for (const extracted of processStyle(doc)) {
2484
+ for (const diag of extracted.service.doValidation(
2485
+ extracted.virtualDoc,
2486
+ extracted.parsed
2074
2487
  )) {
2075
- const range = getSourceRange(doc, info, diag.range);
2076
- if (range) {
2077
- diag.range = range;
2488
+ const sourceRange = getSourceRange(extracted, diag.range);
2489
+ if (sourceRange) {
2490
+ diag.source = "style";
2491
+ diag.range = sourceRange;
2078
2492
  result.push(diag);
2079
2493
  }
2080
2494
  }
@@ -2082,123 +2496,112 @@ var StyleSheetService = {
2082
2496
  return result.length ? result : void 0;
2083
2497
  }
2084
2498
  };
2085
- function getSourceEdits(doc, info, edits) {
2499
+ function processStyle(doc) {
2500
+ return processDoc(doc, ({ uri, version, parsed, project: { lookup } }) => {
2501
+ var _a;
2502
+ const result = [];
2503
+ for (const [ext, extracted] of extractStyle({
2504
+ parsed,
2505
+ lookup
2506
+ })) {
2507
+ const service2 = (_a = services[ext]) == null ? void 0 : _a.call(services, {
2508
+ fileSystemProvider: file_system_default,
2509
+ clientCapabilities
2510
+ });
2511
+ if (service2) {
2512
+ const virtualDoc = TextDocument2.create(
2513
+ uri,
2514
+ "css",
2515
+ version,
2516
+ extracted.toString()
2517
+ );
2518
+ result.push({
2519
+ service: service2,
2520
+ extracted,
2521
+ virtualDoc,
2522
+ parsed: service2.parseStylesheet(virtualDoc)
2523
+ });
2524
+ }
2525
+ }
2526
+ return result;
2527
+ });
2528
+ }
2529
+ function getSourceEdits(extracted, edits) {
2086
2530
  const result = [];
2087
2531
  for (const edit of edits) {
2088
- const sourceEdit = getSourceEdit(doc, info, edit);
2532
+ const sourceEdit = getSourceEdit(extracted, edit);
2089
2533
  if (sourceEdit) {
2090
2534
  result.push(sourceEdit);
2091
2535
  }
2092
2536
  }
2093
2537
  return result.length ? result : void 0;
2094
2538
  }
2095
- function getSourceEdit(doc, info, textEdit) {
2096
- const range = getSourceRange(doc, info, textEdit.range);
2097
- if (range) {
2539
+ function getSourceEdit(extracted, textEdit) {
2540
+ const sourceRange = getSourceRange(extracted, textEdit.range);
2541
+ if (sourceRange) {
2098
2542
  return {
2099
2543
  newText: textEdit.newText,
2100
- range
2544
+ range: sourceRange
2101
2545
  };
2102
2546
  }
2103
2547
  }
2104
- function getSourceInsertReplaceEdit(doc, info, textEdit) {
2548
+ function getSourceInsertReplaceEdit(extracted, textEdit) {
2105
2549
  if (isTextEdit(textEdit)) {
2106
- return getSourceEdit(doc, info, textEdit);
2550
+ return getSourceEdit(extracted, textEdit);
2107
2551
  } else if (textEdit.replace) {
2108
- const range = getSourceRange(doc, info, textEdit.replace);
2109
- if (range) {
2552
+ const sourceRange = getSourceRange(extracted, textEdit.replace);
2553
+ if (sourceRange) {
2110
2554
  return {
2111
2555
  newText: textEdit.newText,
2112
- replace: range
2556
+ replace: sourceRange
2113
2557
  };
2114
2558
  }
2115
2559
  } else {
2116
- const range = getSourceRange(doc, info, textEdit.insert);
2117
- if (range) {
2560
+ const sourceRange = getSourceRange(extracted, textEdit.insert);
2561
+ if (sourceRange) {
2118
2562
  return {
2119
2563
  newText: textEdit.newText,
2120
- insert: range
2564
+ insert: sourceRange
2121
2565
  };
2122
2566
  }
2123
2567
  }
2124
2568
  }
2125
- function getSourceRange(doc, info, range) {
2126
- const start = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.start));
2127
- if (start === void 0)
2128
- return;
2129
- let end = start;
2130
- if (range.start.line !== range.end.line || range.start.character !== range.end.character) {
2131
- end = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.end));
2132
- if (end === void 0)
2133
- return;
2134
- }
2135
- const pos = doc.positionAt(start);
2136
- return {
2137
- start: pos,
2138
- end: start === end ? pos : doc.positionAt(end)
2139
- };
2569
+ function getSourceRange(style, range) {
2570
+ return style.extracted.sourceLocationAt(
2571
+ style.virtualDoc.offsetAt(range.start),
2572
+ style.virtualDoc.offsetAt(range.end)
2573
+ );
2140
2574
  }
2141
- function getStyleSheetInfo(doc) {
2142
- var _a;
2143
- const parsed = parse2(doc);
2144
- let cached = cache3.get(parsed);
2145
- if (!cached) {
2146
- const results = extractStyleSheets(
2147
- doc.getText(),
2148
- parsed.program,
2149
- getCompilerInfo(doc).lookup
2150
- );
2151
- cached = {};
2152
- for (const ext in results) {
2153
- const service2 = (_a = services[ext]) == null ? void 0 : _a.call(services, {
2154
- fileSystemProvider: file_system_default,
2155
- clientCapabilities
2156
- });
2157
- if (!service2)
2158
- continue;
2159
- const { generated, sourceOffsetAt, generatedOffsetAt } = results[ext];
2160
- const virtualDoc = TextDocument2.create(
2161
- doc.uri,
2162
- "css",
2163
- doc.version,
2164
- generated
2165
- );
2166
- cached[ext] = {
2167
- service: service2,
2168
- virtualDoc,
2169
- sourceOffsetAt,
2170
- generatedOffsetAt,
2171
- parsed: service2.parseStylesheet(virtualDoc)
2172
- };
2173
- }
2174
- cache3.set(parsed, cached);
2175
- }
2176
- return cached;
2575
+ function getGeneratedRange(doc, style, range) {
2576
+ return style.extracted.generatedLocationAt(
2577
+ doc.offsetAt(range.start),
2578
+ doc.offsetAt(range.end)
2579
+ );
2177
2580
  }
2178
2581
  function isTextEdit(edit) {
2179
2582
  return edit.range !== void 0;
2180
2583
  }
2181
2584
 
2182
2585
  // src/service/index.ts
2183
- var plugins = [marko_default, StyleSheetService];
2586
+ var REG_MARKDOWN_CHARS = /[\\`*_{}[\]<>()#+.!|-]/g;
2587
+ var plugins = [marko_default, ScriptService, StyleSheetService];
2184
2588
  var service = {
2589
+ commands: Object.assign({}, ...plugins.map(({ commands }) => commands)),
2185
2590
  async initialize(params) {
2186
- await Promise.all(plugins.map((plugin) => {
2187
- var _a;
2188
- return (_a = plugin.initialize) == null ? void 0 : _a.call(plugin, params);
2189
- }));
2591
+ await Promise.allSettled(
2592
+ plugins.map((plugin) => {
2593
+ var _a;
2594
+ return (_a = plugin.initialize) == null ? void 0 : _a.call(plugin, params);
2595
+ })
2596
+ );
2190
2597
  },
2191
2598
  async doComplete(doc, params, cancel) {
2192
- let items;
2193
2599
  let isIncomplete = false;
2194
- try {
2195
- for (const pending of plugins.map(
2196
- (plugin) => {
2197
- var _a;
2198
- return (_a = plugin.doComplete) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2199
- }
2200
- )) {
2201
- const cur = await pending;
2600
+ const itemsByLabel = /* @__PURE__ */ new Map();
2601
+ await Promise.allSettled(
2602
+ plugins.map(async (plugin) => {
2603
+ var _a;
2604
+ const cur = await ((_a = plugin.doComplete) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2202
2605
  if (cancel.isCancellationRequested)
2203
2606
  return;
2204
2607
  if (cur) {
@@ -2207,185 +2610,181 @@ var service = {
2207
2610
  curItems = cur;
2208
2611
  } else {
2209
2612
  curItems = cur.items;
2210
- isIncomplete || (isIncomplete = cur.isIncomplete);
2613
+ isIncomplete ||= cur.isIncomplete;
2614
+ }
2615
+ for (const item of curItems) {
2616
+ const { label } = item;
2617
+ const existingItem = itemsByLabel.get(label);
2618
+ if (existingItem) {
2619
+ if ((existingItem.sortText || label) < (item.sortText || label)) {
2620
+ itemsByLabel.set(label, item);
2621
+ }
2622
+ } else {
2623
+ itemsByLabel.set(label, item);
2624
+ }
2211
2625
  }
2212
- items = items ? items.concat(curItems) : curItems;
2213
2626
  }
2214
- }
2215
- } catch (err) {
2216
- isIncomplete = true;
2217
- displayError(err);
2627
+ })
2628
+ );
2629
+ if (cancel.isCancellationRequested)
2630
+ return;
2631
+ if (itemsByLabel.size) {
2632
+ return { items: [...itemsByLabel.values()], isIncomplete };
2218
2633
  }
2219
- if (items) {
2220
- return CompletionList3.create(items, isIncomplete);
2634
+ },
2635
+ async doCompletionResolve(item, cancel) {
2636
+ var _a;
2637
+ for (const plugin of plugins) {
2638
+ try {
2639
+ const result = await ((_a = plugin.doCompletionResolve) == null ? void 0 : _a.call(plugin, item, cancel));
2640
+ if (cancel.isCancellationRequested)
2641
+ return;
2642
+ if (result)
2643
+ return result;
2644
+ } catch {
2645
+ }
2221
2646
  }
2222
2647
  },
2223
2648
  async findDefinition(doc, params, cancel) {
2224
2649
  let result;
2225
- try {
2226
- for (const pending of plugins.map(
2227
- (plugin) => {
2228
- var _a;
2229
- return (_a = plugin.findDefinition) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2230
- }
2231
- )) {
2232
- const cur = await pending;
2650
+ await Promise.allSettled(
2651
+ plugins.map(async (plugin) => {
2652
+ var _a;
2653
+ const cur = await ((_a = plugin.findDefinition) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2233
2654
  if (cancel.isCancellationRequested)
2234
2655
  return;
2235
2656
  if (cur)
2236
2657
  result = (result || []).concat(cur);
2237
- }
2238
- } catch (err) {
2239
- displayError(err);
2240
- }
2658
+ })
2659
+ );
2660
+ if (cancel.isCancellationRequested)
2661
+ return;
2241
2662
  return result;
2242
2663
  },
2243
2664
  async findReferences(doc, params, cancel) {
2244
2665
  let result;
2245
- try {
2246
- for (const pending of plugins.map(
2247
- (plugin) => {
2248
- var _a;
2249
- return (_a = plugin.findReferences) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2250
- }
2251
- )) {
2252
- const cur = await pending;
2666
+ await Promise.allSettled(
2667
+ plugins.map(async (plugin) => {
2668
+ var _a;
2669
+ const cur = await ((_a = plugin.findReferences) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2253
2670
  if (cancel.isCancellationRequested)
2254
2671
  return;
2255
2672
  if (cur)
2256
- result = result ? result.concat(cur) : cur;
2257
- }
2258
- } catch (err) {
2259
- displayError(err);
2260
- }
2673
+ result = (result || []).concat(cur);
2674
+ })
2675
+ );
2676
+ if (cancel.isCancellationRequested)
2677
+ return;
2261
2678
  return result;
2262
2679
  },
2263
2680
  async findDocumentSymbols(doc, params, cancel) {
2264
2681
  let result;
2265
- try {
2266
- for (const pending of plugins.map(
2267
- (plugin) => {
2268
- var _a;
2269
- return (_a = plugin.findDocumentSymbols) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2270
- }
2271
- )) {
2272
- const cur = await pending;
2682
+ await Promise.allSettled(
2683
+ plugins.map(async (plugin) => {
2684
+ var _a;
2685
+ const cur = await ((_a = plugin.findDocumentSymbols) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2273
2686
  if (cancel.isCancellationRequested)
2274
2687
  return;
2275
2688
  if (cur)
2276
- result = result ? result.concat(cur) : cur;
2277
- }
2278
- } catch (err) {
2279
- displayError(err);
2280
- }
2689
+ result = (result || []).concat(cur);
2690
+ })
2691
+ );
2692
+ if (cancel.isCancellationRequested)
2693
+ return;
2281
2694
  return result;
2282
2695
  },
2283
2696
  async findDocumentLinks(doc, params, cancel) {
2284
2697
  let result;
2285
- try {
2286
- for (const pending of plugins.map(
2287
- (plugin) => {
2288
- var _a;
2289
- return (_a = plugin.findDocumentLinks) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2290
- }
2291
- )) {
2292
- const cur = await pending;
2698
+ await Promise.allSettled(
2699
+ plugins.map(async (plugin) => {
2700
+ var _a;
2701
+ const cur = await ((_a = plugin.findDocumentLinks) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2293
2702
  if (cancel.isCancellationRequested)
2294
2703
  return;
2295
2704
  if (cur)
2296
- result = result ? result.concat(cur) : cur;
2297
- }
2298
- } catch (err) {
2299
- displayError(err);
2300
- }
2705
+ result = (result || []).concat(cur);
2706
+ })
2707
+ );
2708
+ if (cancel.isCancellationRequested)
2709
+ return;
2301
2710
  return result;
2302
2711
  },
2303
2712
  async findDocumentHighlights(doc, params, cancel) {
2304
2713
  let result;
2305
- try {
2306
- for (const pending of plugins.map(
2307
- (plugin) => {
2308
- var _a;
2309
- return (_a = plugin.findDocumentHighlights) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2310
- }
2311
- )) {
2312
- const cur = await pending;
2714
+ await Promise.allSettled(
2715
+ plugins.map(async (plugin) => {
2716
+ var _a;
2717
+ const cur = await ((_a = plugin.findDocumentHighlights) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2313
2718
  if (cancel.isCancellationRequested)
2314
2719
  return;
2315
2720
  if (cur)
2316
- result = result ? result.concat(cur) : cur;
2317
- }
2318
- } catch (err) {
2319
- displayError(err);
2320
- }
2721
+ result = (result || []).concat(cur);
2722
+ })
2723
+ );
2724
+ if (cancel.isCancellationRequested)
2725
+ return;
2321
2726
  return result;
2322
2727
  },
2323
2728
  async findDocumentColors(doc, params, cancel) {
2324
2729
  let result;
2325
- try {
2326
- for (const pending of plugins.map(
2327
- (plugin) => {
2328
- var _a;
2329
- return (_a = plugin.findDocumentColors) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2330
- }
2331
- )) {
2332
- const cur = await pending;
2730
+ await Promise.allSettled(
2731
+ plugins.map(async (plugin) => {
2732
+ var _a;
2733
+ const cur = await ((_a = plugin.findDocumentColors) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2333
2734
  if (cancel.isCancellationRequested)
2334
2735
  return;
2335
2736
  if (cur)
2336
- result = result ? result.concat(cur) : cur;
2337
- }
2338
- } catch (err) {
2339
- displayError(err);
2340
- }
2737
+ result = (result || []).concat(cur);
2738
+ })
2739
+ );
2740
+ if (cancel.isCancellationRequested)
2741
+ return;
2341
2742
  return result;
2342
2743
  },
2343
2744
  async getColorPresentations(doc, params, cancel) {
2344
2745
  let result;
2345
- try {
2346
- for (const pending of plugins.map(
2347
- (plugin) => {
2348
- var _a;
2349
- return (_a = plugin.getColorPresentations) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2350
- }
2351
- )) {
2352
- const cur = await pending;
2746
+ await Promise.allSettled(
2747
+ plugins.map(async (plugin) => {
2748
+ var _a;
2749
+ const cur = await ((_a = plugin.getColorPresentations) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2353
2750
  if (cancel.isCancellationRequested)
2354
2751
  return;
2355
2752
  if (cur)
2356
- result = result ? result.concat(cur) : cur;
2357
- }
2358
- } catch (err) {
2359
- displayError(err);
2360
- }
2753
+ result = (result || []).concat(cur);
2754
+ })
2755
+ );
2756
+ if (cancel.isCancellationRequested)
2757
+ return;
2361
2758
  return result;
2362
2759
  },
2363
2760
  async doHover(doc, params, cancel) {
2364
- var _a;
2365
- try {
2366
- for (const plugin of plugins) {
2367
- const result = await ((_a = plugin.doHover) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2761
+ let result;
2762
+ await Promise.allSettled(
2763
+ plugins.map(async (plugin) => {
2764
+ var _a;
2765
+ const cur = await ((_a = plugin.doHover) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2368
2766
  if (cancel.isCancellationRequested)
2369
2767
  return;
2370
- if (result)
2371
- return result;
2372
- }
2373
- } catch (err) {
2374
- displayError(err);
2375
- }
2768
+ if (cur) {
2769
+ if (result) {
2770
+ result.range = maxRange(result.range, cur.range);
2771
+ result.contents = mergeHoverContents(result.contents, cur.contents);
2772
+ } else {
2773
+ result = cur;
2774
+ }
2775
+ }
2776
+ })
2777
+ );
2778
+ return result;
2376
2779
  },
2377
2780
  async doRename(doc, params, cancel) {
2378
2781
  let changes;
2379
2782
  let changeAnnotations;
2380
2783
  let documentChanges;
2381
- try {
2382
- for (const pending of plugins.map(
2383
- (plugin) => {
2384
- var _a;
2385
- return (_a = plugin.doRename) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2386
- }
2387
- )) {
2388
- const cur = await pending;
2784
+ await Promise.allSettled(
2785
+ plugins.map(async (plugin) => {
2786
+ var _a;
2787
+ const cur = await ((_a = plugin.doRename) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2389
2788
  if (cancel.isCancellationRequested)
2390
2789
  return;
2391
2790
  if (cur) {
@@ -2409,10 +2808,10 @@ var service = {
2409
2808
  documentChanges = documentChanges ? documentChanges.concat(cur.documentChanges) : cur.documentChanges;
2410
2809
  }
2411
2810
  }
2412
- }
2413
- } catch (err) {
2414
- displayError(err);
2415
- }
2811
+ })
2812
+ );
2813
+ if (cancel.isCancellationRequested)
2814
+ return;
2416
2815
  if (changes || changeAnnotations || documentChanges) {
2417
2816
  return {
2418
2817
  changes,
@@ -2423,62 +2822,112 @@ var service = {
2423
2822
  },
2424
2823
  async doCodeActions(doc, params, cancel) {
2425
2824
  let result;
2426
- try {
2427
- for (const pending of plugins.map(
2428
- (plugin) => {
2429
- var _a;
2430
- return (_a = plugin.doCodeActions) == null ? void 0 : _a.call(plugin, doc, params, cancel);
2431
- }
2432
- )) {
2433
- const cur = await pending;
2825
+ await Promise.allSettled(
2826
+ plugins.map(async (plugin) => {
2827
+ var _a;
2828
+ const cur = await ((_a = plugin.doCodeActions) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2434
2829
  if (cancel.isCancellationRequested)
2435
2830
  return;
2436
2831
  if (cur)
2437
- result = result ? result.concat(cur) : cur;
2438
- }
2439
- } catch (err) {
2440
- displayError(err);
2441
- }
2832
+ result = (result || []).concat(cur);
2833
+ })
2834
+ );
2835
+ if (cancel.isCancellationRequested)
2836
+ return;
2442
2837
  return result;
2443
2838
  },
2444
2839
  async doValidate(doc) {
2445
2840
  let result;
2446
- try {
2447
- for (const pending of plugins.map((plugin) => {
2841
+ await Promise.allSettled(
2842
+ plugins.map(async (plugin) => {
2448
2843
  var _a;
2449
- return (_a = plugin.doValidate) == null ? void 0 : _a.call(plugin, doc);
2450
- })) {
2451
- const cur = await pending;
2844
+ const cur = await ((_a = plugin.doValidate) == null ? void 0 : _a.call(plugin, doc));
2452
2845
  if (cur)
2453
- result = result ? result.concat(cur) : cur;
2454
- }
2455
- } catch (err) {
2456
- displayError(err);
2457
- }
2846
+ result = (result || []).concat(cur);
2847
+ })
2848
+ );
2458
2849
  return result;
2459
2850
  },
2460
2851
  format: marko_default.format
2461
2852
  };
2853
+ function maxRange(a, b) {
2854
+ if (!a)
2855
+ return b;
2856
+ if (!b)
2857
+ return a;
2858
+ return {
2859
+ start: {
2860
+ line: Math.min(a.start.line, b.start.line),
2861
+ character: Math.min(a.start.character, b.start.character)
2862
+ },
2863
+ end: {
2864
+ line: Math.max(a.end.line, b.end.line),
2865
+ character: Math.max(a.end.character, b.end.character)
2866
+ }
2867
+ };
2868
+ }
2869
+ function mergeHoverContents(a, b) {
2870
+ if (!a)
2871
+ return b;
2872
+ if (!b)
2873
+ return a;
2874
+ if (!MarkupContent.is(a)) {
2875
+ a = markedStringToMarkupContent(a);
2876
+ }
2877
+ if (!MarkupContent.is(b)) {
2878
+ b = markedStringToMarkupContent(b);
2879
+ }
2880
+ if (a.kind === b.kind) {
2881
+ return {
2882
+ kind: a.kind,
2883
+ value: `${a.value}
2884
+ ${b.value}`
2885
+ };
2886
+ }
2887
+ return {
2888
+ kind: MarkupKind3.Markdown,
2889
+ value: `${markupContentToMarkdown(a)}
2890
+ ${markupContentToMarkdown(b)}`
2891
+ };
2892
+ }
2893
+ function markedStringToMarkupContent(markedString) {
2894
+ return {
2895
+ kind: MarkupKind3.Markdown,
2896
+ value: Array.isArray(markedString) ? markedString.map((it) => markedStringToString(it)).join("\n") : markedStringToString(markedString)
2897
+ };
2898
+ }
2899
+ function markedStringToString(markedString) {
2900
+ if (typeof markedString === "string") {
2901
+ return markedString;
2902
+ }
2903
+ return `\`\`\`${markedString.language}
2904
+ ${markedString.value}
2905
+ \`\`\``;
2906
+ }
2907
+ function markupContentToMarkdown(content) {
2908
+ return content.kind === MarkupKind3.Markdown ? content.value : escapeMarkdown(content.value);
2909
+ }
2910
+ function escapeMarkdown(str) {
2911
+ return str.replace(REG_MARKDOWN_CHARS, "$1");
2912
+ }
2462
2913
 
2463
2914
  // src/index.ts
2464
2915
  if (typeof __require !== "undefined" && __require.extensions && !(".ts" in __require.extensions)) {
2465
2916
  __require.extensions[".ts"] = void 0;
2466
2917
  }
2467
- var documents = new TextDocuments(TextDocument3);
2468
- var connection2 = createConnection(ProposedFeatures.all);
2918
+ var connection3 = createConnection(ProposedFeatures.all);
2469
2919
  var prevDiags = /* @__PURE__ */ new WeakMap();
2470
- var pendingDiags = /* @__PURE__ */ new WeakSet();
2471
2920
  var diagnosticTimeout;
2472
2921
  console.log = (...args) => {
2473
- connection2.console.log(args.map((v) => inspect2(v)).join(" "));
2922
+ connection3.console.log(args.map((v) => inspect2(v)).join(" "));
2474
2923
  };
2475
2924
  console.error = (...args) => {
2476
- connection2.console.error(args.map((v) => inspect2(v)).join(" "));
2925
+ connection3.console.error(args.map((v) => inspect2(v)).join(" "));
2477
2926
  };
2478
2927
  process.on("uncaughtException", console.error);
2479
2928
  process.on("unhandledRejection", console.error);
2480
- connection2.onInitialize(async (params) => {
2481
- setup(connection2);
2929
+ connection3.onInitialize(async (params) => {
2930
+ setup3(connection3);
2482
2931
  await service.initialize(params);
2483
2932
  return {
2484
2933
  capabilities: {
@@ -2494,6 +2943,7 @@ connection2.onInitialize(async (params) => {
2494
2943
  documentHighlightProvider: true,
2495
2944
  documentSymbolProvider: true,
2496
2945
  completionProvider: {
2946
+ resolveProvider: true,
2497
2947
  triggerCharacters: [
2498
2948
  ".",
2499
2949
  ":",
@@ -2519,111 +2969,123 @@ connection2.onInitialize(async (params) => {
2519
2969
  }
2520
2970
  };
2521
2971
  });
2522
- connection2.onDidChangeConfiguration(validateDocs);
2523
- connection2.onDidChangeWatchedFiles(validateDocs);
2524
- documents.onDidChangeContent(({ document }) => {
2525
- queueDiagnostic();
2526
- pendingDiags.add(document);
2527
- clearCompilerCache(document);
2972
+ setup2(connection3);
2973
+ onConfigChange(validateDocs);
2974
+ setup(connection3);
2975
+ onFileChange((changeDoc) => {
2976
+ if (changeDoc) {
2977
+ queueDiagnostic();
2978
+ getMarkoProject(getFSDir(changeDoc)).cache.delete(changeDoc);
2979
+ } else {
2980
+ validateDocs();
2981
+ }
2528
2982
  });
2529
- connection2.onCompletion(async (params, cancel) => {
2983
+ connection3.onCompletion(async (params, cancel) => {
2530
2984
  return await service.doComplete(
2531
- documents.get(params.textDocument.uri),
2985
+ get(params.textDocument.uri),
2532
2986
  params,
2533
2987
  cancel
2534
2988
  ) || null;
2535
2989
  });
2536
- connection2.onDefinition(async (params, cancel) => {
2990
+ connection3.onCompletionResolve(async (item, cancel) => {
2991
+ return await service.doCompletionResolve(item, cancel) || item;
2992
+ });
2993
+ connection3.onDefinition(async (params, cancel) => {
2537
2994
  return await service.findDefinition(
2538
- documents.get(params.textDocument.uri),
2995
+ get(params.textDocument.uri),
2539
2996
  params,
2540
2997
  cancel
2541
2998
  ) || null;
2542
2999
  });
2543
- connection2.onReferences(async (params, cancel) => {
3000
+ connection3.onReferences(async (params, cancel) => {
2544
3001
  return await service.findReferences(
2545
- documents.get(params.textDocument.uri),
3002
+ get(params.textDocument.uri),
2546
3003
  params,
2547
3004
  cancel
2548
3005
  ) || null;
2549
3006
  });
2550
- connection2.onDocumentLinks(async (params, cancel) => {
3007
+ connection3.onDocumentLinks(async (params, cancel) => {
2551
3008
  return await service.findDocumentLinks(
2552
- documents.get(params.textDocument.uri),
3009
+ get(params.textDocument.uri),
2553
3010
  params,
2554
3011
  cancel
2555
3012
  ) || null;
2556
3013
  });
2557
- connection2.onDocumentSymbol(async (params, cancel) => {
3014
+ connection3.onDocumentSymbol(async (params, cancel) => {
2558
3015
  return await service.findDocumentSymbols(
2559
- documents.get(params.textDocument.uri),
3016
+ get(params.textDocument.uri),
2560
3017
  params,
2561
3018
  cancel
2562
3019
  ) || null;
2563
3020
  });
2564
- connection2.onDocumentHighlight(async (params, cancel) => {
3021
+ connection3.onDocumentHighlight(async (params, cancel) => {
2565
3022
  return await service.findDocumentHighlights(
2566
- documents.get(params.textDocument.uri),
3023
+ get(params.textDocument.uri),
2567
3024
  params,
2568
3025
  cancel
2569
3026
  ) || null;
2570
3027
  });
2571
- connection2.onDocumentColor(async (params, cancel) => {
3028
+ connection3.onDocumentColor(async (params, cancel) => {
2572
3029
  return await service.findDocumentColors(
2573
- documents.get(params.textDocument.uri),
3030
+ get(params.textDocument.uri),
2574
3031
  params,
2575
3032
  cancel
2576
3033
  ) || null;
2577
3034
  });
2578
- connection2.onColorPresentation(async (params, cancel) => {
3035
+ connection3.onColorPresentation(async (params, cancel) => {
2579
3036
  return await service.getColorPresentations(
2580
- documents.get(params.textDocument.uri),
3037
+ get(params.textDocument.uri),
2581
3038
  params,
2582
3039
  cancel
2583
3040
  ) || null;
2584
3041
  });
2585
- connection2.onHover(async (params, cancel) => {
3042
+ connection3.onHover(async (params, cancel) => {
2586
3043
  return await service.doHover(
2587
- documents.get(params.textDocument.uri),
3044
+ get(params.textDocument.uri),
2588
3045
  params,
2589
3046
  cancel
2590
3047
  ) || null;
2591
3048
  });
2592
- connection2.onRenameRequest(async (params, cancel) => {
3049
+ connection3.onRenameRequest(async (params, cancel) => {
2593
3050
  return await service.doRename(
2594
- documents.get(params.textDocument.uri),
3051
+ get(params.textDocument.uri),
2595
3052
  params,
2596
3053
  cancel
2597
3054
  ) || null;
2598
3055
  });
2599
- connection2.onCodeAction(async (params, cancel) => {
3056
+ connection3.onCodeAction(async (params, cancel) => {
2600
3057
  return await service.doCodeActions(
2601
- documents.get(params.textDocument.uri),
3058
+ get(params.textDocument.uri),
2602
3059
  params,
2603
3060
  cancel
2604
3061
  ) || null;
2605
3062
  });
2606
- connection2.onDocumentFormatting(async (params, cancel) => {
3063
+ connection3.onDocumentFormatting(async (params, cancel) => {
2607
3064
  return await service.format(
2608
- documents.get(params.textDocument.uri),
3065
+ get(params.textDocument.uri),
2609
3066
  params,
2610
3067
  cancel
2611
3068
  ) || null;
2612
3069
  });
3070
+ for (const command in service.commands) {
3071
+ connection3.onRequest(command, service.commands[command]);
3072
+ }
2613
3073
  function validateDocs() {
2614
3074
  queueDiagnostic();
2615
- clearCompilerCache();
2616
- for (const doc of documents.all()) {
2617
- pendingDiags.add(doc);
3075
+ for (const project of getMarkoProjects()) {
3076
+ project.cache.clear();
3077
+ project.compiler.taglib.clearCaches();
2618
3078
  }
2619
3079
  }
2620
3080
  function queueDiagnostic() {
2621
3081
  clearTimeout(diagnosticTimeout);
2622
3082
  const id = diagnosticTimeout = setTimeout(async () => {
2623
3083
  const results = await Promise.all(
2624
- documents.all().map(async (doc) => {
2625
- if (!pendingDiags.delete(doc))
3084
+ Array.from(getAllOpen()).map(async (doc) => {
3085
+ if (!isOpen(doc)) {
3086
+ prevDiags.delete(doc);
2626
3087
  return;
3088
+ }
2627
3089
  const prevDiag = prevDiags.get(doc) || [];
2628
3090
  const nextDiag = await service.doValidate(doc) || [];
2629
3091
  if (isDeepStrictEqual(prevDiag, nextDiag))
@@ -2636,7 +3098,7 @@ function queueDiagnostic() {
2636
3098
  if (result) {
2637
3099
  const [doc, diag] = result;
2638
3100
  prevDiags.set(doc, diag);
2639
- connection2.sendDiagnostics({
3101
+ connection3.sendDiagnostics({
2640
3102
  uri: doc.uri,
2641
3103
  diagnostics: diag
2642
3104
  });
@@ -2645,6 +3107,5 @@ function queueDiagnostic() {
2645
3107
  }
2646
3108
  }, 400);
2647
3109
  }
2648
- documents.listen(connection2);
2649
- connection2.listen();
3110
+ connection3.listen();
2650
3111
  //# sourceMappingURL=index.mjs.map