@marko/language-server 0.12.17 → 1.0.1

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 +2071 -1567
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.mjs +2103 -1593
  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
289
 
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
- }
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,93 +968,103 @@ function escape(val) {
1256
968
  return String(val).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
1257
969
  }
1258
970
 
1259
- // src/service/marko/definition/OpenTagName.ts
1260
- function OpenTagName3({
1261
- lookup,
1262
- parsed,
1263
- node
1264
- }) {
1265
- const tag = node.parent;
1266
- let tagDef;
1267
- let range = START_OF_FILE;
1268
- if (tag.type === 14 /* AttrTag */) {
1269
- let parentTag = tag.owner;
1270
- while ((parentTag == null ? void 0 : parentTag.type) === 14 /* AttrTag */)
1271
- parentTag = parentTag.owner;
1272
- tagDef = parentTag && parentTag.nameText ? lookup.getTag(parentTag.nameText) : void 0;
1273
- } else {
1274
- tagDef = tag.nameText ? lookup.getTag(tag.nameText) : void 0;
971
+ // src/service/marko/definition/AttrName.ts
972
+ function AttrName2({
973
+ node,
974
+ file: {
975
+ parsed,
976
+ project: { lookup }
1275
977
  }
1276
- if (!tagDef) {
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) {
1277
985
  return;
1278
986
  }
1279
- const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
1280
- if (!path4.isAbsolute(tagEntryFile)) {
987
+ const attrEntryFile = attrDef.filePath || (tagDef == null ? void 0 : tagDef.filePath);
988
+ if (!attrEntryFile) {
1281
989
  return;
1282
990
  }
1283
- if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
1284
- const tagDefDoc = createTextDocument(tagEntryFile);
1285
- const match = RegExpBuilder`/"(?:<${tag.nameText}>|${tag.nameText})"\s*:\s*[^\r\n,]+/g`.exec(
1286
- tagDefDoc.getText()
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
1287
995
  );
1288
996
  if (match && match.index) {
1289
- range = Range4.create(
1290
- tagDefDoc.positionAt(match.index),
1291
- tagDefDoc.positionAt(match.index + match[0].length)
997
+ range = getLocation(
998
+ getLines(tagDefSource),
999
+ match.index,
1000
+ match.index + match[0].length
1292
1001
  );
1293
1002
  }
1003
+ return [
1004
+ {
1005
+ targetUri: URI4.file(attrEntryFile).toString(),
1006
+ targetRange: range,
1007
+ targetSelectionRange: range,
1008
+ originSelectionRange: parsed.locationAt(node)
1009
+ }
1010
+ ];
1294
1011
  }
1295
- return [
1296
- LocationLink.create(
1297
- URI4.file(tagEntryFile).toString(),
1298
- range,
1299
- range,
1300
- parsed.locationAt(node)
1301
- )
1302
- ];
1303
1012
  }
1304
1013
 
1305
- // src/service/marko/definition/AttrName.ts
1014
+ // src/service/marko/definition/OpenTagName.ts
1015
+ import fs4 from "fs";
1016
+ import path5 from "path";
1306
1017
  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
1018
+ import {
1019
+ NodeType as NodeType5,
1020
+ getLines as getLines2,
1021
+ getLocation as getLocation2
1022
+ } from "@marko/language-tools";
1023
+ function OpenTagName3({
1024
+ node,
1025
+ file: {
1026
+ parsed,
1027
+ project: { lookup }
1028
+ }
1312
1029
  }) {
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) {
1030
+ const tag = node.parent;
1031
+ let tagDef;
1032
+ let range = START_LOCATION;
1033
+ if (tag.type === NodeType5.AttrTag) {
1034
+ let parentTag = tag.owner;
1035
+ while ((parentTag == null ? void 0 : parentTag.type) === NodeType5.AttrTag)
1036
+ parentTag = parentTag.owner;
1037
+ tagDef = parentTag && parentTag.nameText ? lookup.getTag(parentTag.nameText) : void 0;
1038
+ } else {
1039
+ tagDef = tag.nameText ? lookup.getTag(tag.nameText) : void 0;
1040
+ }
1041
+ if (!tagDef) {
1321
1042
  return;
1322
1043
  }
1323
- const attrEntryFile = attrDef.filePath || tagDef && tagDef.filePath;
1324
- if (!attrEntryFile) {
1044
+ const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
1045
+ if (!path5.isAbsolute(tagEntryFile)) {
1325
1046
  return;
1326
1047
  }
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()
1048
+ if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
1049
+ const tagDefSource = fs4.readFileSync(tagEntryFile, "utf-8");
1050
+ const match = RegExpBuilder`/"(?:<${tag.nameText}>|${tag.nameText})"\s*:\s*[^\r\n,]+/g`.exec(
1051
+ tagDefSource
1331
1052
  );
1332
1053
  if (match && match.index) {
1333
- range = Range5.create(
1334
- tagDefDoc.positionAt(match.index),
1335
- tagDefDoc.positionAt(match.index + match[0].length)
1054
+ range = getLocation2(
1055
+ getLines2(tagDefSource),
1056
+ match.index,
1057
+ match.index + match[0].length
1336
1058
  );
1337
1059
  }
1338
1060
  }
1339
1061
  return [
1340
- LocationLink2.create(
1341
- URI5.file(attrEntryFile).toString(),
1342
- range,
1343
- range,
1344
- parsed.locationAt(node)
1345
- )
1062
+ {
1063
+ targetUri: URI5.file(tagEntryFile).toString(),
1064
+ targetRange: range,
1065
+ targetSelectionRange: range,
1066
+ originSelectionRange: parsed.locationAt(node)
1067
+ }
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,1000 @@ 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
+ NodeType as NodeType9,
1271
+ ScriptLang as ScriptLang3,
1272
+ extractScript as extractScript2
1273
+ } from "@marko/language-tools";
1558
1274
 
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
- }
1275
+ // src/ts-plugin/host.ts
1276
+ import path8 from "path";
1277
+ import {
1278
+ ScriptLang as ScriptLang2,
1279
+ extractScript,
1280
+ parse as parse2
1281
+ } from "@marko/language-tools";
1282
+
1283
+ // src/utils/get-runtime-types.ts
1284
+ import path6 from "path";
1285
+ var internalTypesFile = path6.join(__dirname, "marko.internal.d.ts");
1286
+ var defaultMarkoTypesFile = path6.join(__dirname, "marko.runtime.d.ts");
1287
+ function getProjectTypeLibs(project, ts2, host) {
1288
+ let cached = project.cache.get(getProjectTypeLibs);
1289
+ if (cached === void 0) {
1290
+ const { resolvedTypeReferenceDirective } = ts2.resolveTypeReferenceDirective(
1291
+ project.translator.runtimeTypes || "marko",
1292
+ path6.join(project.rootDir, "_.d.ts"),
1293
+ host.getCompilationSettings(),
1294
+ host
1295
+ );
1296
+ const markoTypesFile = (resolvedTypeReferenceDirective == null ? void 0 : resolvedTypeReferenceDirective.resolvedFileName) || defaultMarkoTypesFile;
1297
+ cached = {
1298
+ internalTypesFile,
1299
+ markoTypesFile,
1300
+ markoTypesCode: host.readFile(markoTypesFile, "utf-8") || ""
1301
+ };
1302
+ project.cache.set(getProjectTypeLibs, cached);
1303
+ }
1304
+ return cached;
1305
+ }
1306
+
1307
+ // src/utils/get-script-lang.ts
1308
+ import { ScriptLang } from "@marko/language-tools";
1309
+ function getScriptLang(filename, ts2, host, projectScriptLang) {
1310
+ const configPath = ts2.findConfigFile(
1311
+ filename,
1312
+ host.fileExists.bind(host),
1313
+ "marko.json"
1314
+ );
1315
+ if (configPath) {
1316
+ try {
1317
+ const markoConfig = JSON.parse(
1318
+ host.readFile(configPath, "utf-8") || "{}"
1319
+ );
1320
+ const scriptLang = markoConfig["script-lang"] || markoConfig.scriptLang;
1321
+ if (scriptLang !== void 0) {
1322
+ return scriptLang === ScriptLang.ts ? ScriptLang.ts : ScriptLang.js;
1575
1323
  }
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;
1324
+ } catch {
1325
+ }
1326
+ }
1327
+ return /[/\\]node_modules[/\\]/.test(filename) ? ScriptLang.js : projectScriptLang;
1328
+ }
1329
+
1330
+ // src/utils/get-component-filename.ts
1331
+ import path7 from "path";
1332
+ function getComponentFilename(from, host) {
1333
+ const dir = path7.dirname(from);
1334
+ const nameNoExt = path7.basename(from, ".marko");
1335
+ const isEntry = nameNoExt === "index";
1336
+ const componentFull = path7.join(dir, `${nameNoExt}.component.`);
1337
+ const componentBrowserFull = path7.join(
1338
+ dir,
1339
+ `${nameNoExt}.component-browser.`
1340
+ );
1341
+ const componentPartial = isEntry ? path7.join(dir, "component.") : void 0;
1342
+ const componentBrowserPartial = isEntry ? path7.join(dir, "component-browser.") : void 0;
1343
+ for (const entry of host.readDirectory(dir)) {
1344
+ if (entry !== from && (isEntry && entry.startsWith(componentBrowserPartial) || entry.startsWith(componentPartial)) || entry.startsWith(componentBrowserFull) || entry.startsWith(componentFull)) {
1345
+ return entry;
1346
+ }
1347
+ }
1348
+ }
1349
+
1350
+ // src/ts-plugin/host.ts
1351
+ var markoExt = ".marko";
1352
+ var markoExtReg = /\.marko$/;
1353
+ var modulePartsReg = /^((?:@(?:[^/]+)\/)?(?:[^/]+))(.*)$/;
1354
+ var fsPathReg = /^(?:[./\\]|[A-Z]:)/i;
1355
+ function patch(ts2, scriptLang, cache, host) {
1356
+ var _a, _b, _c;
1357
+ const projectTypeLibs = getProjectTypeLibs(
1358
+ getMarkoProject(host.getCurrentDirectory()),
1359
+ ts2,
1360
+ host
1361
+ );
1362
+ const isMarkoTSFile = (fileName) => getScriptLang(fileName, ts2, host, scriptLang) === ScriptLang2.ts;
1363
+ const getScriptFileNames = host.getScriptFileNames.bind(host);
1364
+ host.getScriptFileNames = () => [
1365
+ .../* @__PURE__ */ new Set([
1366
+ ...getScriptFileNames(),
1367
+ projectTypeLibs.internalTypesFile,
1368
+ projectTypeLibs.markoTypesFile
1369
+ ])
1370
+ ];
1371
+ const getScriptKind = (_a = host.getScriptKind) == null ? void 0 : _a.bind(host);
1372
+ if (getScriptKind) {
1373
+ host.getScriptKind = (fileName) => {
1374
+ return markoExtReg.test(fileName) ? isMarkoTSFile(fileName) ? ts2.ScriptKind.TS : ts2.ScriptKind.JS : getScriptKind(fileName);
1375
+ };
1376
+ }
1377
+ const getScriptSnapshot = host.getScriptSnapshot.bind(host);
1378
+ host.getScriptSnapshot = (filename) => {
1379
+ if (markoExtReg.test(filename)) {
1380
+ let cached = cache.get(filename);
1381
+ if (!cached) {
1382
+ const code = host.readFile(filename, "utf-8") || "";
1383
+ const markoProject = getMarkoProject(path8.dirname(filename));
1384
+ cached = extractScript({
1385
+ ts: ts2,
1386
+ parsed: parse2(code, filename),
1387
+ lookup: markoProject.lookup,
1388
+ scriptLang: getScriptLang(filename, ts2, host, scriptLang),
1389
+ runtimeTypesCode: projectTypeLibs.markoTypesCode,
1390
+ componentFilename: getComponentFilename(filename, host)
1391
+ });
1392
+ cached.snapshot = ts2.ScriptSnapshot.fromString(cached.toString());
1393
+ cache.set(filename, cached);
1394
+ }
1395
+ return cached.snapshot;
1396
+ }
1397
+ return getScriptSnapshot(filename);
1398
+ };
1399
+ const readDirectory2 = (_b = host.readDirectory) == null ? void 0 : _b.bind(host);
1400
+ if (readDirectory2) {
1401
+ host.readDirectory = (path10, extensions, exclude, include, depth) => {
1402
+ return readDirectory2(
1403
+ path10,
1404
+ extensions == null ? void 0 : extensions.concat(markoExt),
1405
+ exclude,
1406
+ include,
1407
+ depth
1408
+ );
1409
+ };
1410
+ }
1411
+ const resolveModuleNames = (_c = host.resolveModuleNames) == null ? void 0 : _c.bind(host);
1412
+ if (resolveModuleNames) {
1413
+ host.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, options, sourceFile) => {
1414
+ const resolvedModules = resolveModuleNames(
1415
+ moduleNames,
1416
+ containingFile,
1417
+ reusedNames,
1418
+ redirectedReference,
1419
+ options,
1420
+ sourceFile
1421
+ );
1422
+ for (let i = resolvedModules.length; i--; ) {
1423
+ const moduleName = moduleNames[i];
1424
+ if (!resolvedModules[i] && markoExtReg.test(moduleName)) {
1425
+ if (fsPathReg.test(moduleName)) {
1426
+ const resolvedFileName = path8.resolve(
1427
+ containingFile,
1428
+ "..",
1429
+ moduleName
1430
+ );
1431
+ if (host.fileExists(resolvedFileName)) {
1432
+ resolvedModules[i] = {
1433
+ resolvedFileName,
1434
+ extension: isMarkoTSFile(resolvedFileName) ? ts2.Extension.Ts : ts2.Extension.Js,
1435
+ isExternalLibraryImport: false
1436
+ };
1437
+ }
1438
+ } else if (moduleName[0] !== "*") {
1439
+ const [, nodeModuleName, relativeModulePath] = modulePartsReg.exec(moduleName);
1440
+ const { resolvedModule } = ts2.resolveModuleName(
1441
+ `${nodeModuleName}/package.json`,
1442
+ containingFile,
1443
+ options,
1444
+ host
1445
+ );
1446
+ if (resolvedModule) {
1447
+ const resolvedFileName = path8.join(
1448
+ resolvedModule.resolvedFileName,
1449
+ "..",
1450
+ relativeModulePath
1451
+ );
1452
+ if (host.fileExists(resolvedFileName)) {
1453
+ const isTS = isMarkoTSFile(resolvedFileName);
1454
+ resolvedModules[i] = {
1455
+ resolvedFileName,
1456
+ extension: isTS ? ts2.Extension.Ts : ts2.Extension.Js,
1457
+ isExternalLibraryImport: isTS
1458
+ };
1459
+ }
1595
1460
  }
1596
1461
  }
1597
- next -= 3;
1598
- sort(left, next - 3);
1599
- sort(next + 3, right);
1600
1462
  }
1601
- })(1, sourceMap.length - 2);
1463
+ }
1464
+ return resolvedModules;
1465
+ };
1466
+ }
1467
+ return host;
1468
+ }
1469
+
1470
+ // src/service/script/index.ts
1471
+ var IGNORE_DIAG_REG = /^(?:Expression|Identifier|['"][^\w]['"]) expected.$/;
1472
+ var extractCache = /* @__PURE__ */ new Map();
1473
+ var snapshotCache = /* @__PURE__ */ new Map();
1474
+ var insertModuleStatementLocCache = /* @__PURE__ */ new WeakMap();
1475
+ var markoFileReg = /\.marko$/;
1476
+ var tsTriggerChars = /* @__PURE__ */ new Set([".", '"', "'", "`", "/", "@", "<", "#", " "]);
1477
+ var optionalModifierReg = /\boptional\b/;
1478
+ var deprecatedModifierReg = /\bdeprecated\b/;
1479
+ var colorModifierReg = /\bcolor\b/;
1480
+ var localInternalsPrefix = "__marko_internal_";
1481
+ var ScriptService = {
1482
+ commands: {
1483
+ "$/showScriptOutput": async (uri) => {
1484
+ const doc = get(uri);
1485
+ if ((doc == null ? void 0 : doc.languageId) !== "marko")
1486
+ return;
1487
+ const filename = getFSPath(doc);
1488
+ if (!filename)
1489
+ return;
1490
+ const project = getTSProject(filename);
1491
+ const extracted = processScript(doc, project);
1492
+ const lang = getScriptLang(
1493
+ filename,
1494
+ ts,
1495
+ project.host,
1496
+ project.markoScriptLang
1497
+ );
1498
+ const generated = extracted.toString();
1499
+ const content = (() => {
1500
+ try {
1501
+ return prettier2.format(generated, {
1502
+ parser: lang === ScriptLang3.ts ? "typescript" : "babel"
1503
+ });
1504
+ } catch {
1505
+ return generated;
1506
+ }
1507
+ })();
1602
1508
  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;
1509
+ language: lang === ScriptLang3.ts ? "typescript" : "javascript",
1510
+ content
1511
+ };
1512
+ }
1513
+ },
1514
+ async initialize() {
1515
+ onConfigChange(() => {
1516
+ snapshotCache.clear();
1517
+ });
1518
+ onFileChange((doc) => {
1519
+ if (doc) {
1520
+ const filename = getFSPath(doc);
1521
+ extractCache.delete(filename);
1522
+ snapshotCache.delete(filename);
1523
+ } else {
1524
+ extractCache.clear();
1525
+ snapshotCache.clear();
1526
+ }
1527
+ });
1528
+ },
1529
+ async doComplete(doc, params) {
1530
+ var _a;
1531
+ const fileName = getFSPath(doc);
1532
+ if (!fileName)
1533
+ return;
1534
+ const project = getTSProject(fileName);
1535
+ const extracted = processScript(doc, project);
1536
+ const sourceOffset = doc.offsetAt(params.position);
1537
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1538
+ if (generatedOffset === void 0)
1539
+ return;
1540
+ const completions = project.service.getCompletionsAtPosition(
1541
+ fileName,
1542
+ generatedOffset,
1543
+ {
1544
+ ...await getPreferences(project.markoScriptLang),
1545
+ ...params.context,
1546
+ triggerCharacter: getTSTriggerChar((_a = params.context) == null ? void 0 : _a.triggerCharacter)
1547
+ }
1548
+ );
1549
+ if (!(completions == null ? void 0 : completions.entries.length))
1550
+ return;
1551
+ const result = [];
1552
+ for (const completion of completions.entries) {
1553
+ let { name: label, insertText, sortText } = completion;
1554
+ if (label.startsWith(localInternalsPrefix))
1555
+ continue;
1556
+ const { replacementSpan } = completion;
1557
+ let textEdit;
1558
+ let detail;
1559
+ let kind;
1560
+ let tags;
1561
+ let labelDetails;
1562
+ let source = completion.source;
1563
+ if (source && completion.hasAction) {
1564
+ if (source[0] === ".") {
1565
+ source = path9.resolve(fileName, "..", source);
1566
+ }
1567
+ detail = relativeImportPath(fileName, source);
1568
+ sortText = `\uFFFF${sortText}`;
1569
+ } else if (completion.sourceDisplay) {
1570
+ const description = ts.displayPartsToString(completion.sourceDisplay);
1571
+ if (description !== label) {
1572
+ labelDetails = { description };
1573
+ }
1574
+ }
1575
+ if (completion.kindModifiers) {
1576
+ if (optionalModifierReg.test(completion.kindModifiers)) {
1577
+ insertText = label;
1578
+ label += "?";
1579
+ }
1580
+ if (deprecatedModifierReg.test(completion.kindModifiers)) {
1581
+ tags = [CompletionItemTag2.Deprecated];
1582
+ }
1583
+ if (colorModifierReg.test(completion.kindModifiers)) {
1584
+ kind = CompletionItemKind5.Color;
1585
+ }
1586
+ }
1587
+ if (replacementSpan) {
1588
+ const sourceRange = sourceLocationAtTextSpan(
1589
+ extracted,
1590
+ replacementSpan
1591
+ );
1592
+ if (sourceRange) {
1593
+ textEdit = {
1594
+ range: sourceRange,
1595
+ newText: insertText || label
1596
+ };
1597
+ } else {
1598
+ continue;
1599
+ }
1600
+ }
1601
+ result.push({
1602
+ tags,
1603
+ label,
1604
+ detail,
1605
+ textEdit,
1606
+ sortText,
1607
+ insertText,
1608
+ labelDetails,
1609
+ filterText: insertText,
1610
+ preselect: completion.isRecommended || void 0,
1611
+ kind: kind || convertCompletionItemKind(completion.kind),
1612
+ insertTextFormat: completion.isSnippet ? InsertTextFormat4.Snippet : void 0,
1613
+ data: completion.data && {
1614
+ originalData: completion.data,
1615
+ originalName: completion.name,
1616
+ originalSource: source,
1617
+ generatedOffset,
1618
+ fileName
1619
+ }
1620
+ });
1621
+ }
1622
+ return {
1623
+ isIncomplete: true,
1624
+ items: result
1625
+ };
1626
+ },
1627
+ async doCompletionResolve(item) {
1628
+ const { data } = item;
1629
+ if (!data)
1630
+ return;
1631
+ const { fileName } = data;
1632
+ if (!fileName)
1633
+ return;
1634
+ const doc = get(filenameToURI(fileName));
1635
+ if (!doc)
1636
+ return;
1637
+ const project = getTSProject(fileName);
1638
+ const detail = project.service.getCompletionEntryDetails(
1639
+ fileName,
1640
+ data.generatedOffset,
1641
+ data.originalName,
1642
+ {},
1643
+ data.originalSource,
1644
+ await getPreferences(project.markoScriptLang),
1645
+ data.originalData
1646
+ );
1647
+ if (!(detail == null ? void 0 : detail.codeActions))
1648
+ return;
1649
+ const extracted = processScript(doc, project);
1650
+ const textEdits = item.additionalTextEdits = item.additionalTextEdits || [];
1651
+ for (const action of detail.codeActions) {
1652
+ for (const change of action.changes) {
1653
+ if (change.fileName !== fileName)
1654
+ continue;
1655
+ for (const { span, newText: rawText } of change.textChanges) {
1656
+ let range;
1657
+ let newText = rawText;
1658
+ if (span.length === 0 && /^\s*(?:import|export) /.test(newText)) {
1659
+ const cached = insertModuleStatementLocCache.get(extracted);
1660
+ newText = newText.replace(/\n\s*$/, "\n");
1661
+ if (cached) {
1662
+ range = cached;
1611
1663
  } else {
1612
- max = mid - 1;
1664
+ const { parsed } = getMarkoFile(doc);
1665
+ const offset = getInsertModuleStatementOffset(parsed);
1666
+ const start = parsed.positionAt(offset);
1667
+ range = {
1668
+ start,
1669
+ end: start
1670
+ };
1671
+ insertModuleStatementLocCache.set(extracted, range);
1613
1672
  }
1673
+ } else {
1674
+ range = sourceLocationAtTextSpan(extracted, span);
1614
1675
  }
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;
1630
- }
1676
+ if (range) {
1677
+ textEdits.push({ newText, range });
1631
1678
  }
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
1679
  }
1640
- };
1680
+ }
1641
1681
  }
1642
- };
1643
- }
1644
-
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);
1682
+ return item;
1683
+ },
1684
+ findDefinition(doc, params) {
1685
+ const fileName = getFSPath(doc);
1686
+ if (!fileName)
1687
+ return;
1688
+ const project = getTSProject(fileName);
1689
+ const extracted = processScript(doc, project);
1690
+ const sourceOffset = doc.offsetAt(params.position);
1691
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1692
+ if (generatedOffset === void 0)
1693
+ return;
1694
+ const boundary = project.service.getDefinitionAndBoundSpan(
1695
+ fileName,
1696
+ generatedOffset
1697
+ );
1698
+ if (!(boundary == null ? void 0 : boundary.definitions))
1699
+ return;
1700
+ const originSelectionRange = sourceLocationAtTextSpan(
1701
+ extracted,
1702
+ boundary.textSpan
1703
+ );
1704
+ let result;
1705
+ for (const def of boundary.definitions) {
1706
+ const targetUri = filenameToURI(def.fileName);
1707
+ const defDoc = get(targetUri);
1708
+ if (!defDoc)
1709
+ continue;
1710
+ let link;
1711
+ if (markoFileReg.test(targetUri)) {
1712
+ const extracted2 = processScript(defDoc, project);
1713
+ const targetSelectionRange = sourceLocationAtTextSpan(extracted2, def.textSpan) || START_LOCATION;
1714
+ const targetRange = def.contextSpan && sourceLocationAtTextSpan(extracted2, def.contextSpan) || START_LOCATION;
1715
+ link = {
1716
+ targetUri,
1717
+ targetRange,
1718
+ targetSelectionRange,
1719
+ originSelectionRange
1720
+ };
1721
+ } else {
1722
+ link = {
1723
+ targetUri,
1724
+ targetRange: def.contextSpan ? docLocationAtTextSpan(defDoc, def.contextSpan) : START_LOCATION,
1725
+ targetSelectionRange: docLocationAtTextSpan(defDoc, def.textSpan),
1726
+ originSelectionRange
1727
+ };
1728
+ }
1729
+ if (link) {
1730
+ if (result) {
1731
+ if (Array.isArray(result)) {
1732
+ result.push(link);
1733
+ } else {
1734
+ result = [result, link];
1665
1735
  }
1736
+ } else {
1737
+ result = link;
1666
1738
  }
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;
1677
- }
1739
+ }
1740
+ }
1741
+ return result;
1742
+ },
1743
+ doHover(doc, params) {
1744
+ const fileName = getFSPath(doc);
1745
+ if (!fileName)
1746
+ return;
1747
+ const project = getTSProject(fileName);
1748
+ const extracted = processScript(doc, project);
1749
+ const sourceOffset = doc.offsetAt(params.position);
1750
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1751
+ if (generatedOffset === void 0)
1752
+ return;
1753
+ const quickInfo = project.service.getQuickInfoAtPosition(
1754
+ fileName,
1755
+ generatedOffset
1756
+ );
1757
+ if (!quickInfo)
1758
+ return;
1759
+ const sourceRange = sourceLocationAtTextSpan(extracted, quickInfo.textSpan);
1760
+ if (!sourceRange)
1761
+ return;
1762
+ let contents = "";
1763
+ const displayParts = ts.displayPartsToString(quickInfo.displayParts);
1764
+ if (displayParts) {
1765
+ contents += `\`\`\`typescript
1766
+ ${displayParts}
1767
+ \`\`\``;
1768
+ }
1769
+ const documentation = printDocumentation(
1770
+ quickInfo.documentation,
1771
+ quickInfo.tags
1772
+ );
1773
+ if (documentation) {
1774
+ contents += `
1775
+ ---
1776
+ ${documentation}`;
1777
+ }
1778
+ return {
1779
+ range: sourceRange,
1780
+ contents
1781
+ };
1782
+ },
1783
+ doRename(doc, params) {
1784
+ const fileName = getFSPath(doc);
1785
+ if (!fileName)
1786
+ return;
1787
+ const project = getTSProject(fileName);
1788
+ const extracted = processScript(doc, project);
1789
+ const sourceOffset = doc.offsetAt(params.position);
1790
+ const generatedOffset = extracted.generatedOffsetAt(sourceOffset);
1791
+ if (generatedOffset === void 0)
1792
+ return;
1793
+ const renameLocations = project.service.findRenameLocations(
1794
+ fileName,
1795
+ generatedOffset,
1796
+ false,
1797
+ false,
1798
+ false
1799
+ );
1800
+ if (!renameLocations)
1801
+ return;
1802
+ const changes = {};
1803
+ for (const rename of renameLocations) {
1804
+ const renameURI = filenameToURI(rename.fileName);
1805
+ const renameDoc = get(renameURI);
1806
+ let edit;
1807
+ if (!renameDoc)
1808
+ continue;
1809
+ if (markoFileReg.test(renameURI)) {
1810
+ const extracted2 = processScript(renameDoc, project);
1811
+ const sourceRange = sourceLocationAtTextSpan(
1812
+ extracted2,
1813
+ rename.textSpan
1814
+ );
1815
+ if (sourceRange) {
1816
+ edit = {
1817
+ newText: params.newName,
1818
+ range: sourceRange
1819
+ };
1678
1820
  }
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
- }
1692
- } else {
1693
- for (const child of node.body) {
1694
- visit(child);
1695
- }
1696
- }
1821
+ } else {
1822
+ edit = {
1823
+ newText: params.newName,
1824
+ range: docLocationAtTextSpan(renameDoc, rename.textSpan)
1825
+ };
1826
+ }
1827
+ if (edit) {
1828
+ if (changes[renameURI]) {
1829
+ changes[renameURI].push(edit);
1830
+ } else {
1831
+ changes[renameURI] = [edit];
1832
+ }
1833
+ }
1834
+ }
1835
+ return {
1836
+ changes
1837
+ };
1838
+ },
1839
+ doValidate(doc) {
1840
+ const fileName = getFSPath(doc);
1841
+ if (!fileName)
1842
+ return;
1843
+ const project = getTSProject(fileName);
1844
+ const extracted = processScript(doc, project);
1845
+ let results;
1846
+ for (const tsDiag of project.service.getSuggestionDiagnostics(fileName)) {
1847
+ addDiag(tsDiag);
1848
+ }
1849
+ for (const tsDiag of project.service.getSyntacticDiagnostics(fileName)) {
1850
+ addDiag(tsDiag);
1851
+ }
1852
+ for (const tsDiag of project.service.getSemanticDiagnostics(fileName)) {
1853
+ addDiag(tsDiag);
1854
+ }
1855
+ return results;
1856
+ function addDiag(tsDiag) {
1857
+ const diag = convertDiag(extracted, tsDiag);
1858
+ if (diag && !IGNORE_DIAG_REG.test(diag.message)) {
1859
+ if (results) {
1860
+ results.push(diag);
1861
+ } else {
1862
+ results = [diag];
1863
+ }
1864
+ }
1865
+ }
1866
+ }
1867
+ };
1868
+ function processScript(doc, tsProject) {
1869
+ return processDoc(doc, ({ parsed, filename, project: markoProject }) => {
1870
+ var _a;
1871
+ const { lookup } = markoProject;
1872
+ const { host, markoScriptLang } = tsProject;
1873
+ return extractScript2({
1874
+ ts,
1875
+ parsed,
1876
+ lookup,
1877
+ scriptLang: getScriptLang(filename, ts, host, markoScriptLang),
1878
+ runtimeTypesCode: (_a = getProjectTypeLibs(markoProject, ts, host)) == null ? void 0 : _a.markoTypesCode,
1879
+ componentFilename: getComponentFilename(filename, host)
1880
+ });
1881
+ });
1882
+ }
1883
+ function getInsertModuleStatementOffset(parsed) {
1884
+ const { program } = parsed;
1885
+ let firstNode;
1886
+ if (program.static.length) {
1887
+ let lastImport;
1888
+ for (const node of program.static) {
1889
+ switch (node.type) {
1890
+ case NodeType9.Export:
1891
+ return node.start;
1892
+ case NodeType9.Import:
1893
+ lastImport = node;
1894
+ break;
1895
+ }
1896
+ }
1897
+ if (lastImport) {
1898
+ return lastImport.end + 1;
1899
+ }
1900
+ firstNode = program.static[0];
1901
+ }
1902
+ if (program.body.length) {
1903
+ if (!firstNode || firstNode.start > program.body[0].start) {
1904
+ firstNode = program.body[0];
1905
+ }
1906
+ }
1907
+ if (firstNode) {
1908
+ return getOffsetAfterComments(firstNode);
1909
+ }
1910
+ return 0;
1911
+ }
1912
+ function getOffsetAfterComments(node) {
1913
+ const { comments } = node;
1914
+ if (comments) {
1915
+ return comments.at(-1).end + 1;
1916
+ }
1917
+ return Math.max(0, node.start - 1);
1918
+ }
1919
+ function sourceLocationAtTextSpan(extracted, { start, length }) {
1920
+ if (start === 0 && length === 0)
1921
+ return START_LOCATION;
1922
+ return extracted.sourceLocationAt(start, start + length);
1923
+ }
1924
+ function docLocationAtTextSpan(doc, { start, length }) {
1925
+ return {
1926
+ start: doc.positionAt(start),
1927
+ end: doc.positionAt(start + length)
1928
+ };
1929
+ }
1930
+ function getTSProject(docFsPath) {
1931
+ var _a;
1932
+ let configPath;
1933
+ let markoScriptLang = ScriptLang3.js;
1934
+ if (docFsPath) {
1935
+ configPath = ts.findConfigFile(
1936
+ docFsPath,
1937
+ ts.sys.fileExists,
1938
+ "tsconfig.json"
1939
+ );
1940
+ if (configPath) {
1941
+ markoScriptLang = ScriptLang3.ts;
1942
+ } else {
1943
+ configPath = ts.findConfigFile(
1944
+ docFsPath,
1945
+ ts.sys.fileExists,
1946
+ "jsconfig.json"
1947
+ );
1948
+ }
1949
+ }
1950
+ const rootDir = configPath && path9.dirname(configPath) || process.cwd();
1951
+ const markoProject = getMarkoProject(configPath && rootDir);
1952
+ let projectCache = markoProject.cache.get(getTSProject);
1953
+ let cached;
1954
+ if (projectCache) {
1955
+ cached = projectCache.get(rootDir);
1956
+ if (cached)
1957
+ return cached;
1958
+ } else {
1959
+ projectCache = /* @__PURE__ */ new Map();
1960
+ markoProject.cache.set(getTSProject, projectCache);
1961
+ }
1962
+ const { fileNames, options, projectReferences } = ts.parseJsonConfigFileContent(
1963
+ configPath && ts.readConfigFile(configPath, ts.sys.readFile).config || {
1964
+ compilerOptions: { lib: ["dom", "node", "esnext"] }
1965
+ },
1966
+ ts.sys,
1967
+ rootDir,
1968
+ void 0,
1969
+ configPath,
1970
+ void 0,
1971
+ [
1972
+ {
1973
+ extension: ".marko",
1974
+ isMixedContent: false,
1975
+ scriptKind: ts.ScriptKind.Deferred
1976
+ }
1977
+ ]
1978
+ );
1979
+ const potentialGlobalFiles = new Set(
1980
+ fileNames.filter((file) => /\.[cm]?ts$/.test(file))
1981
+ );
1982
+ options.rootDir ??= rootDir;
1983
+ options.module = ts.ModuleKind.ESNext;
1984
+ options.moduleResolution = ts.ModuleResolutionKind.NodeJs;
1985
+ options.noEmit = options.allowJs = options.declaration = options.skipLibCheck = options.isolatedModules = options.resolveJsonModule = options.skipDefaultLibCheck = options.allowNonTsExtensions = true;
1986
+ const tsPkgFile = configPath && ((_a = ts.resolveModuleName("typescript/package.json", configPath, options, ts.sys).resolvedModule) == null ? void 0 : _a.resolvedFileName);
1987
+ const defaultLibFile = path9.join(
1988
+ tsPkgFile ? path9.join(tsPkgFile, "../lib") : __dirname,
1989
+ ts.getDefaultLibFileName(options)
1990
+ );
1991
+ const host = patch(
1992
+ ts,
1993
+ markoScriptLang,
1994
+ extractCache,
1995
+ {
1996
+ getNewLine() {
1997
+ return ts.sys.newLine;
1998
+ },
1999
+ useCaseSensitiveFileNames() {
2000
+ return ts.sys.useCaseSensitiveFileNames;
2001
+ },
2002
+ getCompilationSettings() {
2003
+ return options;
2004
+ },
2005
+ getCurrentDirectory() {
2006
+ return options.rootDir;
2007
+ },
2008
+ getProjectVersion() {
2009
+ return projectVersion.toString(32);
2010
+ },
2011
+ getDefaultLibFileName() {
2012
+ return defaultLibFile;
2013
+ },
2014
+ getProjectReferences() {
2015
+ return projectReferences;
2016
+ },
2017
+ resolveModuleNames(moduleNames, containingFile) {
2018
+ return moduleNames.map((moduleName) => {
2019
+ return ts.resolveModuleName(moduleName, containingFile, options, host).resolvedModule;
2020
+ });
2021
+ },
2022
+ readDirectory: ts.sys.readDirectory,
2023
+ readFile: (filename) => {
2024
+ var _a2;
2025
+ return (_a2 = get(filenameToURI(filename))) == null ? void 0 : _a2.getText();
2026
+ },
2027
+ fileExists: (filename) => exists(filenameToURI(filename)),
2028
+ getScriptFileNames() {
2029
+ const result = new Set(potentialGlobalFiles);
2030
+ for (const doc of getAllOpen()) {
2031
+ const { scheme, fsPath } = URI6.parse(doc.uri);
2032
+ if (scheme === "file")
2033
+ result.add(fsPath);
1697
2034
  }
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
- }
2035
+ return [...result];
2036
+ },
2037
+ getScriptVersion(filename) {
2038
+ var _a2;
2039
+ return `${((_a2 = get(filenameToURI(filename))) == null ? void 0 : _a2.version) ?? -1}`;
2040
+ },
2041
+ getScriptKind(filename) {
2042
+ switch (path9.extname(filename)) {
2043
+ case ts.Extension.Js:
2044
+ return ts.ScriptKind.JS;
2045
+ case ts.Extension.Jsx:
2046
+ return ts.ScriptKind.JSX;
2047
+ case ts.Extension.Ts:
2048
+ return ts.ScriptKind.TS;
2049
+ case ts.Extension.Tsx:
2050
+ return ts.ScriptKind.TSX;
2051
+ case ts.Extension.Json:
2052
+ return ts.ScriptKind.JSON;
2053
+ default:
2054
+ return ts.ScriptKind.Unknown;
1710
2055
  }
1711
- break;
2056
+ },
2057
+ getScriptSnapshot(filename) {
2058
+ let snapshot = snapshotCache.get(filename);
2059
+ if (!snapshot) {
2060
+ const doc = get(filenameToURI(filename));
2061
+ if (!doc)
2062
+ return;
2063
+ snapshot = ts.ScriptSnapshot.fromString(doc.getText());
2064
+ snapshotCache.set(filename, snapshot);
2065
+ }
2066
+ return snapshot;
2067
+ }
1712
2068
  }
2069
+ );
2070
+ const tsProject = {
2071
+ host,
2072
+ rootDir: options.rootDir,
2073
+ service: ts.createLanguageService(host),
2074
+ markoProject,
2075
+ markoScriptLang,
2076
+ markoProjectTypeLibs: getProjectTypeLibs(markoProject, ts, host)
1713
2077
  };
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();
2078
+ projectCache.set(rootDir, tsProject);
2079
+ return tsProject;
2080
+ }
2081
+ function filenameToURI(filename) {
2082
+ return URI6.file(filename).toString();
2083
+ }
2084
+ async function getPreferences(scriptLang) {
2085
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2086
+ const configName = scriptLang === ScriptLang3.js ? "javascript" : "typescript";
2087
+ const [preferencesConfig, suggestConfig, inlayHintsConfig] = await Promise.all([
2088
+ getConfig(`${configName}.preferences`),
2089
+ getConfig(`${configName}.suggest`),
2090
+ getConfig(`${configName}.inlayHints`)
2091
+ ]);
2092
+ return {
2093
+ disableSuggestions: suggestConfig.enabled === false,
2094
+ quotePreference: preferencesConfig.quoteStyle || "auto",
2095
+ includeCompletionsForModuleExports: suggestConfig.autoImports ?? true,
2096
+ includeCompletionsForImportStatements: suggestConfig.includeCompletionsForImportStatements ?? true,
2097
+ includeCompletionsWithSnippetText: suggestConfig.includeCompletionsWithSnippetText ?? true,
2098
+ includeAutomaticOptionalChainCompletions: suggestConfig.includeAutomaticOptionalChainCompletions ?? true,
2099
+ includeCompletionsWithInsertText: true,
2100
+ includeCompletionsWithClassMemberSnippets: ((_a = suggestConfig.classMemberSnippets) == null ? void 0 : _a.enabled) ?? true,
2101
+ includeCompletionsWithObjectLiteralMethodSnippets: ((_b = suggestConfig.objectLiteralMethodSnippets) == null ? void 0 : _b.enabled) ?? true,
2102
+ useLabelDetailsInCompletionEntries: true,
2103
+ allowIncompleteCompletions: true,
2104
+ importModuleSpecifierPreference: preferencesConfig.importModuleSpecifierPreference,
2105
+ importModuleSpecifierEnding: preferencesConfig.importModuleSpecifierEnding || "auto",
2106
+ allowTextChangesInNewFiles: true,
2107
+ providePrefixAndSuffixTextForRename: true,
2108
+ includePackageJsonAutoImports: preferencesConfig.includePackageJsonAutoImports ?? true,
2109
+ provideRefactorNotApplicableReason: true,
2110
+ jsxAttributeCompletionStyle: preferencesConfig.jsxAttributeCompletionStyle ?? "auto",
2111
+ includeInlayParameterNameHints: ((_c = inlayHintsConfig.parameterNames) == null ? void 0 : _c.enabled) ?? "none",
2112
+ includeInlayParameterNameHintsWhenArgumentMatchesName: !((_d = inlayHintsConfig.parameterNames) == null ? void 0 : _d.suppressWhenArgumentMatchesName),
2113
+ includeInlayFunctionParameterTypeHints: ((_e = inlayHintsConfig.parameterTypes) == null ? void 0 : _e.enabled) ?? true,
2114
+ includeInlayVariableTypeHints: ((_f = inlayHintsConfig.variableTypes) == null ? void 0 : _f.enabled) ?? true,
2115
+ includeInlayPropertyDeclarationTypeHints: ((_g = inlayHintsConfig.propertyDeclarationTypes) == null ? void 0 : _g.enabled) ?? true,
2116
+ includeInlayFunctionLikeReturnTypeHints: ((_h = inlayHintsConfig.functionLikeReturnTypes) == null ? void 0 : _h.enabled) ?? true,
2117
+ includeInlayEnumMemberValueHints: ((_i = inlayHintsConfig.enumMemberValues) == null ? void 0 : _i.enabled) ?? true
2118
+ };
2119
+ }
2120
+ function printDocumentation(docs2, tags) {
2121
+ let result = "";
2122
+ if (docs2) {
2123
+ result += ts.displayPartsToString(docs2);
2124
+ }
2125
+ if (tags) {
2126
+ for (const tag of tags) {
2127
+ const text = ts.displayPartsToString(tag.text);
2128
+ result += `*@${tag.name}*${text ? /\n/.test(text) ? `
2129
+ ${text}` : `- ${text}` : ""}`;
2130
+ }
2131
+ }
2132
+ return result;
2133
+ }
2134
+ function convertDiag(extracted, tsDiag) {
2135
+ const sourceRange = tsDiag.start === void 0 ? START_LOCATION : sourceLocationAtTextSpan(extracted, tsDiag);
2136
+ if (sourceRange) {
2137
+ return {
2138
+ range: sourceRange,
2139
+ source: "script",
2140
+ code: tsDiag.code,
2141
+ tags: convertDiagTags(tsDiag),
2142
+ severity: convertDiagSeverity(tsDiag),
2143
+ message: ts.flattenDiagnosticMessageText(tsDiag.messageText, "\n")
2144
+ };
2145
+ }
2146
+ }
2147
+ function convertDiagSeverity(tsDiag) {
2148
+ switch (tsDiag.category) {
2149
+ case ts.DiagnosticCategory.Error:
2150
+ return DiagnosticSeverity2.Error;
2151
+ case ts.DiagnosticCategory.Warning:
2152
+ return DiagnosticSeverity2.Warning;
2153
+ case ts.DiagnosticCategory.Suggestion:
2154
+ return DiagnosticSeverity2.Hint;
2155
+ default:
2156
+ return DiagnosticSeverity2.Information;
2157
+ }
2158
+ }
2159
+ function convertDiagTags(tsDiag) {
2160
+ let tags;
2161
+ if (tsDiag.reportsDeprecated) {
2162
+ tags = [DiagnosticTag.Deprecated];
2163
+ }
2164
+ if (tsDiag.reportsUnnecessary) {
2165
+ if (tags)
2166
+ tags.push(DiagnosticTag.Unnecessary);
2167
+ else
2168
+ tags = [DiagnosticTag.Unnecessary];
2169
+ }
2170
+ return tags;
2171
+ }
2172
+ function convertCompletionItemKind(kind) {
2173
+ switch (kind) {
2174
+ case ts.ScriptElementKind.warning:
2175
+ case ts.ScriptElementKind.linkText:
2176
+ return CompletionItemKind5.Text;
2177
+ case ts.ScriptElementKind.keyword:
2178
+ case ts.ScriptElementKind.primitiveType:
2179
+ return CompletionItemKind5.Keyword;
2180
+ case ts.ScriptElementKind.scriptElement:
2181
+ return CompletionItemKind5.File;
2182
+ case ts.ScriptElementKind.directory:
2183
+ return CompletionItemKind5.Folder;
2184
+ case ts.ScriptElementKind.label:
2185
+ case ts.ScriptElementKind.string:
2186
+ return CompletionItemKind5.Constant;
2187
+ case ts.ScriptElementKind.moduleElement:
2188
+ case ts.ScriptElementKind.externalModuleName:
2189
+ return CompletionItemKind5.Module;
2190
+ case ts.ScriptElementKind.typeElement:
2191
+ case ts.ScriptElementKind.classElement:
2192
+ case ts.ScriptElementKind.localClassElement:
2193
+ return CompletionItemKind5.Class;
2194
+ case ts.ScriptElementKind.interfaceElement:
2195
+ return CompletionItemKind5.Interface;
2196
+ case ts.ScriptElementKind.enumElement:
2197
+ return CompletionItemKind5.Enum;
2198
+ case ts.ScriptElementKind.enumMemberElement:
2199
+ return CompletionItemKind5.EnumMember;
2200
+ case ts.ScriptElementKind.alias:
2201
+ case ts.ScriptElementKind.letElement:
2202
+ case ts.ScriptElementKind.constElement:
2203
+ case ts.ScriptElementKind.variableElement:
2204
+ case ts.ScriptElementKind.parameterElement:
2205
+ case ts.ScriptElementKind.localVariableElement:
2206
+ return CompletionItemKind5.Variable;
2207
+ case ts.ScriptElementKind.functionElement:
2208
+ case ts.ScriptElementKind.localFunctionElement:
2209
+ return CompletionItemKind5.Function;
2210
+ case ts.ScriptElementKind.callSignatureElement:
2211
+ case ts.ScriptElementKind.memberFunctionElement:
2212
+ case ts.ScriptElementKind.indexSignatureElement:
2213
+ case ts.ScriptElementKind.constructSignatureElement:
2214
+ return CompletionItemKind5.Method;
2215
+ case ts.ScriptElementKind.memberGetAccessorElement:
2216
+ case ts.ScriptElementKind.memberSetAccessorElement:
2217
+ case ts.ScriptElementKind.memberVariableElement:
2218
+ return CompletionItemKind5.Field;
2219
+ case ts.ScriptElementKind.constructorImplementationElement:
2220
+ return CompletionItemKind5.Constructor;
2221
+ case ts.ScriptElementKind.typeParameterElement:
2222
+ return CompletionItemKind5.TypeParameter;
2223
+ case ts.ScriptElementKind.link:
2224
+ case ts.ScriptElementKind.linkName:
2225
+ return CompletionItemKind5.Reference;
2226
+ default:
2227
+ return CompletionItemKind5.Property;
1719
2228
  }
1720
- return resultsByExt;
2229
+ }
2230
+ function getTSTriggerChar(char) {
2231
+ if (char && tsTriggerChars.has(char))
2232
+ return char;
1721
2233
  }
1722
2234
 
1723
- // src/service/stylesheet/index.ts
1724
- var cache3 = /* @__PURE__ */ new WeakMap();
2235
+ // src/service/style/index.ts
2236
+ import {
2237
+ getCSSLanguageService,
2238
+ getLESSLanguageService,
2239
+ getSCSSLanguageService
2240
+ } from "vscode-css-languageservice";
2241
+ import {
2242
+ TextDocumentEdit
2243
+ } from "vscode-languageserver";
2244
+ import { TextDocument as TextDocument2 } from "vscode-languageserver-textdocument";
2245
+ import { extractStyle } from "@marko/language-tools";
1725
2246
  var services = {
1726
- css: getCSSLanguageService,
1727
- less: getLESSLanguageService,
1728
- scss: getSCSSLanguageService
2247
+ ".css": getCSSLanguageService,
2248
+ ".less": getLESSLanguageService,
2249
+ ".scss": getSCSSLanguageService
1729
2250
  };
1730
2251
  var clientCapabilities;
1731
2252
  var StyleSheetService = {
@@ -1733,70 +2254,58 @@ var StyleSheetService = {
1733
2254
  clientCapabilities = params.capabilities;
1734
2255
  },
1735
2256
  async doComplete(doc, params) {
1736
- const infoByExt = getStyleSheetInfo(doc);
1737
2257
  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)
2258
+ for (const style of processStyle(doc)) {
2259
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2260
+ if (generatedPos === void 0)
1742
2261
  continue;
1743
- const { service: service2, virtualDoc } = info;
1744
- const result = await service2.doComplete2(
1745
- virtualDoc,
1746
- virtualDoc.positionAt(generatedOffset),
1747
- info.parsed,
2262
+ const result = await style.service.doComplete2(
2263
+ style.virtualDoc,
2264
+ generatedPos,
2265
+ style.parsed,
1748
2266
  { resolveReference: resolveUrl }
1749
2267
  );
1750
2268
  if (result.itemDefaults) {
1751
2269
  const { editRange } = result.itemDefaults;
1752
2270
  if (editRange) {
1753
2271
  if ("start" in editRange) {
1754
- result.itemDefaults.editRange = getSourceRange(
1755
- doc,
1756
- info,
1757
- editRange
1758
- );
2272
+ result.itemDefaults.editRange = getSourceRange(style, editRange);
1759
2273
  } else {
1760
- editRange.insert = getSourceRange(doc, info, editRange.insert);
1761
- editRange.replace = getSourceRange(doc, info, editRange.replace);
2274
+ editRange.insert = getSourceRange(style, editRange.insert);
2275
+ editRange.replace = getSourceRange(style, editRange.replace);
1762
2276
  }
1763
2277
  }
1764
2278
  }
1765
2279
  for (const item of result.items) {
1766
2280
  if (item.textEdit) {
1767
- item.textEdit = getSourceInsertReplaceEdit(doc, info, item.textEdit);
2281
+ item.textEdit = getSourceInsertReplaceEdit(style, item.textEdit);
1768
2282
  }
1769
2283
  if (item.additionalTextEdits) {
1770
2284
  item.additionalTextEdits = getSourceEdits(
1771
- doc,
1772
- info,
2285
+ style,
1773
2286
  item.additionalTextEdits
1774
2287
  );
1775
2288
  }
1776
2289
  }
1777
2290
  return result;
1778
2291
  }
1779
- return CompletionList2.create([], true);
1780
2292
  },
1781
2293
  findDefinition(doc, params) {
1782
- const infoByExt = getStyleSheetInfo(doc);
1783
2294
  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)
2295
+ for (const style of processStyle(doc)) {
2296
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2297
+ if (generatedPos === void 0)
1788
2298
  continue;
1789
- const { service: service2, virtualDoc } = info;
1790
- const result = service2.findDefinition(
1791
- virtualDoc,
1792
- virtualDoc.positionAt(generatedOffset),
1793
- info.parsed
2299
+ const result = style.service.findDefinition(
2300
+ style.virtualDoc,
2301
+ generatedPos,
2302
+ style.parsed
1794
2303
  );
1795
2304
  if (result) {
1796
- const range = getSourceRange(doc, info, result.range);
1797
- if (range) {
2305
+ const sourceRange = getSourceRange(style, result.range);
2306
+ if (sourceRange) {
1798
2307
  return {
1799
- range,
2308
+ range: sourceRange,
1800
2309
  uri: doc.uri
1801
2310
  };
1802
2311
  }
@@ -1805,24 +2314,21 @@ var StyleSheetService = {
1805
2314
  }
1806
2315
  },
1807
2316
  findReferences(doc, params) {
1808
- const infoByExt = getStyleSheetInfo(doc);
1809
2317
  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)
2318
+ for (const style of processStyle(doc)) {
2319
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2320
+ if (generatedPos === void 0)
1814
2321
  continue;
1815
- const { service: service2, virtualDoc } = info;
1816
2322
  const result = [];
1817
- for (const location of service2.findReferences(
1818
- virtualDoc,
1819
- virtualDoc.positionAt(generatedOffset),
1820
- info.parsed
2323
+ for (const location of style.service.findReferences(
2324
+ style.virtualDoc,
2325
+ generatedPos,
2326
+ style.parsed
1821
2327
  )) {
1822
- const range = getSourceRange(doc, info, location.range);
1823
- if (range) {
2328
+ const sourceRange = getSourceRange(style, location.range);
2329
+ if (sourceRange) {
1824
2330
  result.push({
1825
- range,
2331
+ range: sourceRange,
1826
2332
  uri: location.uri
1827
2333
  });
1828
2334
  }
@@ -1831,25 +2337,22 @@ var StyleSheetService = {
1831
2337
  }
1832
2338
  },
1833
2339
  findDocumentSymbols(doc) {
1834
- const infoByExt = getStyleSheetInfo(doc);
1835
2340
  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
2341
+ for (const extracted of processStyle(doc)) {
2342
+ for (const symbol of extracted.service.findDocumentSymbols(
2343
+ extracted.virtualDoc,
2344
+ extracted.parsed
1842
2345
  )) {
1843
2346
  if (symbol.location.uri === doc.uri) {
1844
- const range = getSourceRange(doc, info, symbol.location.range);
1845
- if (range) {
2347
+ const sourceRange = getSourceRange(extracted, symbol.location.range);
2348
+ if (sourceRange) {
1846
2349
  result.push({
1847
2350
  kind: symbol.kind,
1848
2351
  name: symbol.name,
1849
2352
  tags: symbol.tags,
1850
2353
  deprecated: symbol.deprecated,
1851
2354
  containerName: symbol.containerName,
1852
- location: { uri: doc.uri, range }
2355
+ location: { uri: doc.uri, range: sourceRange }
1853
2356
  });
1854
2357
  }
1855
2358
  } else {
@@ -1860,20 +2363,17 @@ var StyleSheetService = {
1860
2363
  return result.length ? result : void 0;
1861
2364
  },
1862
2365
  async findDocumentLinks(doc) {
1863
- const infoByExt = getStyleSheetInfo(doc);
1864
2366
  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,
2367
+ for (const extracted of processStyle(doc)) {
2368
+ for (const link of await extracted.service.findDocumentLinks2(
2369
+ extracted.virtualDoc,
2370
+ extracted.parsed,
1871
2371
  { resolveReference: resolveUrl }
1872
2372
  )) {
1873
- const range = getSourceRange(doc, info, link.range);
1874
- if (range) {
2373
+ const sourceRange = getSourceRange(extracted, link.range);
2374
+ if (sourceRange) {
1875
2375
  result.push({
1876
- range,
2376
+ range: sourceRange,
1877
2377
  target: link.target,
1878
2378
  tooltip: link.tooltip,
1879
2379
  data: link.data
@@ -1884,24 +2384,21 @@ var StyleSheetService = {
1884
2384
  return result.length ? result : void 0;
1885
2385
  },
1886
2386
  findDocumentHighlights(doc, params) {
1887
- const infoByExt = getStyleSheetInfo(doc);
1888
2387
  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)
2388
+ for (const style of processStyle(doc)) {
2389
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2390
+ if (generatedPos === void 0)
1893
2391
  continue;
1894
- const { service: service2, virtualDoc } = info;
1895
2392
  const result = [];
1896
- for (const highlight of service2.findDocumentHighlights(
1897
- virtualDoc,
1898
- virtualDoc.positionAt(generatedOffset),
1899
- info.parsed
2393
+ for (const highlight of style.service.findDocumentHighlights(
2394
+ style.virtualDoc,
2395
+ generatedPos,
2396
+ style.parsed
1900
2397
  )) {
1901
- const range = getSourceRange(doc, info, highlight.range);
1902
- if (range) {
2398
+ const sourceRange = getSourceRange(style, highlight.range);
2399
+ if (sourceRange) {
1903
2400
  result.push({
1904
- range,
2401
+ range: sourceRange,
1905
2402
  kind: highlight.kind
1906
2403
  });
1907
2404
  }
@@ -1910,19 +2407,16 @@ var StyleSheetService = {
1910
2407
  }
1911
2408
  },
1912
2409
  findDocumentColors(doc) {
1913
- const infoByExt = getStyleSheetInfo(doc);
1914
2410
  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
2411
+ for (const extracted of processStyle(doc)) {
2412
+ for (const colorInfo of extracted.service.findDocumentColors(
2413
+ extracted.virtualDoc,
2414
+ extracted.parsed
1921
2415
  )) {
1922
- const range = getSourceRange(doc, info, colorInfo.range);
1923
- if (range) {
2416
+ const sourceRange = getSourceRange(extracted, colorInfo.range);
2417
+ if (sourceRange) {
1924
2418
  result.push({
1925
- range,
2419
+ range: sourceRange,
1926
2420
  color: colorInfo.color
1927
2421
  });
1928
2422
  }
@@ -1931,31 +2425,19 @@ var StyleSheetService = {
1931
2425
  return result.length ? result : void 0;
1932
2426
  },
1933
2427
  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)
2428
+ for (const extracted of processStyle(doc)) {
2429
+ const generatedRange = getGeneratedRange(doc, extracted, params.range);
2430
+ if (generatedRange === void 0)
1940
2431
  continue;
1941
- const generatedOffsetEnd = info.generatedOffsetAt(
1942
- doc.offsetAt(params.range.end)
1943
- );
1944
- if (generatedOffsetEnd === void 0)
1945
- continue;
1946
- const { service: service2, virtualDoc } = info;
1947
2432
  const result = [];
1948
- for (const colorPresentation of service2.getColorPresentations(
1949
- virtualDoc,
1950
- info.parsed,
2433
+ for (const colorPresentation of extracted.service.getColorPresentations(
2434
+ extracted.virtualDoc,
2435
+ extracted.parsed,
1951
2436
  params.color,
1952
- Range8.create(
1953
- virtualDoc.positionAt(generatedOffsetStart),
1954
- virtualDoc.positionAt(generatedOffsetEnd)
1955
- )
2437
+ generatedRange
1956
2438
  )) {
1957
- const textEdit = colorPresentation.textEdit && getSourceEdit(doc, info, colorPresentation.textEdit);
1958
- const additionalTextEdits = colorPresentation.additionalTextEdits && getSourceEdits(doc, info, colorPresentation.additionalTextEdits);
2439
+ const textEdit = colorPresentation.textEdit && getSourceEdit(extracted, colorPresentation.textEdit);
2440
+ const additionalTextEdits = colorPresentation.additionalTextEdits && getSourceEdits(extracted, colorPresentation.additionalTextEdits);
1959
2441
  if (textEdit || additionalTextEdits) {
1960
2442
  result.push({
1961
2443
  label: colorPresentation.label,
@@ -1968,25 +2450,22 @@ var StyleSheetService = {
1968
2450
  }
1969
2451
  },
1970
2452
  doHover(doc, params) {
1971
- const infoByExt = getStyleSheetInfo(doc);
1972
2453
  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)
2454
+ for (const style of processStyle(doc)) {
2455
+ const generatedPos = style.extracted.generatedPositionAt(sourceOffset);
2456
+ if (generatedPos === void 0)
1977
2457
  continue;
1978
- const { service: service2, virtualDoc } = info;
1979
- const result = service2.doHover(
1980
- virtualDoc,
1981
- virtualDoc.positionAt(generatedOffset),
1982
- info.parsed
2458
+ const result = style.service.doHover(
2459
+ style.virtualDoc,
2460
+ generatedPos,
2461
+ style.parsed
1983
2462
  );
1984
2463
  if (result) {
1985
2464
  if (result.range) {
1986
- const range = getSourceRange(doc, info, result.range);
1987
- if (range) {
2465
+ const sourceRange = getSourceRange(style, result.range);
2466
+ if (sourceRange) {
1988
2467
  return {
1989
- range,
2468
+ range: sourceRange,
1990
2469
  contents: result.contents
1991
2470
  };
1992
2471
  }
@@ -1997,24 +2476,21 @@ var StyleSheetService = {
1997
2476
  }
1998
2477
  },
1999
2478
  async doRename(doc, params) {
2000
- const infoByExt = getStyleSheetInfo(doc);
2001
2479
  const sourceOffset = doc.offsetAt(params.position);
2002
- for (const ext in infoByExt) {
2003
- const info = infoByExt[ext];
2004
- const generatedOffset = info.generatedOffsetAt(sourceOffset);
2480
+ for (const style of processStyle(doc)) {
2481
+ const generatedOffset = style.extracted.generatedOffsetAt(sourceOffset);
2005
2482
  if (generatedOffset === void 0)
2006
2483
  continue;
2007
- const { service: service2, virtualDoc } = info;
2008
- const result = service2.doRename(
2009
- virtualDoc,
2010
- virtualDoc.positionAt(generatedOffset),
2484
+ const result = style.service.doRename(
2485
+ style.virtualDoc,
2486
+ style.virtualDoc.positionAt(generatedOffset),
2011
2487
  params.newName,
2012
- info.parsed
2488
+ style.parsed
2013
2489
  );
2014
2490
  if (result.changes) {
2015
2491
  for (const uri in result.changes) {
2016
2492
  if (uri === doc.uri) {
2017
- result.changes[uri] = getSourceEdits(doc, info, result.changes[uri]) || [];
2493
+ result.changes[uri] = getSourceEdits(style, result.changes[uri]) || [];
2018
2494
  }
2019
2495
  }
2020
2496
  }
@@ -2022,7 +2498,7 @@ var StyleSheetService = {
2022
2498
  for (const change of result.documentChanges) {
2023
2499
  if (TextDocumentEdit.is(change)) {
2024
2500
  if (change.textDocument.uri === doc.uri) {
2025
- change.edits = getSourceEdits(doc, info, change.edits) || [];
2501
+ change.edits = getSourceEdits(style, change.edits) || [];
2026
2502
  }
2027
2503
  }
2028
2504
  }
@@ -2032,49 +2508,36 @@ var StyleSheetService = {
2032
2508
  },
2033
2509
  doCodeActions(doc, params) {
2034
2510
  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)
2511
+ for (const extracted of processStyle(doc)) {
2512
+ const generatedRange = getGeneratedRange(doc, extracted, params.range);
2513
+ if (generatedRange === void 0)
2046
2514
  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
- ),
2515
+ const result = extracted.service.doCodeActions(
2516
+ extracted.virtualDoc,
2517
+ generatedRange,
2054
2518
  params.context,
2055
- info.parsed
2519
+ extracted.parsed
2056
2520
  );
2057
2521
  for (const command of result) {
2058
2522
  const edits = (_a = command.arguments) == null ? void 0 : _a[2];
2059
2523
  if (edits && Array.isArray(edits) && isTextEdit(edits[0])) {
2060
- command.arguments[2] = getSourceEdits(doc, info, edits);
2524
+ command.arguments[2] = getSourceEdits(extracted, edits);
2061
2525
  }
2062
2526
  }
2063
2527
  return result;
2064
2528
  }
2065
2529
  },
2066
2530
  doValidate(doc) {
2067
- const infoByExt = getStyleSheetInfo(doc);
2068
2531
  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
2532
+ for (const extracted of processStyle(doc)) {
2533
+ for (const diag of extracted.service.doValidation(
2534
+ extracted.virtualDoc,
2535
+ extracted.parsed
2074
2536
  )) {
2075
- const range = getSourceRange(doc, info, diag.range);
2076
- if (range) {
2077
- diag.range = range;
2537
+ const sourceRange = getSourceRange(extracted, diag.range);
2538
+ if (sourceRange) {
2539
+ diag.source = "style";
2540
+ diag.range = sourceRange;
2078
2541
  result.push(diag);
2079
2542
  }
2080
2543
  }
@@ -2082,123 +2545,112 @@ var StyleSheetService = {
2082
2545
  return result.length ? result : void 0;
2083
2546
  }
2084
2547
  };
2085
- function getSourceEdits(doc, info, edits) {
2548
+ function processStyle(doc) {
2549
+ return processDoc(doc, ({ uri, version, parsed, project: { lookup } }) => {
2550
+ var _a;
2551
+ const result = [];
2552
+ for (const [ext, extracted] of extractStyle({
2553
+ parsed,
2554
+ lookup
2555
+ })) {
2556
+ const service2 = (_a = services[ext]) == null ? void 0 : _a.call(services, {
2557
+ fileSystemProvider: file_system_default,
2558
+ clientCapabilities
2559
+ });
2560
+ if (service2) {
2561
+ const virtualDoc = TextDocument2.create(
2562
+ uri,
2563
+ "css",
2564
+ version,
2565
+ extracted.toString()
2566
+ );
2567
+ result.push({
2568
+ service: service2,
2569
+ extracted,
2570
+ virtualDoc,
2571
+ parsed: service2.parseStylesheet(virtualDoc)
2572
+ });
2573
+ }
2574
+ }
2575
+ return result;
2576
+ });
2577
+ }
2578
+ function getSourceEdits(extracted, edits) {
2086
2579
  const result = [];
2087
2580
  for (const edit of edits) {
2088
- const sourceEdit = getSourceEdit(doc, info, edit);
2581
+ const sourceEdit = getSourceEdit(extracted, edit);
2089
2582
  if (sourceEdit) {
2090
2583
  result.push(sourceEdit);
2091
2584
  }
2092
2585
  }
2093
2586
  return result.length ? result : void 0;
2094
2587
  }
2095
- function getSourceEdit(doc, info, textEdit) {
2096
- const range = getSourceRange(doc, info, textEdit.range);
2097
- if (range) {
2588
+ function getSourceEdit(extracted, textEdit) {
2589
+ const sourceRange = getSourceRange(extracted, textEdit.range);
2590
+ if (sourceRange) {
2098
2591
  return {
2099
2592
  newText: textEdit.newText,
2100
- range
2593
+ range: sourceRange
2101
2594
  };
2102
2595
  }
2103
2596
  }
2104
- function getSourceInsertReplaceEdit(doc, info, textEdit) {
2597
+ function getSourceInsertReplaceEdit(extracted, textEdit) {
2105
2598
  if (isTextEdit(textEdit)) {
2106
- return getSourceEdit(doc, info, textEdit);
2599
+ return getSourceEdit(extracted, textEdit);
2107
2600
  } else if (textEdit.replace) {
2108
- const range = getSourceRange(doc, info, textEdit.replace);
2109
- if (range) {
2601
+ const sourceRange = getSourceRange(extracted, textEdit.replace);
2602
+ if (sourceRange) {
2110
2603
  return {
2111
2604
  newText: textEdit.newText,
2112
- replace: range
2605
+ replace: sourceRange
2113
2606
  };
2114
2607
  }
2115
2608
  } else {
2116
- const range = getSourceRange(doc, info, textEdit.insert);
2117
- if (range) {
2609
+ const sourceRange = getSourceRange(extracted, textEdit.insert);
2610
+ if (sourceRange) {
2118
2611
  return {
2119
2612
  newText: textEdit.newText,
2120
- insert: range
2613
+ insert: sourceRange
2121
2614
  };
2122
2615
  }
2123
2616
  }
2124
2617
  }
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
- };
2618
+ function getSourceRange(style, range) {
2619
+ return style.extracted.sourceLocationAt(
2620
+ style.virtualDoc.offsetAt(range.start),
2621
+ style.virtualDoc.offsetAt(range.end)
2622
+ );
2140
2623
  }
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;
2624
+ function getGeneratedRange(doc, style, range) {
2625
+ return style.extracted.generatedLocationAt(
2626
+ doc.offsetAt(range.start),
2627
+ doc.offsetAt(range.end)
2628
+ );
2177
2629
  }
2178
2630
  function isTextEdit(edit) {
2179
2631
  return edit.range !== void 0;
2180
2632
  }
2181
2633
 
2182
2634
  // src/service/index.ts
2183
- var plugins = [marko_default, StyleSheetService];
2635
+ var REG_MARKDOWN_CHARS = /[\\`*_{}[\]<>()#+.!|-]/g;
2636
+ var plugins = [marko_default, ScriptService, StyleSheetService];
2184
2637
  var service = {
2638
+ commands: Object.assign({}, ...plugins.map(({ commands }) => commands)),
2185
2639
  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
- }));
2640
+ await Promise.allSettled(
2641
+ plugins.map((plugin) => {
2642
+ var _a;
2643
+ return (_a = plugin.initialize) == null ? void 0 : _a.call(plugin, params);
2644
+ })
2645
+ );
2190
2646
  },
2191
2647
  async doComplete(doc, params, cancel) {
2192
- let items;
2193
2648
  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;
2649
+ const itemsByLabel = /* @__PURE__ */ new Map();
2650
+ await Promise.allSettled(
2651
+ plugins.map(async (plugin) => {
2652
+ var _a;
2653
+ const cur = await ((_a = plugin.doComplete) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2202
2654
  if (cancel.isCancellationRequested)
2203
2655
  return;
2204
2656
  if (cur) {
@@ -2207,185 +2659,181 @@ var service = {
2207
2659
  curItems = cur;
2208
2660
  } else {
2209
2661
  curItems = cur.items;
2210
- isIncomplete || (isIncomplete = cur.isIncomplete);
2662
+ isIncomplete ||= cur.isIncomplete;
2663
+ }
2664
+ for (const item of curItems) {
2665
+ const { label } = item;
2666
+ const existingItem = itemsByLabel.get(label);
2667
+ if (existingItem) {
2668
+ if ((existingItem.sortText || label) < (item.sortText || label)) {
2669
+ itemsByLabel.set(label, item);
2670
+ }
2671
+ } else {
2672
+ itemsByLabel.set(label, item);
2673
+ }
2211
2674
  }
2212
- items = items ? items.concat(curItems) : curItems;
2213
2675
  }
2214
- }
2215
- } catch (err) {
2216
- isIncomplete = true;
2217
- displayError(err);
2676
+ })
2677
+ );
2678
+ if (cancel.isCancellationRequested)
2679
+ return;
2680
+ if (itemsByLabel.size) {
2681
+ return { items: [...itemsByLabel.values()], isIncomplete };
2218
2682
  }
2219
- if (items) {
2220
- return CompletionList3.create(items, isIncomplete);
2683
+ },
2684
+ async doCompletionResolve(item, cancel) {
2685
+ var _a;
2686
+ for (const plugin of plugins) {
2687
+ try {
2688
+ const result = await ((_a = plugin.doCompletionResolve) == null ? void 0 : _a.call(plugin, item, cancel));
2689
+ if (cancel.isCancellationRequested)
2690
+ return;
2691
+ if (result)
2692
+ return result;
2693
+ } catch {
2694
+ }
2221
2695
  }
2222
2696
  },
2223
2697
  async findDefinition(doc, params, cancel) {
2224
2698
  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;
2699
+ await Promise.allSettled(
2700
+ plugins.map(async (plugin) => {
2701
+ var _a;
2702
+ const cur = await ((_a = plugin.findDefinition) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2233
2703
  if (cancel.isCancellationRequested)
2234
2704
  return;
2235
2705
  if (cur)
2236
2706
  result = (result || []).concat(cur);
2237
- }
2238
- } catch (err) {
2239
- displayError(err);
2240
- }
2707
+ })
2708
+ );
2709
+ if (cancel.isCancellationRequested)
2710
+ return;
2241
2711
  return result;
2242
2712
  },
2243
2713
  async findReferences(doc, params, cancel) {
2244
2714
  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;
2715
+ await Promise.allSettled(
2716
+ plugins.map(async (plugin) => {
2717
+ var _a;
2718
+ const cur = await ((_a = plugin.findReferences) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2253
2719
  if (cancel.isCancellationRequested)
2254
2720
  return;
2255
2721
  if (cur)
2256
- result = result ? result.concat(cur) : cur;
2257
- }
2258
- } catch (err) {
2259
- displayError(err);
2260
- }
2722
+ result = (result || []).concat(cur);
2723
+ })
2724
+ );
2725
+ if (cancel.isCancellationRequested)
2726
+ return;
2261
2727
  return result;
2262
2728
  },
2263
2729
  async findDocumentSymbols(doc, params, cancel) {
2264
2730
  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;
2731
+ await Promise.allSettled(
2732
+ plugins.map(async (plugin) => {
2733
+ var _a;
2734
+ const cur = await ((_a = plugin.findDocumentSymbols) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2273
2735
  if (cancel.isCancellationRequested)
2274
2736
  return;
2275
2737
  if (cur)
2276
- result = result ? result.concat(cur) : cur;
2277
- }
2278
- } catch (err) {
2279
- displayError(err);
2280
- }
2738
+ result = (result || []).concat(cur);
2739
+ })
2740
+ );
2741
+ if (cancel.isCancellationRequested)
2742
+ return;
2281
2743
  return result;
2282
2744
  },
2283
2745
  async findDocumentLinks(doc, params, cancel) {
2284
2746
  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;
2747
+ await Promise.allSettled(
2748
+ plugins.map(async (plugin) => {
2749
+ var _a;
2750
+ const cur = await ((_a = plugin.findDocumentLinks) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2293
2751
  if (cancel.isCancellationRequested)
2294
2752
  return;
2295
2753
  if (cur)
2296
- result = result ? result.concat(cur) : cur;
2297
- }
2298
- } catch (err) {
2299
- displayError(err);
2300
- }
2754
+ result = (result || []).concat(cur);
2755
+ })
2756
+ );
2757
+ if (cancel.isCancellationRequested)
2758
+ return;
2301
2759
  return result;
2302
2760
  },
2303
2761
  async findDocumentHighlights(doc, params, cancel) {
2304
2762
  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;
2763
+ await Promise.allSettled(
2764
+ plugins.map(async (plugin) => {
2765
+ var _a;
2766
+ const cur = await ((_a = plugin.findDocumentHighlights) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2313
2767
  if (cancel.isCancellationRequested)
2314
2768
  return;
2315
2769
  if (cur)
2316
- result = result ? result.concat(cur) : cur;
2317
- }
2318
- } catch (err) {
2319
- displayError(err);
2320
- }
2770
+ result = (result || []).concat(cur);
2771
+ })
2772
+ );
2773
+ if (cancel.isCancellationRequested)
2774
+ return;
2321
2775
  return result;
2322
2776
  },
2323
2777
  async findDocumentColors(doc, params, cancel) {
2324
2778
  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;
2779
+ await Promise.allSettled(
2780
+ plugins.map(async (plugin) => {
2781
+ var _a;
2782
+ const cur = await ((_a = plugin.findDocumentColors) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2333
2783
  if (cancel.isCancellationRequested)
2334
2784
  return;
2335
2785
  if (cur)
2336
- result = result ? result.concat(cur) : cur;
2337
- }
2338
- } catch (err) {
2339
- displayError(err);
2340
- }
2786
+ result = (result || []).concat(cur);
2787
+ })
2788
+ );
2789
+ if (cancel.isCancellationRequested)
2790
+ return;
2341
2791
  return result;
2342
2792
  },
2343
2793
  async getColorPresentations(doc, params, cancel) {
2344
2794
  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;
2795
+ await Promise.allSettled(
2796
+ plugins.map(async (plugin) => {
2797
+ var _a;
2798
+ const cur = await ((_a = plugin.getColorPresentations) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2353
2799
  if (cancel.isCancellationRequested)
2354
2800
  return;
2355
2801
  if (cur)
2356
- result = result ? result.concat(cur) : cur;
2357
- }
2358
- } catch (err) {
2359
- displayError(err);
2360
- }
2802
+ result = (result || []).concat(cur);
2803
+ })
2804
+ );
2805
+ if (cancel.isCancellationRequested)
2806
+ return;
2361
2807
  return result;
2362
2808
  },
2363
2809
  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));
2810
+ let result;
2811
+ await Promise.allSettled(
2812
+ plugins.map(async (plugin) => {
2813
+ var _a;
2814
+ const cur = await ((_a = plugin.doHover) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2368
2815
  if (cancel.isCancellationRequested)
2369
2816
  return;
2370
- if (result)
2371
- return result;
2372
- }
2373
- } catch (err) {
2374
- displayError(err);
2375
- }
2817
+ if (cur) {
2818
+ if (result) {
2819
+ result.range = maxRange(result.range, cur.range);
2820
+ result.contents = mergeHoverContents(result.contents, cur.contents);
2821
+ } else {
2822
+ result = cur;
2823
+ }
2824
+ }
2825
+ })
2826
+ );
2827
+ return result;
2376
2828
  },
2377
2829
  async doRename(doc, params, cancel) {
2378
2830
  let changes;
2379
2831
  let changeAnnotations;
2380
2832
  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;
2833
+ await Promise.allSettled(
2834
+ plugins.map(async (plugin) => {
2835
+ var _a;
2836
+ const cur = await ((_a = plugin.doRename) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2389
2837
  if (cancel.isCancellationRequested)
2390
2838
  return;
2391
2839
  if (cur) {
@@ -2409,10 +2857,10 @@ var service = {
2409
2857
  documentChanges = documentChanges ? documentChanges.concat(cur.documentChanges) : cur.documentChanges;
2410
2858
  }
2411
2859
  }
2412
- }
2413
- } catch (err) {
2414
- displayError(err);
2415
- }
2860
+ })
2861
+ );
2862
+ if (cancel.isCancellationRequested)
2863
+ return;
2416
2864
  if (changes || changeAnnotations || documentChanges) {
2417
2865
  return {
2418
2866
  changes,
@@ -2423,62 +2871,112 @@ var service = {
2423
2871
  },
2424
2872
  async doCodeActions(doc, params, cancel) {
2425
2873
  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;
2874
+ await Promise.allSettled(
2875
+ plugins.map(async (plugin) => {
2876
+ var _a;
2877
+ const cur = await ((_a = plugin.doCodeActions) == null ? void 0 : _a.call(plugin, doc, params, cancel));
2434
2878
  if (cancel.isCancellationRequested)
2435
2879
  return;
2436
2880
  if (cur)
2437
- result = result ? result.concat(cur) : cur;
2438
- }
2439
- } catch (err) {
2440
- displayError(err);
2441
- }
2881
+ result = (result || []).concat(cur);
2882
+ })
2883
+ );
2884
+ if (cancel.isCancellationRequested)
2885
+ return;
2442
2886
  return result;
2443
2887
  },
2444
2888
  async doValidate(doc) {
2445
2889
  let result;
2446
- try {
2447
- for (const pending of plugins.map((plugin) => {
2890
+ await Promise.allSettled(
2891
+ plugins.map(async (plugin) => {
2448
2892
  var _a;
2449
- return (_a = plugin.doValidate) == null ? void 0 : _a.call(plugin, doc);
2450
- })) {
2451
- const cur = await pending;
2893
+ const cur = await ((_a = plugin.doValidate) == null ? void 0 : _a.call(plugin, doc));
2452
2894
  if (cur)
2453
- result = result ? result.concat(cur) : cur;
2454
- }
2455
- } catch (err) {
2456
- displayError(err);
2457
- }
2895
+ result = (result || []).concat(cur);
2896
+ })
2897
+ );
2458
2898
  return result;
2459
2899
  },
2460
2900
  format: marko_default.format
2461
2901
  };
2902
+ function maxRange(a, b) {
2903
+ if (!a)
2904
+ return b;
2905
+ if (!b)
2906
+ return a;
2907
+ return {
2908
+ start: {
2909
+ line: Math.min(a.start.line, b.start.line),
2910
+ character: Math.min(a.start.character, b.start.character)
2911
+ },
2912
+ end: {
2913
+ line: Math.max(a.end.line, b.end.line),
2914
+ character: Math.max(a.end.character, b.end.character)
2915
+ }
2916
+ };
2917
+ }
2918
+ function mergeHoverContents(a, b) {
2919
+ if (!a)
2920
+ return b;
2921
+ if (!b)
2922
+ return a;
2923
+ if (!MarkupContent.is(a)) {
2924
+ a = markedStringToMarkupContent(a);
2925
+ }
2926
+ if (!MarkupContent.is(b)) {
2927
+ b = markedStringToMarkupContent(b);
2928
+ }
2929
+ if (a.kind === b.kind) {
2930
+ return {
2931
+ kind: a.kind,
2932
+ value: `${a.value}
2933
+ ${b.value}`
2934
+ };
2935
+ }
2936
+ return {
2937
+ kind: MarkupKind3.Markdown,
2938
+ value: `${markupContentToMarkdown(a)}
2939
+ ${markupContentToMarkdown(b)}`
2940
+ };
2941
+ }
2942
+ function markedStringToMarkupContent(markedString) {
2943
+ return {
2944
+ kind: MarkupKind3.Markdown,
2945
+ value: Array.isArray(markedString) ? markedString.map((it) => markedStringToString(it)).join("\n") : markedStringToString(markedString)
2946
+ };
2947
+ }
2948
+ function markedStringToString(markedString) {
2949
+ if (typeof markedString === "string") {
2950
+ return markedString;
2951
+ }
2952
+ return `\`\`\`${markedString.language}
2953
+ ${markedString.value}
2954
+ \`\`\``;
2955
+ }
2956
+ function markupContentToMarkdown(content) {
2957
+ return content.kind === MarkupKind3.Markdown ? content.value : escapeMarkdown(content.value);
2958
+ }
2959
+ function escapeMarkdown(str) {
2960
+ return str.replace(REG_MARKDOWN_CHARS, "$1");
2961
+ }
2462
2962
 
2463
2963
  // src/index.ts
2464
2964
  if (typeof __require !== "undefined" && __require.extensions && !(".ts" in __require.extensions)) {
2465
2965
  __require.extensions[".ts"] = void 0;
2466
2966
  }
2467
- var documents = new TextDocuments(TextDocument3);
2468
- var connection2 = createConnection(ProposedFeatures.all);
2967
+ var connection3 = createConnection(ProposedFeatures.all);
2469
2968
  var prevDiags = /* @__PURE__ */ new WeakMap();
2470
- var pendingDiags = /* @__PURE__ */ new WeakSet();
2471
2969
  var diagnosticTimeout;
2472
2970
  console.log = (...args) => {
2473
- connection2.console.log(args.map((v) => inspect2(v)).join(" "));
2971
+ connection3.console.log(args.map((v) => inspect2(v)).join(" "));
2474
2972
  };
2475
2973
  console.error = (...args) => {
2476
- connection2.console.error(args.map((v) => inspect2(v)).join(" "));
2974
+ connection3.console.error(args.map((v) => inspect2(v)).join(" "));
2477
2975
  };
2478
2976
  process.on("uncaughtException", console.error);
2479
2977
  process.on("unhandledRejection", console.error);
2480
- connection2.onInitialize(async (params) => {
2481
- setup(connection2);
2978
+ connection3.onInitialize(async (params) => {
2979
+ setup3(connection3);
2482
2980
  await service.initialize(params);
2483
2981
  return {
2484
2982
  capabilities: {
@@ -2494,6 +2992,7 @@ connection2.onInitialize(async (params) => {
2494
2992
  documentHighlightProvider: true,
2495
2993
  documentSymbolProvider: true,
2496
2994
  completionProvider: {
2995
+ resolveProvider: true,
2497
2996
  triggerCharacters: [
2498
2997
  ".",
2499
2998
  ":",
@@ -2519,111 +3018,123 @@ connection2.onInitialize(async (params) => {
2519
3018
  }
2520
3019
  };
2521
3020
  });
2522
- connection2.onDidChangeConfiguration(validateDocs);
2523
- connection2.onDidChangeWatchedFiles(validateDocs);
2524
- documents.onDidChangeContent(({ document }) => {
2525
- queueDiagnostic();
2526
- pendingDiags.add(document);
2527
- clearCompilerCache(document);
3021
+ setup2(connection3);
3022
+ onConfigChange(validateDocs);
3023
+ setup(connection3);
3024
+ onFileChange((changeDoc) => {
3025
+ if (changeDoc) {
3026
+ queueDiagnostic();
3027
+ getMarkoProject(getFSDir(changeDoc)).cache.delete(changeDoc);
3028
+ } else {
3029
+ validateDocs();
3030
+ }
2528
3031
  });
2529
- connection2.onCompletion(async (params, cancel) => {
3032
+ connection3.onCompletion(async (params, cancel) => {
2530
3033
  return await service.doComplete(
2531
- documents.get(params.textDocument.uri),
3034
+ get(params.textDocument.uri),
2532
3035
  params,
2533
3036
  cancel
2534
3037
  ) || null;
2535
3038
  });
2536
- connection2.onDefinition(async (params, cancel) => {
3039
+ connection3.onCompletionResolve(async (item, cancel) => {
3040
+ return await service.doCompletionResolve(item, cancel) || item;
3041
+ });
3042
+ connection3.onDefinition(async (params, cancel) => {
2537
3043
  return await service.findDefinition(
2538
- documents.get(params.textDocument.uri),
3044
+ get(params.textDocument.uri),
2539
3045
  params,
2540
3046
  cancel
2541
3047
  ) || null;
2542
3048
  });
2543
- connection2.onReferences(async (params, cancel) => {
3049
+ connection3.onReferences(async (params, cancel) => {
2544
3050
  return await service.findReferences(
2545
- documents.get(params.textDocument.uri),
3051
+ get(params.textDocument.uri),
2546
3052
  params,
2547
3053
  cancel
2548
3054
  ) || null;
2549
3055
  });
2550
- connection2.onDocumentLinks(async (params, cancel) => {
3056
+ connection3.onDocumentLinks(async (params, cancel) => {
2551
3057
  return await service.findDocumentLinks(
2552
- documents.get(params.textDocument.uri),
3058
+ get(params.textDocument.uri),
2553
3059
  params,
2554
3060
  cancel
2555
3061
  ) || null;
2556
3062
  });
2557
- connection2.onDocumentSymbol(async (params, cancel) => {
3063
+ connection3.onDocumentSymbol(async (params, cancel) => {
2558
3064
  return await service.findDocumentSymbols(
2559
- documents.get(params.textDocument.uri),
3065
+ get(params.textDocument.uri),
2560
3066
  params,
2561
3067
  cancel
2562
3068
  ) || null;
2563
3069
  });
2564
- connection2.onDocumentHighlight(async (params, cancel) => {
3070
+ connection3.onDocumentHighlight(async (params, cancel) => {
2565
3071
  return await service.findDocumentHighlights(
2566
- documents.get(params.textDocument.uri),
3072
+ get(params.textDocument.uri),
2567
3073
  params,
2568
3074
  cancel
2569
3075
  ) || null;
2570
3076
  });
2571
- connection2.onDocumentColor(async (params, cancel) => {
3077
+ connection3.onDocumentColor(async (params, cancel) => {
2572
3078
  return await service.findDocumentColors(
2573
- documents.get(params.textDocument.uri),
3079
+ get(params.textDocument.uri),
2574
3080
  params,
2575
3081
  cancel
2576
3082
  ) || null;
2577
3083
  });
2578
- connection2.onColorPresentation(async (params, cancel) => {
3084
+ connection3.onColorPresentation(async (params, cancel) => {
2579
3085
  return await service.getColorPresentations(
2580
- documents.get(params.textDocument.uri),
3086
+ get(params.textDocument.uri),
2581
3087
  params,
2582
3088
  cancel
2583
3089
  ) || null;
2584
3090
  });
2585
- connection2.onHover(async (params, cancel) => {
3091
+ connection3.onHover(async (params, cancel) => {
2586
3092
  return await service.doHover(
2587
- documents.get(params.textDocument.uri),
3093
+ get(params.textDocument.uri),
2588
3094
  params,
2589
3095
  cancel
2590
3096
  ) || null;
2591
3097
  });
2592
- connection2.onRenameRequest(async (params, cancel) => {
3098
+ connection3.onRenameRequest(async (params, cancel) => {
2593
3099
  return await service.doRename(
2594
- documents.get(params.textDocument.uri),
3100
+ get(params.textDocument.uri),
2595
3101
  params,
2596
3102
  cancel
2597
3103
  ) || null;
2598
3104
  });
2599
- connection2.onCodeAction(async (params, cancel) => {
3105
+ connection3.onCodeAction(async (params, cancel) => {
2600
3106
  return await service.doCodeActions(
2601
- documents.get(params.textDocument.uri),
3107
+ get(params.textDocument.uri),
2602
3108
  params,
2603
3109
  cancel
2604
3110
  ) || null;
2605
3111
  });
2606
- connection2.onDocumentFormatting(async (params, cancel) => {
3112
+ connection3.onDocumentFormatting(async (params, cancel) => {
2607
3113
  return await service.format(
2608
- documents.get(params.textDocument.uri),
3114
+ get(params.textDocument.uri),
2609
3115
  params,
2610
3116
  cancel
2611
3117
  ) || null;
2612
3118
  });
3119
+ for (const command in service.commands) {
3120
+ connection3.onRequest(command, service.commands[command]);
3121
+ }
2613
3122
  function validateDocs() {
2614
3123
  queueDiagnostic();
2615
- clearCompilerCache();
2616
- for (const doc of documents.all()) {
2617
- pendingDiags.add(doc);
3124
+ for (const project of getMarkoProjects()) {
3125
+ project.cache.clear();
3126
+ project.compiler.taglib.clearCaches();
2618
3127
  }
2619
3128
  }
2620
3129
  function queueDiagnostic() {
2621
3130
  clearTimeout(diagnosticTimeout);
2622
3131
  const id = diagnosticTimeout = setTimeout(async () => {
2623
3132
  const results = await Promise.all(
2624
- documents.all().map(async (doc) => {
2625
- if (!pendingDiags.delete(doc))
3133
+ Array.from(getAllOpen()).map(async (doc) => {
3134
+ if (!isOpen(doc)) {
3135
+ prevDiags.delete(doc);
2626
3136
  return;
3137
+ }
2627
3138
  const prevDiag = prevDiags.get(doc) || [];
2628
3139
  const nextDiag = await service.doValidate(doc) || [];
2629
3140
  if (isDeepStrictEqual(prevDiag, nextDiag))
@@ -2636,7 +3147,7 @@ function queueDiagnostic() {
2636
3147
  if (result) {
2637
3148
  const [doc, diag] = result;
2638
3149
  prevDiags.set(doc, diag);
2639
- connection2.sendDiagnostics({
3150
+ connection3.sendDiagnostics({
2640
3151
  uri: doc.uri,
2641
3152
  diagnostics: diag
2642
3153
  });
@@ -2645,6 +3156,5 @@ function queueDiagnostic() {
2645
3156
  }
2646
3157
  }, 400);
2647
3158
  }
2648
- documents.listen(connection2);
2649
- connection2.listen();
3159
+ connection3.listen();
2650
3160
  //# sourceMappingURL=index.mjs.map