@marko/language-server 0.12.2 → 0.12.5

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 +1322 -555
  2. package/dist/index.js.map +3 -3
  3. package/dist/index.mjs +1350 -605
  4. package/dist/index.mjs.map +3 -3
  5. package/dist/service/index.d.ts +6 -0
  6. package/dist/service/marko/complete/AttrName.d.ts +3 -0
  7. package/dist/service/marko/complete/OpenTagName.d.ts +3 -0
  8. package/dist/service/marko/complete/Tag.d.ts +6 -0
  9. package/dist/service/marko/complete/index.d.ts +14 -0
  10. package/dist/service/marko/definition/AttrName.d.ts +3 -0
  11. package/dist/service/marko/definition/OpenTagName.d.ts +3 -0
  12. package/dist/service/marko/definition/index.d.ts +14 -0
  13. package/dist/service/marko/format.d.ts +2 -0
  14. package/dist/service/marko/index.d.ts +3 -0
  15. package/dist/service/marko/validate.d.ts +2 -0
  16. package/dist/service/stylesheet/extract.d.ts +10 -0
  17. package/dist/service/stylesheet/index.d.ts +3 -0
  18. package/dist/service/types.d.ts +12 -0
  19. package/dist/utils/compiler.d.ts +16 -4
  20. package/dist/utils/doc-file.d.ts +3 -0
  21. package/dist/utils/extractor.d.ts +12 -0
  22. package/dist/utils/get-node-at-offset.d.ts +2 -0
  23. package/dist/utils/messages.d.ts +5 -0
  24. package/dist/utils/parser.d.ts +176 -0
  25. package/dist/utils/utils.d.ts +1 -8
  26. package/package.json +15 -14
  27. package/LICENSE +0 -20
  28. package/dist/utils/completions/index.d.ts +0 -6
  29. package/dist/utils/completions/types/attributeModifier.d.ts +0 -5
  30. package/dist/utils/completions/types/attributeName.d.ts +0 -5
  31. package/dist/utils/completions/types/closeTag.d.ts +0 -5
  32. package/dist/utils/completions/types/openTag.d.ts +0 -5
  33. package/dist/utils/completions/types/openTagName.d.ts +0 -5
  34. package/dist/utils/completions/types/styleContent.d.ts +0 -5
  35. package/dist/utils/definitions/index.d.ts +0 -2
  36. package/dist/utils/definitions/types/attributeName.d.ts +0 -5
  37. package/dist/utils/definitions/types/openTagName.d.ts +0 -5
  38. package/dist/utils/htmljs-parser.d.ts +0 -128
package/dist/index.js CHANGED
@@ -1,27 +1,10 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
- var __spreadValues = (a, b) => {
11
- for (var prop in b || (b = {}))
12
- if (__hasOwnProp.call(b, prop))
13
- __defNormalProp(a, prop, b[prop]);
14
- if (__getOwnPropSymbols)
15
- for (var prop of __getOwnPropSymbols(b)) {
16
- if (__propIsEnum.call(b, prop))
17
- __defNormalProp(a, prop, b[prop]);
18
- }
19
- return a;
20
- };
21
- var __export = (target, all) => {
22
- for (var name in all)
23
- __defProp(target, name, { get: all[name], enumerable: true });
24
- };
25
8
  var __copyProps = (to, from, except, desc) => {
26
9
  if (from && typeof from === "object" || typeof from === "function") {
27
10
  for (let key of __getOwnPropNames(from))
@@ -34,315 +17,780 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
17
 
35
18
  // src/index.ts
36
19
  var import_node = require("vscode-languageserver/node");
37
- var import_vscode_uri6 = require("vscode-uri");
38
20
  var import_vscode_languageserver_textdocument3 = require("vscode-languageserver-textdocument");
39
- var prettier = __toESM(require("prettier"));
40
- var markoPrettier = __toESM(require("prettier-plugin-marko"));
41
- var import_util = require("util");
21
+ var import_util2 = require("util");
42
22
 
43
23
  // src/utils/compiler.ts
44
- var import_path = __toESM(require("path"));
45
- var import_vscode_uri = require("vscode-uri");
24
+ var import_vscode_uri2 = require("vscode-uri");
46
25
  var import_resolve_from = __toESM(require("resolve-from"));
47
26
  var import_lasso_package_root = __toESM(require("lasso-package-root"));
48
27
  var builtinCompiler = __toESM(require("@marko/compiler"));
49
28
  var builtinTranslator = __toESM(require("@marko/translator-default"));
50
- builtinCompiler.configure({ translator: builtinTranslator });
51
- var compilerAndTranslatorForDoc = /* @__PURE__ */ new WeakMap();
52
- function getCompilerAndTranslatorForDoc(doc) {
53
- let compilerAndTranslator = compilerAndTranslatorForDoc.get(doc);
54
- if (!compilerAndTranslator) {
55
- compilerAndTranslatorForDoc.set(doc, compilerAndTranslator = loadCompiler(import_path.default.dirname(import_vscode_uri.URI.parse(doc.uri).fsPath)));
29
+
30
+ // src/utils/doc-file.ts
31
+ var import_path = __toESM(require("path"));
32
+ var import_vscode_uri = require("vscode-uri");
33
+ function getDocDir(doc) {
34
+ const filename = getDocFile(doc);
35
+ return filename ? import_path.default.dirname(filename) : void 0;
36
+ }
37
+ function getDocFile(doc) {
38
+ return import_vscode_uri.URI.parse(doc.uri).fsPath;
39
+ }
40
+
41
+ // src/utils/parser.ts
42
+ var import_htmljs_parser = require("htmljs-parser");
43
+
44
+ // src/utils/get-node-at-offset.ts
45
+ function getNodeAtOffset(offset, program) {
46
+ const bodyNode = childAtOffset(offset, program.body);
47
+ if (bodyNode)
48
+ return visitChildNode(offset, bodyNode);
49
+ return childAtOffset(offset, program.static) || program;
50
+ }
51
+ function visitChildNode(offset, child) {
52
+ switch (child.type) {
53
+ case 1 /* Tag */:
54
+ case 14 /* AttrTag */:
55
+ return visitTag(offset, child);
56
+ default:
57
+ return child;
56
58
  }
57
- return compilerAndTranslator;
58
59
  }
59
- function getTagLibLookup(document) {
60
- try {
61
- const { compiler, translator } = getCompilerAndTranslatorForDoc(document);
62
- return compiler.taglib.buildLookup(import_vscode_uri.URI.parse(document.uri).fsPath, translator);
63
- } catch {
60
+ function visitTag(offset, tag) {
61
+ const { body } = tag;
62
+ if (body && offset > tag.open.end) {
63
+ const childNode = childAtOffset(offset, body);
64
+ return childNode ? visitChildNode(offset, childNode) : tag;
65
+ }
66
+ const { attrs } = tag;
67
+ if (attrs && offset > attrs[0].start) {
68
+ const attrNode = childAtOffset(offset, attrs);
69
+ return attrNode ? visitAttrNode(offset, attrNode) : tag;
70
+ }
71
+ const { var: tagVar } = tag;
72
+ if (tagVar && offset > tagVar.start && offset <= tagVar.end) {
73
+ return tagVar;
74
+ }
75
+ const { args } = tag;
76
+ if (args && offset > args.start && offset <= args.end) {
77
+ return args;
64
78
  }
79
+ const { params } = tag;
80
+ if (params && offset > params.start && offset <= params.end) {
81
+ return params;
82
+ }
83
+ const { name } = tag;
84
+ if (name && offset <= name.end) {
85
+ return name;
86
+ }
87
+ return tag;
65
88
  }
66
- function loadCompiler(dir) {
67
- const rootDir = import_lasso_package_root.default.getRootDir(dir);
68
- const pkgPath = rootDir && import_resolve_from.default.silent(rootDir, "@marko/compiler/package.json");
69
- const pkg = pkgPath && require(pkgPath);
70
- if (pkg && /^5\./.test(pkg.version)) {
71
- try {
72
- let translator = [].concat(Object.keys(pkg.dependencies), Object.keys(pkg.peerDependencies), Object.keys(pkg.devDependencies)).find((name) => /^marko$|^(@\/marko\/|marko-)translator-/.test(name));
73
- if (translator === "marko" || !translator) {
74
- translator = require((0, import_resolve_from.default)(dir, "@marko/compiler/config")).translator;
89
+ function visitAttrNode(offset, attr) {
90
+ switch (attr.type) {
91
+ case 14 /* AttrTag */:
92
+ return visitTag(offset, attr);
93
+ case 8 /* AttrNamed */: {
94
+ const { value } = attr;
95
+ if (value && offset > value.start) {
96
+ return value;
75
97
  }
76
- require((0, import_resolve_from.default)(dir, translator));
77
- return {
78
- compiler: require((0, import_resolve_from.default)(dir, "@marko/compiler")),
79
- translator
80
- };
81
- } catch {
98
+ const { name } = attr;
99
+ if (offset > name.start && offset <= name.end) {
100
+ return name;
101
+ }
102
+ break;
82
103
  }
83
104
  }
84
- return {
85
- compiler: builtinCompiler,
86
- translator: builtinTranslator
87
- };
105
+ return attr;
106
+ }
107
+ function childAtOffset(offset, children) {
108
+ let max = children.length - 1;
109
+ if (max === -1)
110
+ return void 0;
111
+ let min = 0;
112
+ while (min < max) {
113
+ const mid = 1 + min + max >>> 1;
114
+ if (children[mid].start < offset) {
115
+ min = mid;
116
+ } else {
117
+ max = mid - 1;
118
+ }
119
+ }
120
+ const child = children[min];
121
+ return offset > child.start && offset <= child.end ? child : void 0;
88
122
  }
89
123
 
90
- // src/utils/htmljs-parser.ts
91
- var import_htmljs_parser = require("htmljs-parser");
92
- var SUPPORTED_STYLE_LANGS = {
93
- css: true,
94
- scss: true,
95
- less: true
96
- };
97
- function parseUntilOffset(options) {
98
- const { offset, text, taglib, includeErrors } = options;
99
- let result = null;
100
- let parentTag = null;
124
+ // src/utils/parser.ts
125
+ var UNFINISHED = Number.MAX_SAFE_INTEGER;
126
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
127
+ NodeType2[NodeType2["Program"] = 0] = "Program";
128
+ NodeType2[NodeType2["Tag"] = 1] = "Tag";
129
+ NodeType2[NodeType2["OpenTagName"] = 2] = "OpenTagName";
130
+ NodeType2[NodeType2["ShorthandId"] = 3] = "ShorthandId";
131
+ NodeType2[NodeType2["ShorthandClassName"] = 4] = "ShorthandClassName";
132
+ NodeType2[NodeType2["TagVar"] = 5] = "TagVar";
133
+ NodeType2[NodeType2["TagArgs"] = 6] = "TagArgs";
134
+ NodeType2[NodeType2["TagParams"] = 7] = "TagParams";
135
+ NodeType2[NodeType2["AttrNamed"] = 8] = "AttrNamed";
136
+ NodeType2[NodeType2["AttrName"] = 9] = "AttrName";
137
+ NodeType2[NodeType2["AttrArgs"] = 10] = "AttrArgs";
138
+ NodeType2[NodeType2["AttrValue"] = 11] = "AttrValue";
139
+ NodeType2[NodeType2["AttrMethod"] = 12] = "AttrMethod";
140
+ NodeType2[NodeType2["AttrSpread"] = 13] = "AttrSpread";
141
+ NodeType2[NodeType2["AttrTag"] = 14] = "AttrTag";
142
+ NodeType2[NodeType2["Text"] = 15] = "Text";
143
+ NodeType2[NodeType2["CDATA"] = 16] = "CDATA";
144
+ NodeType2[NodeType2["Doctype"] = 17] = "Doctype";
145
+ NodeType2[NodeType2["Declaration"] = 18] = "Declaration";
146
+ NodeType2[NodeType2["Comment"] = 19] = "Comment";
147
+ NodeType2[NodeType2["Statement"] = 20] = "Statement";
148
+ NodeType2[NodeType2["Placeholder"] = 21] = "Placeholder";
149
+ NodeType2[NodeType2["Scriptlet"] = 22] = "Scriptlet";
150
+ return NodeType2;
151
+ })(NodeType || {});
152
+ function parse(source) {
153
+ const program = {
154
+ type: 0 /* Program */,
155
+ parent: void 0,
156
+ static: [],
157
+ body: [],
158
+ start: 0,
159
+ end: source.length
160
+ };
161
+ let curBodyType;
162
+ let curOpenTagStart;
163
+ let curParent = program;
164
+ let curAttr = void 0;
165
+ let curBody = program.body;
101
166
  const parser = (0, import_htmljs_parser.createParser)({
102
- onError: includeErrors && finish,
103
- onScriptlet: finish,
104
- onPlaceholder: finish,
105
- onOpenTagName(ev) {
106
- if (parentTag) {
107
- ev.parent = parentTag;
108
- }
109
- if (!ev.concise) {
110
- ev.pos += 1;
111
- }
112
- ev.endPos = ev.pos + ev.tagName.length;
113
- parentTag = ev;
114
- finish(ev);
167
+ onText(range) {
168
+ curBody.push({
169
+ type: 15 /* Text */,
170
+ parent: curParent,
171
+ start: range.start,
172
+ end: range.end
173
+ });
115
174
  },
116
- onOpenTag(ev) {
117
- ev.parent = parentTag.parent;
118
- parentTag = ev;
119
- if (ev.tagName === "style") {
120
- const firstAttr = ev.attributes[0];
121
- const isBlock = firstAttr && firstAttr.name.startsWith("{");
122
- if (isBlock) {
123
- const content = firstAttr.name.slice(1, -1);
124
- const pos = text.indexOf(content, ev.tagNameEndPos);
125
- const endPos = pos + content.length;
126
- const requestedLanguage = ev.shorthandClassNames && ev.shorthandClassNames[0].rawParts[0] && ev.shorthandClassNames[0].rawParts[0].text;
127
- const language = requestedLanguage && SUPPORTED_STYLE_LANGS[requestedLanguage] ? requestedLanguage : "css";
128
- finish({
129
- type: "styleContent",
130
- language,
131
- block: true,
132
- content: text.slice(pos, endPos),
133
- pos,
134
- endPos
135
- });
136
- return;
137
- }
175
+ onCDATA(range) {
176
+ curBody.push({
177
+ type: 16 /* CDATA */,
178
+ parent: curParent,
179
+ value: range.value,
180
+ start: range.start,
181
+ end: range.end
182
+ });
183
+ },
184
+ onDoctype(range) {
185
+ curBody.push({
186
+ type: 17 /* Doctype */,
187
+ parent: curParent,
188
+ value: range.value,
189
+ start: range.start,
190
+ end: range.end
191
+ });
192
+ },
193
+ onDeclaration(range) {
194
+ curBody.push({
195
+ type: 18 /* Declaration */,
196
+ parent: curParent,
197
+ value: range.value,
198
+ start: range.start,
199
+ end: range.end
200
+ });
201
+ },
202
+ onComment(range) {
203
+ curBody.push({
204
+ type: 19 /* Comment */,
205
+ parent: curParent,
206
+ value: range.value,
207
+ start: range.start,
208
+ end: range.end
209
+ });
210
+ },
211
+ onPlaceholder(range) {
212
+ curBody.push({
213
+ type: 21 /* Placeholder */,
214
+ parent: curParent,
215
+ value: range.value,
216
+ escape: range.escape,
217
+ start: range.start,
218
+ end: range.end
219
+ });
220
+ },
221
+ onScriptlet(range) {
222
+ curBody.push({
223
+ type: 22 /* Scriptlet */,
224
+ parent: curParent,
225
+ value: range.value,
226
+ block: range.block,
227
+ start: range.start,
228
+ end: range.end
229
+ });
230
+ },
231
+ onOpenTagStart(range) {
232
+ curOpenTagStart = range;
233
+ },
234
+ onOpenTagName(range) {
235
+ let concise = true;
236
+ let start = range.start;
237
+ let type = 1 /* Tag */;
238
+ let nameText = void 0;
239
+ if (curOpenTagStart) {
240
+ concise = false;
241
+ start = curOpenTagStart.start;
242
+ curOpenTagStart = void 0;
138
243
  }
139
- let attrEndPos = ev.tagNameEndPos;
140
- for (const attr of ev.attributes) {
141
- if (!attr.name) {
142
- if (attr.value !== void 0) {
143
- attrEndPos += attr.value.length;
144
- }
145
- continue;
146
- }
147
- if (attr.name.slice(0, 3) === "...") {
148
- attrEndPos = attr.argument ? attr.argument.endPos + 1 : attr.endPos;
149
- continue;
150
- }
151
- const attrStartPos = text.indexOf(attr.name, attrEndPos);
152
- const match = /:(.*)$/.exec(attr.name);
153
- const modifier = match && match[1];
154
- let name = attr.name;
155
- if (modifier) {
156
- name = name.slice(0, name.length - modifier.length - 1);
157
- const modifierStartPos = attrStartPos + name.length;
158
- const modifierEndPos = modifierStartPos + modifier.length + 1;
159
- if (finish({
160
- type: "attributeModifier",
161
- tag: ev,
162
- name,
163
- modifier,
164
- pos: modifierStartPos,
165
- endPos: modifierEndPos
166
- })) {
167
- return;
168
- }
169
- }
170
- const attrNameEndPos = attrStartPos + name.length;
171
- if (finish({
172
- type: "attributeName",
173
- tag: ev,
174
- name,
175
- pos: attrStartPos,
176
- endPos: attrNameEndPos
177
- })) {
178
- return;
179
- }
180
- if (attr.value) {
181
- attrEndPos = attr.endPos;
182
- const valueStartPos = attr.pos + 1;
183
- if (finish({
184
- type: "attributeValue",
185
- tag: ev,
186
- name,
187
- value: text.slice(valueStartPos, attrEndPos),
188
- pos: valueStartPos,
189
- endPos: attr.endPos
190
- })) {
244
+ if (range.expressions.length) {
245
+ curBodyType = import_htmljs_parser.TagType.html;
246
+ } else {
247
+ switch (nameText = parser.read(range)) {
248
+ case "area":
249
+ case "base":
250
+ case "br":
251
+ case "col":
252
+ case "embed":
253
+ case "hr":
254
+ case "img":
255
+ case "input":
256
+ case "link":
257
+ case "meta":
258
+ case "param":
259
+ case "source":
260
+ case "track":
261
+ case "wbr":
262
+ curBodyType = import_htmljs_parser.TagType.void;
191
263
  break;
264
+ case "html-comment":
265
+ case "script":
266
+ case "style":
267
+ case "textarea":
268
+ curBodyType = import_htmljs_parser.TagType.text;
269
+ break;
270
+ case "class":
271
+ case "export":
272
+ case "import":
273
+ case "static": {
274
+ let i = program.body.length;
275
+ for (; i--; ) {
276
+ const prev = program.body[i];
277
+ if (prev.type === 19 /* Comment */) {
278
+ program.static.push(prev);
279
+ } else {
280
+ break;
281
+ }
282
+ }
283
+ program.body.length = i + 1;
284
+ program.static.push(curParent = {
285
+ type: 20 /* Statement */,
286
+ parent: program,
287
+ start: range.start,
288
+ end: UNFINISHED
289
+ });
290
+ return curBodyType = import_htmljs_parser.TagType.statement;
192
291
  }
193
- } else {
194
- attrEndPos = attr.argument ? attr.argument.endPos + 1 : attr.endPos;
292
+ default:
293
+ if (nameText[0] === "@") {
294
+ type = 14 /* AttrTag */;
295
+ }
296
+ curBodyType = import_htmljs_parser.TagType.html;
297
+ break;
195
298
  }
196
299
  }
197
- finish(ev);
300
+ const parent = curParent;
301
+ const end = UNFINISHED;
302
+ const name = {
303
+ type: 2 /* OpenTagName */,
304
+ parent: void 0,
305
+ quasis: range.quasis,
306
+ expressions: range.expressions,
307
+ start: range.start,
308
+ end: range.end
309
+ };
310
+ const tag = curParent = name.parent = {
311
+ type,
312
+ parent,
313
+ owner: void 0,
314
+ concise,
315
+ open: { start, end },
316
+ nameText,
317
+ name,
318
+ var: void 0,
319
+ args: void 0,
320
+ params: void 0,
321
+ shorthandId: void 0,
322
+ shorthandClassNames: void 0,
323
+ attrs: void 0,
324
+ selfClosed: false,
325
+ bodyType: curBodyType,
326
+ body: void 0,
327
+ close: void 0,
328
+ start,
329
+ end
330
+ };
331
+ if (tag.type === 14 /* AttrTag */) {
332
+ let owner = parent;
333
+ outer:
334
+ do {
335
+ switch (owner.type) {
336
+ case 14 /* AttrTag */:
337
+ break;
338
+ case 1 /* Tag */:
339
+ if (isTransparentTag(owner)) {
340
+ owner = owner.parent;
341
+ continue outer;
342
+ }
343
+ break;
344
+ default:
345
+ break outer;
346
+ }
347
+ tag.owner = owner;
348
+ tag.nameText = resolveAttrTagName(tag);
349
+ pushAttr(owner, tag);
350
+ } while (false);
351
+ }
352
+ curBody.push(tag);
353
+ curOpenTagStart = void 0;
354
+ return curBodyType;
198
355
  },
199
- onText(ev) {
200
- ev.endPos = parser.pos;
201
- ev.pos = ev.endPos - ev.value.length;
202
- if (parentTag) {
203
- ev.parent = parentTag;
204
- if (parentTag.tagName === "style") {
205
- finish({
206
- type: "styleContent",
207
- language: "css",
208
- block: false,
209
- content: ev.value,
210
- pos: ev.pos,
211
- endPos: ev.endPos
212
- });
213
- return;
356
+ onTagShorthandId(range) {
357
+ curParent.shorthandId = {
358
+ type: 3 /* ShorthandId */,
359
+ parent: curParent,
360
+ quasis: range.quasis,
361
+ expressions: range.expressions,
362
+ start: range.start,
363
+ end: range.end
364
+ };
365
+ },
366
+ onTagShorthandClass(range) {
367
+ const shorthandClassName = {
368
+ type: 4 /* ShorthandClassName */,
369
+ parent: curParent,
370
+ quasis: range.quasis,
371
+ expressions: range.expressions,
372
+ start: range.start,
373
+ end: range.end
374
+ };
375
+ if (curParent.shorthandClassNames) {
376
+ curParent.shorthandClassNames.push(shorthandClassName);
377
+ } else {
378
+ curParent.shorthandClassNames = [shorthandClassName];
379
+ }
380
+ },
381
+ onTagVar(range) {
382
+ curParent.var = {
383
+ type: 5 /* TagVar */,
384
+ parent: curParent,
385
+ value: range.value,
386
+ start: range.start,
387
+ end: range.end
388
+ };
389
+ },
390
+ onTagParams(range) {
391
+ curParent.params = {
392
+ type: 7 /* TagParams */,
393
+ parent: curParent,
394
+ value: range.value,
395
+ start: range.start,
396
+ end: range.end
397
+ };
398
+ },
399
+ onTagArgs(range) {
400
+ curParent.args = {
401
+ type: 6 /* TagArgs */,
402
+ parent: curParent,
403
+ value: range.value,
404
+ start: range.start,
405
+ end: range.end
406
+ };
407
+ },
408
+ onAttrName(range) {
409
+ const parent = curParent;
410
+ const name = {
411
+ type: 9 /* AttrName */,
412
+ parent: void 0,
413
+ start: range.start,
414
+ end: range.end
415
+ };
416
+ pushAttr(parent, curAttr = name.parent = {
417
+ type: 8 /* AttrNamed */,
418
+ parent,
419
+ name,
420
+ value: void 0,
421
+ args: void 0,
422
+ start: range.start,
423
+ end: range.end
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 === import_htmljs_parser.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 === import_htmljs_parser.TagType.void) {
475
+ curParent = tag.parent;
476
+ tag.selfClosed = range.selfClosed;
477
+ tag.end = range.end;
478
+ } else {
479
+ curBody = tag.body = [];
214
480
  }
215
481
  }
216
- finish(ev);
217
482
  },
218
- onCloseTag(ev) {
219
- parentTag = parentTag && parentTag.parent;
220
- finish(ev);
221
- }
222
- }, {
223
- isOpenTagOnly(ev) {
224
- const tagDef = taglib.getTag(ev);
225
- return tagDef && tagDef.openTagOnly;
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;
226
494
  }
227
495
  });
228
- try {
229
- parser.parse(`${text}
230
- `);
231
- } catch (err) {
232
- return includeErrors ? {
233
- type: "error",
234
- code: "UNEXPECTED_TOKEN",
235
- message: err.message,
236
- pos: parser.pos,
237
- endPos: parser.pos
238
- } : null;
239
- }
240
- return result;
241
- function finish(event) {
242
- const { type, pos, endPos } = event;
243
- if (!result && (type === "error" || pos != null && pos <= offset && endPos != null && endPos >= offset)) {
244
- result = event;
245
- parser.end();
246
- return true;
247
- }
248
- return false;
249
- }
250
- }
251
-
252
- // src/utils/completions/index.ts
253
- var completions_exports = {};
254
- __export(completions_exports, {
255
- attributeModifier: () => attributeModifier,
256
- attributeName: () => attributeName,
257
- closeTag: () => closeTag,
258
- openTag: () => openTag,
259
- openTagName: () => openTagName,
260
- styleContent: () => styleContent
261
- });
262
-
263
- // src/utils/completions/types/attributeModifier.ts
264
- var import_vscode_languageserver = require("vscode-languageserver");
265
- function attributeModifier(_taglib, _document, _params, _event) {
266
- return import_vscode_languageserver.CompletionList.create([
267
- {
268
- label: "scoped",
269
- kind: import_vscode_languageserver.CompletionItemKind.Keyword,
270
- detail: "Use to prefix with a unique ID"
271
- },
272
- {
273
- label: "no-update",
274
- kind: import_vscode_languageserver.CompletionItemKind.Keyword,
275
- detail: "Use to skip future updates to this attribute"
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;
276
528
  }
277
- ], true);
529
+ } while (parentTag);
530
+ }
531
+ function isTransparentTag(node) {
532
+ return node.nameText !== void 0 && /^(?:if|else(?:-if)?|for|while)$/.test(node.nameText);
278
533
  }
279
534
 
280
- // src/utils/completions/types/attributeName.ts
281
- var import_vscode_languageserver3 = require("vscode-languageserver");
282
-
283
- // src/utils/utils.ts
284
- var import_fs = __toESM(require("fs"));
285
- var import_vscode_uri2 = require("vscode-uri");
286
- var import_vscode_languageserver2 = require("vscode-languageserver");
287
- var import_vscode_languageserver_textdocument = require("vscode-languageserver-textdocument");
288
- var START_OF_FILE = import_vscode_languageserver2.Range.create(import_vscode_languageserver2.Position.create(0, 0), import_vscode_languageserver2.Position.create(0, 0));
289
- function findNonControlFlowParent(tag) {
290
- let parent = tag.parent;
291
- while (parent) {
292
- if (!/^(?:else-)?if|else|for|while$/.test(parent.tagName)) {
293
- return parent;
294
- }
295
- parent = parent.parent;
535
+ // src/utils/compiler.ts
536
+ var lookupKey = Symbol("lookup");
537
+ var compilerInfoByDir = /* @__PURE__ */ new Map();
538
+ var builtinInfo = {
539
+ cache: /* @__PURE__ */ new Map(),
540
+ lookup: builtinCompiler.taglib.buildLookup(__dirname, builtinTranslator),
541
+ compiler: builtinCompiler,
542
+ translator: builtinTranslator
543
+ };
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));
296
551
  }
297
- return null;
298
- }
299
- function rangeFromEvent(document, event) {
300
- return import_vscode_languageserver2.Range.create(document.positionAt(event.pos), document.positionAt(event.endPos));
552
+ return parsed;
301
553
  }
302
- function createTextDocument(filename) {
303
- const uri = import_vscode_uri2.URI.file(filename).toString();
304
- const content = import_fs.default.readFileSync(filename, "utf-8");
305
- return import_vscode_languageserver_textdocument.TextDocument.create(uri, "plaintext", 0, content);
554
+ function getCompilerInfo(doc) {
555
+ const dir = getDocDir(doc);
556
+ if (!dir)
557
+ return builtinInfo;
558
+ let info = compilerInfoByDir.get(dir);
559
+ if (!info) {
560
+ info = loadCompilerInfo(dir);
561
+ compilerInfoByDir.set(dir, info);
562
+ }
563
+ return info;
306
564
  }
307
- function shiftCompletionRanges(list, offset) {
308
- list.items.forEach((item) => {
309
- if (item.additionalTextEdits) {
310
- item.additionalTextEdits.forEach((edit) => shiftRange(edit.range, offset));
565
+ function setup(connection3, documents2) {
566
+ connection3.onDidChangeWatchedFiles(() => {
567
+ clearAllCaches();
568
+ });
569
+ documents2.onDidChangeContent(({ document }) => {
570
+ if (document.version > 1) {
571
+ if (document.languageId === "marko") {
572
+ getCompilerInfo(document).cache.delete(document);
573
+ } else if (/[./\\]marko(?:-tag)?\.json$/.test(document.uri)) {
574
+ clearAllCaches();
575
+ }
311
576
  }
312
- if (item.textEdit) {
313
- shiftEdit(item.textEdit, offset);
577
+ });
578
+ documents2.onDidClose(({ document }) => {
579
+ if (document.languageId === "marko" && import_vscode_uri2.URI.parse(document.uri).scheme !== "file") {
580
+ getCompilerInfo(document).cache.delete(document);
314
581
  }
315
582
  });
316
- return list;
317
583
  }
318
- function shiftEdit(edit, offset) {
319
- if (import_vscode_languageserver2.TextEdit.is(edit)) {
320
- shiftRange(edit.range, offset);
321
- } else {
322
- shiftRange(edit.insert, offset);
323
- shiftRange(edit.replace, offset);
584
+ function clearAllCaches() {
585
+ for (const [, info] of compilerInfoByDir) {
586
+ info.cache.clear();
587
+ info.compiler.taglib.clearCaches();
324
588
  }
325
589
  }
326
- function shiftRange(range, offset) {
327
- if (range) {
328
- shiftPosition(range.start, offset);
329
- shiftPosition(range.end, offset);
590
+ function loadCompilerInfo(dir) {
591
+ const rootDir = import_lasso_package_root.default.getRootDir(dir);
592
+ const pkgPath = rootDir && import_resolve_from.default.silent(rootDir, "@marko/compiler/package.json");
593
+ const pkg = pkgPath && require(pkgPath);
594
+ const cache2 = /* @__PURE__ */ new Map();
595
+ let translator = builtinTranslator;
596
+ let compiler = builtinCompiler;
597
+ if (pkg && /^5\./.test(pkg.version)) {
598
+ try {
599
+ let checkTranslator = [].concat(Object.keys(pkg.dependencies), Object.keys(pkg.peerDependencies), Object.keys(pkg.devDependencies)).find((name) => /^marko$|^(@\/marko\/|marko-)translator-/.test(name));
600
+ if (checkTranslator === "marko" || !checkTranslator) {
601
+ checkTranslator = require((0, import_resolve_from.default)(dir, "@marko/compiler/config")).translator;
602
+ }
603
+ [compiler, translator] = [
604
+ require((0, import_resolve_from.default)(dir, "@marko/compiler")),
605
+ require((0, import_resolve_from.default)(dir, checkTranslator))
606
+ ];
607
+ } catch {
608
+ }
330
609
  }
610
+ return {
611
+ cache: cache2,
612
+ get lookup() {
613
+ let lookup = cache2.get(lookupKey);
614
+ if (lookup === void 0) {
615
+ try {
616
+ lookup = compiler.taglib.buildLookup(dir, translator);
617
+ } catch {
618
+ lookup = builtinInfo.lookup;
619
+ }
620
+ cache2.set(lookupKey, lookup);
621
+ }
622
+ return lookup;
623
+ },
624
+ compiler,
625
+ translator
626
+ };
627
+ }
628
+
629
+ // src/utils/messages.ts
630
+ var import_util = require("util");
631
+ var connection;
632
+ function setup2(_) {
633
+ connection = _;
331
634
  }
332
- function shiftPosition(pos, offset) {
333
- if (pos.line === 0) {
334
- pos.character += offset.character;
635
+ function displayError(data) {
636
+ display("showError", data);
637
+ }
638
+ function display(type, data) {
639
+ const msg = typeof data === "string" ? data : (0, import_util.inspect)(data, { colors: false });
640
+ setImmediate(() => connection.sendNotification(type, msg));
641
+ }
642
+
643
+ // src/service/index.ts
644
+ var import_vscode_languageserver11 = require("vscode-languageserver");
645
+
646
+ // src/service/marko/complete/index.ts
647
+ var import_vscode_languageserver4 = require("vscode-languageserver");
648
+
649
+ // src/service/marko/complete/Tag.ts
650
+ var import_vscode_languageserver = require("vscode-languageserver");
651
+ var partialCloseTagReg = /<\/(?:[^><]*>)?/iy;
652
+ function Tag(event) {
653
+ const { node } = event;
654
+ const isClosed = node.end !== UNFINISHED;
655
+ if (isClosed || node.concise)
656
+ return;
657
+ const { offset, parsed, code } = event;
658
+ const closingTagStr = `</${node.nameText}>`;
659
+ if (offset === node.open.end) {
660
+ return [
661
+ {
662
+ label: closingTagStr,
663
+ kind: import_vscode_languageserver.CompletionItemKind.Class,
664
+ insertTextFormat: import_vscode_languageserver.InsertTextFormat.Snippet,
665
+ insertText: `
666
+ $0
667
+ ${closingTagStr}`
668
+ }
669
+ ];
670
+ } else if (node.close && offset >= node.close.start) {
671
+ const start = node.close.start;
672
+ partialCloseTagReg.lastIndex = start;
673
+ const [{ length }] = partialCloseTagReg.exec(code);
674
+ const end = start + length;
675
+ return [
676
+ {
677
+ label: closingTagStr,
678
+ kind: import_vscode_languageserver.CompletionItemKind.Class,
679
+ insertTextFormat: import_vscode_languageserver.InsertTextFormat.Snippet,
680
+ textEdit: import_vscode_languageserver.TextEdit.replace(parsed.locationAt({
681
+ start,
682
+ end
683
+ }), closingTagStr)
684
+ }
685
+ ];
335
686
  }
336
- pos.line += offset.line;
337
- return pos;
338
687
  }
339
688
 
340
- // src/utils/completions/types/attributeName.ts
341
- function attributeName(taglib, document, _params, event) {
689
+ // src/service/marko/complete/OpenTagName.ts
690
+ var import_path2 = __toESM(require("path"));
691
+ var import_vscode_uri3 = require("vscode-uri");
692
+ var import_vscode_languageserver2 = require("vscode-languageserver");
693
+ function OpenTagName({
694
+ document,
695
+ lookup,
696
+ parsed,
697
+ node
698
+ }) {
699
+ const currentTemplateFilePath = getDocFile(document);
700
+ const tag = node.parent;
701
+ const tagNameLocation = parsed.locationAt(node);
702
+ let tags;
703
+ if (tag.type === 14 /* AttrTag */) {
704
+ let parentTag = tag.owner;
705
+ while ((parentTag == null ? void 0 : parentTag.type) === 14 /* AttrTag */)
706
+ parentTag = parentTag.owner;
707
+ const parentTagDef = parentTag && parentTag.nameText && lookup.getTag(parentTag.nameText);
708
+ tags = parentTagDef && parentTagDef.nestedTags && Object.values(parentTagDef.nestedTags) || [];
709
+ } else {
710
+ tags = lookup.getTagsSorted().filter((it) => !it.isNestedTag);
711
+ }
712
+ return tags.filter((it) => !it.deprecated).filter((it) => it.name !== "*").filter((it) => /^[^_]/.test(it.name) || !/\/node_modules\//.test(it.filePath)).map((it) => {
713
+ let label = it.isNestedTag ? `@${it.name}` : it.name;
714
+ const fileForTag = it.template || it.renderer || it.filePath;
715
+ const fileURIForTag = import_vscode_uri3.URI.file(fileForTag).toString();
716
+ const nodeModuleMatch = /\/node_modules\/((?:@[^/]+\/)?[^/]+)/.exec(fileForTag);
717
+ const nodeModuleName = nodeModuleMatch && nodeModuleMatch[1];
718
+ const isCoreTag = nodeModuleName === "marko";
719
+ const documentation = {
720
+ kind: import_vscode_languageserver2.MarkupKind.Markdown,
721
+ value: it.html ? `Built in [<${it.name}>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${it.name}) HTML tag.` : nodeModuleName ? isCoreTag ? `Core Marko [<${it.name}>](${fileURIForTag}) tag.` : `Custom Marko tag discovered from the ["${nodeModuleName}"](${fileURIForTag}) npm package.` : `Custom Marko tag discovered from:
722
+
723
+ [${currentTemplateFilePath ? import_path2.default.relative(currentTemplateFilePath, fileForTag) : currentTemplateFilePath}](${fileURIForTag})`
724
+ };
725
+ if (it.description) {
726
+ documentation.value += `
727
+
728
+ ${it.description}`;
729
+ }
730
+ const autocomplete = it.autocomplete && it.autocomplete[0];
731
+ if (autocomplete) {
732
+ if (autocomplete.displayText) {
733
+ label = autocomplete.displayText;
734
+ }
735
+ if (autocomplete.description) {
736
+ documentation.value += `
737
+
738
+ ${autocomplete.description}`;
739
+ }
740
+ if (autocomplete.descriptionMoreURL) {
741
+ documentation.value += `
742
+
743
+ [More Info](${autocomplete.descriptionMoreURL})`;
744
+ }
745
+ }
746
+ return {
747
+ label,
748
+ documentation,
749
+ kind: import_vscode_languageserver2.CompletionItemKind.Class,
750
+ insertTextFormat: import_vscode_languageserver2.InsertTextFormat.Snippet,
751
+ textEdit: import_vscode_languageserver2.TextEdit.replace(tagNameLocation, autocomplete && autocomplete.snippet || label)
752
+ };
753
+ });
754
+ }
755
+
756
+ // src/service/marko/complete/AttrName.ts
757
+ var import_vscode_languageserver3 = require("vscode-languageserver");
758
+ function AttrName({
759
+ offset,
760
+ node,
761
+ parsed,
762
+ lookup
763
+ }) {
764
+ let name = parsed.read(node);
765
+ if (name[0] === "{")
766
+ return;
767
+ const modifierIndex = name.indexOf(":");
768
+ const hasModifier = modifierIndex !== -1;
769
+ if (hasModifier) {
770
+ if (offset >= node.start + modifierIndex) {
771
+ return [
772
+ {
773
+ label: "scoped",
774
+ kind: import_vscode_languageserver3.CompletionItemKind.Keyword,
775
+ detail: "Use to prefix with a unique ID"
776
+ },
777
+ {
778
+ label: "no-update",
779
+ kind: import_vscode_languageserver3.CompletionItemKind.Keyword,
780
+ detail: "Use to skip future updates to this attribute"
781
+ }
782
+ ];
783
+ } else {
784
+ name = name.slice(0, modifierIndex);
785
+ }
786
+ }
342
787
  const completions = [];
343
- const attrNameRange = rangeFromEvent(document, event);
344
- const tagDef = !event.tag.tagNameExpression && taglib.getTag(event.tag.tagName);
345
- const tagName = tagDef && tagDef.name || "*";
788
+ const attrNameLoc = parsed.locationAt(hasModifier ? {
789
+ start: node.start,
790
+ end: node.start + name.length
791
+ } : node);
792
+ const tagName = node.parent.parent.nameText || "";
793
+ const tagDef = tagName && lookup.getTag(tagName);
346
794
  const nestedTagAttrs = {};
347
795
  const neverAttrs = /* @__PURE__ */ new Set();
348
796
  if (tagDef && tagDef.nestedTags) {
@@ -351,12 +799,12 @@ function attributeName(taglib, document, _params, event) {
351
799
  nestedTagAttrs[nestedTagDef.targetProperty] = true;
352
800
  }
353
801
  }
354
- taglib.forEachAttribute(tagName, (attr) => {
802
+ lookup.forEachAttribute(tagName, (attr) => {
355
803
  if (attr.type === "never") {
356
804
  neverAttrs.add(attr.name);
357
805
  }
358
806
  });
359
- taglib.forEachAttribute(tagName, (attr, parent) => {
807
+ lookup.forEachAttribute(tagName, (attr, parent) => {
360
808
  if (attr.deprecated || nestedTagAttrs[attr.name] || attr.name === "*" || neverAttrs.has(attr.name) || attr.name[0] === "_" && /\/node_modules\//.test(attr.filePath || parent.filePath)) {
361
809
  return;
362
810
  }
@@ -404,138 +852,64 @@ function attributeName(taglib, document, _params, event) {
404
852
  documentation: documentation.value ? documentation : void 0,
405
853
  kind: import_vscode_languageserver3.CompletionItemKind.Property,
406
854
  insertTextFormat: import_vscode_languageserver3.InsertTextFormat.Snippet,
407
- textEdit: import_vscode_languageserver3.TextEdit.replace(attrNameRange, snippet)
855
+ textEdit: import_vscode_languageserver3.TextEdit.replace(attrNameLoc, snippet)
408
856
  });
409
857
  });
410
- return import_vscode_languageserver3.CompletionList.create(completions, true);
858
+ return completions;
411
859
  }
412
860
 
413
- // src/utils/completions/types/closeTag.ts
414
- var import_vscode_languageserver4 = require("vscode-languageserver");
415
- function closeTag(_taglib, document, _params, event) {
416
- if (event.tagName[0] === "$") {
417
- return;
418
- }
419
- const closingTagStr = `</${event.tagName}>`;
420
- return import_vscode_languageserver4.CompletionList.create([
421
- {
422
- label: closingTagStr,
423
- kind: import_vscode_languageserver4.CompletionItemKind.Class,
424
- insertTextFormat: import_vscode_languageserver4.InsertTextFormat.Snippet,
425
- textEdit: import_vscode_languageserver4.TextEdit.replace(rangeFromEvent(document, event), closingTagStr)
426
- }
427
- ], true);
428
- }
861
+ // src/service/marko/complete/index.ts
862
+ var handlers = {
863
+ Tag,
864
+ OpenTagName,
865
+ AttrName
866
+ };
867
+ var doComplete = async (doc, params) => {
868
+ var _a;
869
+ const parsed = parse2(doc);
870
+ const offset = doc.offsetAt(params.position);
871
+ const node = parsed.nodeAt(offset);
872
+ return import_vscode_languageserver4.CompletionList.create(await ((_a = handlers[NodeType[node.type]]) == null ? void 0 : _a.call(handlers, {
873
+ document: doc,
874
+ params,
875
+ parsed,
876
+ offset,
877
+ node,
878
+ code: doc.getText(),
879
+ ...getCompilerInfo(doc)
880
+ })) || [], true);
881
+ };
429
882
 
430
- // src/utils/completions/types/openTag.ts
883
+ // src/service/marko/validate.ts
431
884
  var import_vscode_languageserver5 = require("vscode-languageserver");
432
- function openTag(_taglib, _document, params, event) {
433
- const triggerCharacter = params.context && params.context.triggerCharacter;
434
- if (triggerCharacter !== ">" || event.openTagOnly || event.selfClosed) {
435
- return;
436
- }
437
- const closingTagStr = `</${event.tagName[0] === "$" ? "" : event.tagName}>`;
438
- return import_vscode_languageserver5.CompletionList.create([
439
- {
440
- label: closingTagStr,
441
- kind: import_vscode_languageserver5.CompletionItemKind.Class,
442
- insertTextFormat: import_vscode_languageserver5.InsertTextFormat.Snippet,
443
- insertText: `
444
- $0
445
- ${closingTagStr}`
885
+ var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
886
+ var doValidate = (doc) => {
887
+ const fsPath = getDocFile(doc);
888
+ const diagnostics = [];
889
+ const { compiler, translator, cache: cache2 } = getCompilerInfo(doc);
890
+ try {
891
+ compiler.compileSync(doc.getText(), fsPath || "untitled.marko", {
892
+ cache: cache2,
893
+ output: "source",
894
+ code: false,
895
+ translator
896
+ });
897
+ } catch (e) {
898
+ let match;
899
+ while (match = markoErrorRegExp.exec(e.message)) {
900
+ const [, fileName, rawLine, rawCol, msg] = match;
901
+ const line = (parseInt(rawLine, 10) || 1) - 1;
902
+ const col = (parseInt(rawCol, 10) || 1) - 1;
903
+ diagnostics.push(import_vscode_languageserver5.Diagnostic.create(import_vscode_languageserver5.Range.create(line, col, line, col), msg, import_vscode_languageserver5.DiagnosticSeverity.Error, void 0, fileName));
446
904
  }
447
- ], true);
448
- }
449
-
450
- // src/utils/completions/types/openTagName.ts
451
- var import_path2 = __toESM(require("path"));
452
- var import_vscode_uri3 = require("vscode-uri");
453
- var import_vscode_languageserver6 = require("vscode-languageserver");
454
- function openTagName(taglib, document, params, event) {
455
- const { fsPath: currentTemplateFilePath } = import_vscode_uri3.URI.parse(document.uri);
456
- let tags;
457
- const triggerCharacter = params.context && params.context.triggerCharacter || event.tagName[0];
458
- const isAttributeTag = triggerCharacter === "@";
459
- const tagNameRange = rangeFromEvent(document, event);
460
- if (isAttributeTag) {
461
- const parentTag = findNonControlFlowParent(event);
462
- const parentTagDef = parentTag && !parentTag.tagNameExpression && taglib.getTag(parentTag.tagName);
463
- tags = parentTagDef && parentTagDef.nestedTags && Object.values(parentTagDef.nestedTags) || [];
464
- } else {
465
- tags = taglib.getTagsSorted().filter((it) => !it.isNestedTag);
466
905
  }
467
- return import_vscode_languageserver6.CompletionList.create(tags.filter((it) => !it.deprecated).filter((it) => it.name !== "*").filter((it) => /^[^_]/.test(it.name) || !/\/node_modules\//.test(it.filePath)).map((it) => {
468
- let label = it.isNestedTag ? `@${it.name}` : it.name;
469
- const fileForTag = it.template || it.renderer || it.filePath;
470
- const fileURIForTag = import_vscode_uri3.URI.file(fileForTag).toString();
471
- const nodeModuleMatch = /\/node_modules\/((?:@[^/]+\/)?[^/]+)/.exec(fileForTag);
472
- const nodeModuleName = nodeModuleMatch && nodeModuleMatch[1];
473
- const isCoreTag = nodeModuleName === "marko";
474
- const documentation = {
475
- kind: import_vscode_languageserver6.MarkupKind.Markdown,
476
- value: it.html ? `Built in [<${it.name}>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${it.name}) HTML tag.` : nodeModuleName ? isCoreTag ? `Core Marko [<${it.name}>](${fileURIForTag}) tag.` : `Custom Marko tag discovered from the ["${nodeModuleName}"](${fileURIForTag}) npm package.` : `Custom Marko tag discovered from:
477
-
478
- [${import_path2.default.relative(currentTemplateFilePath, fileForTag)}](${fileURIForTag})`
479
- };
480
- if (it.description) {
481
- documentation.value += `
482
-
483
- ${it.description}`;
484
- }
485
- const autocomplete = it.autocomplete && it.autocomplete[0];
486
- if (autocomplete) {
487
- if (autocomplete.displayText) {
488
- label = autocomplete.displayText;
489
- }
490
- if (autocomplete.description) {
491
- documentation.value += `
492
-
493
- ${autocomplete.description}`;
494
- }
495
- if (autocomplete.descriptionMoreURL) {
496
- documentation.value += `
497
-
498
- [More Info](${autocomplete.descriptionMoreURL})`;
499
- }
500
- }
501
- return {
502
- label,
503
- documentation,
504
- kind: import_vscode_languageserver6.CompletionItemKind.Class,
505
- insertTextFormat: import_vscode_languageserver6.InsertTextFormat.Snippet,
506
- textEdit: import_vscode_languageserver6.TextEdit.replace(tagNameRange, autocomplete && autocomplete.snippet || label)
507
- };
508
- }), true);
509
- }
510
-
511
- // src/utils/completions/types/styleContent.ts
512
- var import_vscode_languageserver7 = require("vscode-languageserver");
513
- var import_vscode_languageserver_textdocument2 = require("vscode-languageserver-textdocument");
514
- var import_vscode_css_languageservice = require("vscode-css-languageservice");
515
- var services = {
516
- css: import_vscode_css_languageservice.getCSSLanguageService,
517
- scss: import_vscode_css_languageservice.getSCSSLanguageService,
518
- less: import_vscode_css_languageservice.getLESSLanguageService
906
+ return diagnostics;
519
907
  };
520
- function styleContent(_taglib, document, params, event) {
521
- const service = services[event.language]();
522
- const startPos = document.positionAt(event.pos);
523
- const relativePos = shiftPosition(params.position, import_vscode_languageserver7.Position.create(startPos.line * -1, startPos.character * -1));
524
- const contentDocument = import_vscode_languageserver_textdocument2.TextDocument.create(document.uri, event.language, document.version, event.content);
525
- const completions = service.doComplete(contentDocument, relativePos, service.parseStylesheet(contentDocument));
526
- return shiftCompletionRanges(completions, startPos);
527
- }
528
-
529
- // src/utils/definitions/index.ts
530
- var definitions_exports = {};
531
- __export(definitions_exports, {
532
- attributeName: () => attributeName2,
533
- openTagName: () => openTagName2
534
- });
535
908
 
536
- // src/utils/definitions/types/attributeName.ts
537
- var import_vscode_uri4 = require("vscode-uri");
538
- var import_vscode_languageserver8 = require("vscode-languageserver");
909
+ // src/service/marko/definition/OpenTagName.ts
910
+ var import_path3 = __toESM(require("path"));
911
+ var import_vscode_uri5 = require("vscode-uri");
912
+ var import_vscode_languageserver7 = require("vscode-languageserver");
539
913
 
540
914
  // src/utils/regexp-builder.ts
541
915
  function RegExpBuilder(strings, ...expressions) {
@@ -561,11 +935,68 @@ function escape(val) {
561
935
  return String(val).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
562
936
  }
563
937
 
564
- // src/utils/definitions/types/attributeName.ts
565
- function attributeName2(taglib, document, _params, event) {
566
- const tagName = event.tag.tagNameExpression ? void 0 : event.tag.tagName;
567
- const tagDef = tagName && taglib.getTag(tagName);
568
- const attrDef = taglib.getAttribute(tagName || "*", event.name);
938
+ // src/utils/utils.ts
939
+ var import_fs = __toESM(require("fs"));
940
+ var import_vscode_uri4 = require("vscode-uri");
941
+ var import_vscode_languageserver6 = require("vscode-languageserver");
942
+ var import_vscode_languageserver_textdocument = require("vscode-languageserver-textdocument");
943
+ var START_OF_FILE = import_vscode_languageserver6.Range.create(import_vscode_languageserver6.Position.create(0, 0), import_vscode_languageserver6.Position.create(0, 0));
944
+ function createTextDocument(filename) {
945
+ const uri = import_vscode_uri4.URI.file(filename).toString();
946
+ const content = import_fs.default.readFileSync(filename, "utf-8");
947
+ return import_vscode_languageserver_textdocument.TextDocument.create(uri, "plaintext", 0, content);
948
+ }
949
+
950
+ // src/service/marko/definition/OpenTagName.ts
951
+ function OpenTagName2({
952
+ lookup,
953
+ parsed,
954
+ node
955
+ }) {
956
+ const tag = node.parent;
957
+ let tagDef;
958
+ let range = START_OF_FILE;
959
+ if (tag.type === 14 /* AttrTag */) {
960
+ let parentTag = tag.owner;
961
+ while ((parentTag == null ? void 0 : parentTag.type) === 14 /* AttrTag */)
962
+ parentTag = parentTag.owner;
963
+ tagDef = parentTag && parentTag.nameText ? lookup.getTag(parentTag.nameText) : void 0;
964
+ } else {
965
+ tagDef = tag.nameText ? lookup.getTag(tag.nameText) : void 0;
966
+ }
967
+ if (!tagDef) {
968
+ return;
969
+ }
970
+ const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
971
+ if (!import_path3.default.isAbsolute(tagEntryFile)) {
972
+ return;
973
+ }
974
+ if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
975
+ const tagDefDoc = createTextDocument(tagEntryFile);
976
+ const match = RegExpBuilder`/"(?:<${tag.nameText}>|${tag.nameText})"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
977
+ if (match && match.index) {
978
+ range = import_vscode_languageserver7.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
979
+ }
980
+ }
981
+ return [
982
+ import_vscode_languageserver7.LocationLink.create(import_vscode_uri5.URI.file(tagEntryFile).toString(), range, range, parsed.locationAt(node))
983
+ ];
984
+ }
985
+
986
+ // src/service/marko/definition/AttrName.ts
987
+ var import_vscode_uri6 = require("vscode-uri");
988
+ var import_vscode_languageserver8 = require("vscode-languageserver");
989
+ function AttrName2({
990
+ lookup,
991
+ parsed,
992
+ node
993
+ }) {
994
+ const tagName = node.parent.parent.nameText;
995
+ const attrName = parsed.read(node);
996
+ if (attrName[0] === "{")
997
+ return;
998
+ const tagDef = tagName && lookup.getTag(tagName);
999
+ const attrDef = lookup.getAttribute(tagName || "", attrName);
569
1000
  let range = START_OF_FILE;
570
1001
  if (!attrDef) {
571
1002
  return;
@@ -576,204 +1007,540 @@ function attributeName2(taglib, document, _params, event) {
576
1007
  }
577
1008
  if (/\/marko(?:-tag)?\.json$/.test(attrEntryFile)) {
578
1009
  const tagDefDoc = createTextDocument(attrEntryFile);
579
- const match = RegExpBuilder`/"@${event.name}"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
1010
+ const match = RegExpBuilder`/"@${attrName}"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
580
1011
  if (match && match.index) {
581
1012
  range = import_vscode_languageserver8.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
582
1013
  }
583
1014
  }
584
1015
  return [
585
- import_vscode_languageserver8.LocationLink.create(import_vscode_uri4.URI.file(attrEntryFile).toString(), range, range, rangeFromEvent(document, event))
1016
+ import_vscode_languageserver8.LocationLink.create(import_vscode_uri6.URI.file(attrEntryFile).toString(), range, range, parsed.locationAt(node))
586
1017
  ];
587
1018
  }
588
1019
 
589
- // src/utils/definitions/types/openTagName.ts
590
- var import_vscode_uri5 = require("vscode-uri");
1020
+ // src/service/marko/definition/index.ts
1021
+ var handlers2 = {
1022
+ OpenTagName: OpenTagName2,
1023
+ AttrName: AttrName2
1024
+ };
1025
+ var findDefinition = async (doc, params) => {
1026
+ var _a;
1027
+ const parsed = parse2(doc);
1028
+ const offset = doc.offsetAt(params.position);
1029
+ const node = parsed.nodeAt(offset);
1030
+ return await ((_a = handlers2[NodeType[node.type]]) == null ? void 0 : _a.call(handlers2, {
1031
+ document: doc,
1032
+ params,
1033
+ parsed,
1034
+ offset,
1035
+ node,
1036
+ code: doc.getText(),
1037
+ ...getCompilerInfo(doc)
1038
+ })) || [];
1039
+ };
1040
+
1041
+ // src/service/marko/format.ts
591
1042
  var import_vscode_languageserver9 = require("vscode-languageserver");
592
- function openTagName2(taglib, document, _params, event) {
593
- let tagDef;
594
- let range = START_OF_FILE;
595
- const isAttributeTag = event.tagName[0] === "@";
596
- if (isAttributeTag) {
597
- const parentTag = findNonControlFlowParent(event);
598
- tagDef = parentTag && (parentTag.tagNameExpression ? void 0 : taglib.getTag(parentTag.tagName));
599
- } else {
600
- tagDef = taglib.getTag(event.tagName);
1043
+ var import_vscode_uri7 = require("vscode-uri");
1044
+ var prettier = __toESM(require("prettier"));
1045
+ var markoPrettier = __toESM(require("prettier-plugin-marko"));
1046
+ var NO_EDIT = [
1047
+ import_vscode_languageserver9.TextEdit.replace(import_vscode_languageserver9.Range.create(import_vscode_languageserver9.Position.create(0, 0), import_vscode_languageserver9.Position.create(0, 0)), "")
1048
+ ];
1049
+ var format2 = async (doc, params, token) => {
1050
+ try {
1051
+ const { fsPath, scheme } = import_vscode_uri7.URI.parse(doc.uri);
1052
+ const text = doc.getText();
1053
+ const options = {
1054
+ parser: "marko",
1055
+ filepath: fsPath,
1056
+ plugins: [markoPrettier],
1057
+ tabWidth: params.options.tabSize,
1058
+ useTabs: params.options.insertSpaces === false,
1059
+ ...scheme === "file" ? await prettier.resolveConfig(fsPath, {
1060
+ editorconfig: true
1061
+ }).catch(() => null) : null
1062
+ };
1063
+ if (!token.isCancellationRequested) {
1064
+ return [
1065
+ import_vscode_languageserver9.TextEdit.replace(import_vscode_languageserver9.Range.create(doc.positionAt(0), doc.positionAt(text.length)), prettier.format(text, options))
1066
+ ];
1067
+ }
1068
+ } catch (e) {
1069
+ displayError(e);
601
1070
  }
602
- if (!tagDef) {
603
- return;
1071
+ return NO_EDIT;
1072
+ };
1073
+
1074
+ // src/service/marko/index.ts
1075
+ var marko_default = {
1076
+ doComplete,
1077
+ doValidate,
1078
+ findDefinition,
1079
+ format: format2
1080
+ };
1081
+
1082
+ // src/service/stylesheet/index.ts
1083
+ var import_vscode_languageserver10 = require("vscode-languageserver");
1084
+ var import_vscode_css_languageservice = require("vscode-css-languageservice");
1085
+ var import_vscode_languageserver_textdocument2 = require("vscode-languageserver-textdocument");
1086
+
1087
+ // src/utils/extractor.ts
1088
+ function createExtractor(code) {
1089
+ let generated = "";
1090
+ const generatedMap = [];
1091
+ return {
1092
+ write(strs, ...exprs) {
1093
+ const len = exprs.length;
1094
+ for (let i = 0; i < len; i++) {
1095
+ const expr = exprs[i];
1096
+ generated += strs[i];
1097
+ if (typeof expr === "string") {
1098
+ generated += expr;
1099
+ } else {
1100
+ generatedMap.push(generated.length, expr.start, expr.end);
1101
+ generated += code.slice(expr.start, expr.end);
1102
+ }
1103
+ }
1104
+ generated += strs[len];
1105
+ },
1106
+ end() {
1107
+ const sourceMap = generatedMap.slice();
1108
+ (function sort(left, right) {
1109
+ if (left < right) {
1110
+ let next = left;
1111
+ for (let i = left; i <= right; i += 3) {
1112
+ if (sourceMap[i] <= sourceMap[right]) {
1113
+ [sourceMap[next - 1], sourceMap[i - 1]] = [
1114
+ sourceMap[i - 1],
1115
+ sourceMap[next - 1]
1116
+ ];
1117
+ [sourceMap[next], sourceMap[i]] = [sourceMap[i], sourceMap[next]];
1118
+ [sourceMap[next + 1], sourceMap[i + 1]] = [
1119
+ sourceMap[i + 1],
1120
+ sourceMap[next + 1]
1121
+ ];
1122
+ next += 3;
1123
+ }
1124
+ }
1125
+ next -= 3;
1126
+ sort(left, next - 3);
1127
+ sort(next + 3, right);
1128
+ }
1129
+ })(1, sourceMap.length - 2);
1130
+ return {
1131
+ generated,
1132
+ sourceOffsetAt(generatedOffset) {
1133
+ let max = generatedMap.length / 3;
1134
+ let min = 0;
1135
+ while (min < max) {
1136
+ const mid = 1 + min + max >>> 1;
1137
+ if (generatedMap[mid * 3] <= generatedOffset) {
1138
+ min = mid;
1139
+ } else {
1140
+ max = mid - 1;
1141
+ }
1142
+ }
1143
+ const key = min * 3;
1144
+ const generatedStart = generatedMap[key];
1145
+ const sourceStart = generatedMap[key + 1];
1146
+ const sourceEnd = generatedMap[key + 2];
1147
+ return sourceEnd - sourceStart <= generatedOffset - generatedStart ? void 0 : sourceStart + (generatedOffset - generatedStart);
1148
+ },
1149
+ generatedOffsetAt(sourceOffset) {
1150
+ let max = sourceMap.length / 3;
1151
+ let min = 0;
1152
+ while (min < max) {
1153
+ const mid = 1 + min + max >>> 1;
1154
+ if (sourceMap[mid * 3 + 1] <= sourceOffset) {
1155
+ min = mid;
1156
+ } else {
1157
+ max = mid - 1;
1158
+ }
1159
+ }
1160
+ const key = min * 3;
1161
+ const sourceStart = sourceMap[key + 1];
1162
+ const sourceEnd = sourceMap[key + 2];
1163
+ if (sourceOffset < sourceStart || sourceOffset > sourceEnd)
1164
+ return void 0;
1165
+ const generatedStart = sourceMap[key];
1166
+ return generatedStart + (sourceOffset - sourceStart);
1167
+ }
1168
+ };
1169
+ }
1170
+ };
1171
+ }
1172
+
1173
+ // src/service/stylesheet/extract.ts
1174
+ function extractStyleSheets(code, program, lookup) {
1175
+ let placeholderId = 0;
1176
+ const extractorsByExt = {};
1177
+ const read = (range) => code.slice(range.start, range.end);
1178
+ const getExtractor = (ext) => extractorsByExt[ext] || (extractorsByExt[ext] = createExtractor(code));
1179
+ const getFileExtFromTag = (tag) => {
1180
+ const prefixEnd = tag.shorthandClassNames ? tag.shorthandClassNames.at(-1).end : tag.name.end;
1181
+ return tag.shorthandClassNames ? read({
1182
+ start: tag.shorthandClassNames[0].start,
1183
+ end: prefixEnd
1184
+ }).replace(/^.*\./, "") : "css";
1185
+ };
1186
+ const visit = (node) => {
1187
+ var _a, _b, _c;
1188
+ switch (node.type) {
1189
+ case 1 /* Tag */:
1190
+ if ((_a = node.body) == null ? void 0 : _a.length) {
1191
+ if (node.nameText === "style") {
1192
+ const ext = getFileExtFromTag(node);
1193
+ for (const child of node.body) {
1194
+ switch (child.type) {
1195
+ case 15 /* Text */:
1196
+ getExtractor(ext).write`${child}`;
1197
+ break;
1198
+ case 21 /* Placeholder */:
1199
+ getExtractor(ext).write`${`var(--_${placeholderId++})`}`;
1200
+ break;
1201
+ }
1202
+ }
1203
+ } else {
1204
+ if (node.attrs) {
1205
+ for (const attr of node.attrs) {
1206
+ if (attr.type === 8 /* AttrNamed */ && ((_b = attr.value) == null ? void 0 : _b.type) === 11 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])) {
1207
+ const name = read(attr.name);
1208
+ if (name === "#style" || name === "style" && lookup && node.nameText && name === "style" && ((_c = lookup.getTag(node.nameText)) == null ? void 0 : _c.html)) {
1209
+ getExtractor("css").write`:root{${{
1210
+ start: attr.value.value.start + 1,
1211
+ end: attr.value.value.end - 1
1212
+ }}}`;
1213
+ }
1214
+ }
1215
+ }
1216
+ }
1217
+ for (const child of node.body) {
1218
+ visit(child);
1219
+ }
1220
+ }
1221
+ } else if (node.nameText === "style" && node.concise && node.attrs) {
1222
+ const block = node.attrs.at(-1);
1223
+ if (block.type === 8 /* AttrNamed */ && code[block.start] === "{") {
1224
+ getExtractor(getFileExtFromTag(node)).write`${{
1225
+ start: block.start + 1,
1226
+ end: block.end - 1
1227
+ }}`;
1228
+ }
1229
+ }
1230
+ break;
1231
+ }
1232
+ };
1233
+ for (const node of program.body)
1234
+ visit(node);
1235
+ const resultsByExt = {};
1236
+ for (const ext in extractorsByExt) {
1237
+ resultsByExt[ext] = extractorsByExt[ext].end();
604
1238
  }
605
- const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
606
- if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
607
- const tagDefDoc = createTextDocument(tagEntryFile);
608
- const match = RegExpBuilder`/"<${event.tagName}>"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
609
- if (match && match.index) {
610
- range = import_vscode_languageserver9.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
1239
+ return resultsByExt;
1240
+ }
1241
+
1242
+ // src/service/stylesheet/index.ts
1243
+ var cache = /* @__PURE__ */ new WeakMap();
1244
+ var services = {
1245
+ css: import_vscode_css_languageservice.getCSSLanguageService,
1246
+ less: import_vscode_css_languageservice.getLESSLanguageService,
1247
+ scss: import_vscode_css_languageservice.getSCSSLanguageService
1248
+ };
1249
+ var stylesheet_default = {
1250
+ async doComplete(doc, params) {
1251
+ const infoByExt = getStyleSheetInfo(doc);
1252
+ const sourceOffset = doc.offsetAt(params.position);
1253
+ for (const ext in infoByExt) {
1254
+ const info = infoByExt[ext];
1255
+ const generatedOffset = info.generatedOffsetAt(sourceOffset);
1256
+ if (generatedOffset === void 0)
1257
+ continue;
1258
+ const { service: service2, virtualDoc } = info;
1259
+ const result = service2.doComplete(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed);
1260
+ for (const item of result.items) {
1261
+ if (item.additionalTextEdits) {
1262
+ for (const edit of item.additionalTextEdits) {
1263
+ if (!updateRange(doc, info, edit.range)) {
1264
+ edit.newText = "";
1265
+ edit.range = START_OF_FILE;
1266
+ }
1267
+ }
1268
+ }
1269
+ const { textEdit } = item;
1270
+ if (textEdit) {
1271
+ if (textEdit.range) {
1272
+ if (!updateRange(doc, info, textEdit.range)) {
1273
+ textEdit.newText = "";
1274
+ textEdit.range = START_OF_FILE;
1275
+ }
1276
+ }
1277
+ if (textEdit.insert) {
1278
+ if (!updateRange(doc, info, textEdit.insert)) {
1279
+ textEdit.newText = "";
1280
+ textEdit.insert = START_OF_FILE;
1281
+ }
1282
+ }
1283
+ }
1284
+ }
1285
+ return result;
1286
+ }
1287
+ return import_vscode_languageserver10.CompletionList.create([], true);
1288
+ },
1289
+ async findDefinition(doc, params) {
1290
+ const infoByExt = getStyleSheetInfo(doc);
1291
+ const sourceOffset = doc.offsetAt(params.position);
1292
+ for (const ext in infoByExt) {
1293
+ const info = infoByExt[ext];
1294
+ const generatedOffset = info.generatedOffsetAt(sourceOffset);
1295
+ if (generatedOffset === void 0)
1296
+ continue;
1297
+ const { service: service2, virtualDoc } = info;
1298
+ const result = service2.findDefinition(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed);
1299
+ if (result && updateRange(doc, info, result.range)) {
1300
+ return result;
1301
+ }
1302
+ break;
1303
+ }
1304
+ },
1305
+ async doHover(doc, params) {
1306
+ const infoByExt = getStyleSheetInfo(doc);
1307
+ const sourceOffset = doc.offsetAt(params.position);
1308
+ for (const ext in infoByExt) {
1309
+ const info = infoByExt[ext];
1310
+ const generatedOffset = info.generatedOffsetAt(sourceOffset);
1311
+ if (generatedOffset === void 0)
1312
+ continue;
1313
+ const { service: service2, virtualDoc } = info;
1314
+ const result = service2.doHover(virtualDoc, virtualDoc.positionAt(generatedOffset), service2.parseStylesheet(virtualDoc));
1315
+ if (result && (!result.range || updateRange(doc, info, result.range))) {
1316
+ return result;
1317
+ }
611
1318
  }
1319
+ },
1320
+ async doValidate(doc) {
1321
+ const infoByExt = getStyleSheetInfo(doc);
1322
+ const result = [];
1323
+ for (const ext in infoByExt) {
1324
+ const info = infoByExt[ext];
1325
+ for (const diag of info.service.doValidation(info.virtualDoc, info.parsed)) {
1326
+ if (updateRange(doc, info, diag.range)) {
1327
+ result.push(diag);
1328
+ }
1329
+ }
1330
+ }
1331
+ return result;
612
1332
  }
613
- return [
614
- import_vscode_languageserver9.LocationLink.create(import_vscode_uri5.URI.file(tagEntryFile).toString(), range, range, rangeFromEvent(document, event))
615
- ];
1333
+ };
1334
+ function updateRange(doc, info, range) {
1335
+ const start = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.start));
1336
+ const end = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.end));
1337
+ if (start !== void 0 || end !== void 0) {
1338
+ range.start = doc.positionAt(start ?? end);
1339
+ range.end = doc.positionAt(end ?? start);
1340
+ return true;
1341
+ }
1342
+ return false;
1343
+ }
1344
+ function getStyleSheetInfo(doc) {
1345
+ var _a;
1346
+ const parsed = parse2(doc);
1347
+ let cached = cache.get(parsed);
1348
+ if (!cached) {
1349
+ const results = extractStyleSheets(doc.getText(), parsed.program, getCompilerInfo(doc).lookup);
1350
+ cached = {};
1351
+ for (const ext in results) {
1352
+ const service2 = (_a = services[ext]) == null ? void 0 : _a.call(services);
1353
+ if (!service2)
1354
+ continue;
1355
+ const { generated, sourceOffsetAt, generatedOffsetAt } = results[ext];
1356
+ const virtualDoc = import_vscode_languageserver_textdocument2.TextDocument.create(doc.uri, "css", doc.version, generated);
1357
+ cached[ext] = {
1358
+ service: service2,
1359
+ virtualDoc,
1360
+ sourceOffsetAt,
1361
+ generatedOffsetAt,
1362
+ parsed: service2.parseStylesheet(virtualDoc)
1363
+ };
1364
+ }
1365
+ cache.set(parsed, cached);
1366
+ }
1367
+ return cached;
616
1368
  }
617
1369
 
1370
+ // src/service/index.ts
1371
+ var plugins = [marko_default, stylesheet_default];
1372
+ var service = {
1373
+ async doComplete(doc, params, cancel) {
1374
+ const result = import_vscode_languageserver11.CompletionList.create([], false);
1375
+ try {
1376
+ const requests = plugins.map((plugin) => {
1377
+ var _a;
1378
+ return (_a = plugin.doComplete) == null ? void 0 : _a.call(plugin, doc, params, cancel);
1379
+ });
1380
+ for (const pending of requests) {
1381
+ const cur = await pending;
1382
+ if (cancel.isCancellationRequested)
1383
+ break;
1384
+ if (cur) {
1385
+ let items;
1386
+ if (Array.isArray(cur)) {
1387
+ items = cur;
1388
+ } else {
1389
+ items = cur.items;
1390
+ result.isIncomplete || (result.isIncomplete = cur.isIncomplete);
1391
+ }
1392
+ result.items.push(...items);
1393
+ }
1394
+ }
1395
+ } catch (err) {
1396
+ result.isIncomplete = true;
1397
+ displayError(err);
1398
+ }
1399
+ return result;
1400
+ },
1401
+ async findDefinition(doc, params, cancel) {
1402
+ const result = [];
1403
+ try {
1404
+ const requests = plugins.map((plugin) => {
1405
+ var _a;
1406
+ return (_a = plugin.findDefinition) == null ? void 0 : _a.call(plugin, doc, params, cancel);
1407
+ });
1408
+ for (const pending of requests) {
1409
+ const cur = await pending;
1410
+ if (cancel.isCancellationRequested)
1411
+ break;
1412
+ if (cur) {
1413
+ if (Array.isArray(cur)) {
1414
+ result.push(...cur);
1415
+ } else {
1416
+ result.push(cur);
1417
+ }
1418
+ }
1419
+ }
1420
+ } catch (err) {
1421
+ displayError(err);
1422
+ }
1423
+ return result;
1424
+ },
1425
+ async doHover(doc, params, cancel) {
1426
+ var _a;
1427
+ try {
1428
+ for (const plugin of plugins) {
1429
+ const result = await ((_a = plugin.doHover) == null ? void 0 : _a.call(plugin, doc, params, cancel));
1430
+ if (cancel.isCancellationRequested)
1431
+ return;
1432
+ if (result)
1433
+ return result;
1434
+ }
1435
+ } catch (err) {
1436
+ displayError(err);
1437
+ }
1438
+ },
1439
+ async doValidate(doc) {
1440
+ const result = [];
1441
+ try {
1442
+ const requests = plugins.map((plugin) => {
1443
+ var _a;
1444
+ return (_a = plugin.doValidate) == null ? void 0 : _a.call(plugin, doc);
1445
+ });
1446
+ for (const pending of requests) {
1447
+ const cur = await pending;
1448
+ if (cur)
1449
+ result.push(...cur);
1450
+ }
1451
+ } catch (err) {
1452
+ displayError(err);
1453
+ }
1454
+ return result;
1455
+ },
1456
+ format: marko_default.format
1457
+ };
1458
+
618
1459
  // src/index.ts
619
1460
  if (typeof require !== "undefined" && require.extensions && !(".ts" in require.extensions)) {
620
1461
  require.extensions[".ts"] = void 0;
621
1462
  }
622
- var cacheForCompiler = /* @__PURE__ */ new WeakMap();
623
- var connection = (0, import_node.createConnection)(import_node.ProposedFeatures.all);
1463
+ var documents = new import_node.TextDocuments(import_vscode_languageserver_textdocument3.TextDocument);
1464
+ var connection2 = (0, import_node.createConnection)(import_node.ProposedFeatures.all);
624
1465
  var prevDiagnostics = /* @__PURE__ */ new WeakMap();
625
1466
  var diagnosticTimeouts = /* @__PURE__ */ new WeakMap();
626
- var documents = new import_node.TextDocuments(import_vscode_languageserver_textdocument3.TextDocument);
627
- var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
628
1467
  console.log = (...args) => {
629
- connection.console.log(args.map((v) => (0, import_util.inspect)(v)).join(" "));
1468
+ connection2.console.log(args.map((v) => (0, import_util2.inspect)(v)).join(" "));
630
1469
  };
631
1470
  console.error = (...args) => {
632
- connection.console.error(args.map((v) => (0, import_util.inspect)(v)).join(" "));
1471
+ connection2.console.error(args.map((v) => (0, import_util2.inspect)(v)).join(" "));
633
1472
  };
634
1473
  process.on("uncaughtException", console.error);
635
1474
  process.on("unhandledRejection", console.error);
636
- connection.onInitialize(() => {
1475
+ connection2.onInitialize(() => {
1476
+ setup2(connection2);
1477
+ setup(connection2, documents);
637
1478
  return {
638
1479
  capabilities: {
639
1480
  textDocumentSync: import_node.TextDocumentSyncKind.Incremental,
640
1481
  documentFormattingProvider: true,
641
1482
  definitionProvider: true,
1483
+ hoverProvider: true,
642
1484
  completionProvider: {
643
- triggerCharacters: [".", ":", "<", ">", "@", "/"]
1485
+ triggerCharacters: [
1486
+ ".",
1487
+ ":",
1488
+ "<",
1489
+ ">",
1490
+ "@",
1491
+ "/",
1492
+ '"',
1493
+ "'",
1494
+ "`",
1495
+ " ",
1496
+ "=",
1497
+ "*",
1498
+ "#",
1499
+ "$",
1500
+ "+",
1501
+ "^",
1502
+ "(",
1503
+ "[",
1504
+ "-"
1505
+ ]
644
1506
  }
645
1507
  }
646
1508
  };
647
1509
  });
648
- connection.onInitialized(() => {
1510
+ connection2.onInitialized(() => {
649
1511
  documents.all().forEach((doc) => queueValidation(doc));
650
1512
  });
651
- connection.onCompletion((params) => {
652
- const doc = documents.get(params.textDocument.uri);
653
- const taglib = getTagLibLookup(doc);
654
- if (!taglib)
655
- return import_node.CompletionList.create([], true);
656
- const event = parseUntilOffset({
657
- taglib,
658
- offset: doc.offsetAt(params.position),
659
- text: doc.getText()
660
- });
661
- const handler = event && completions_exports[event.type];
662
- return handler && handler(taglib, doc, params, event) || import_node.CompletionList.create([], true);
1513
+ documents.onDidChangeContent((change) => {
1514
+ queueValidation(change.document);
663
1515
  });
664
- connection.onDefinition((params) => {
665
- const doc = documents.get(params.textDocument.uri);
666
- const taglib = getTagLibLookup(doc);
667
- if (!taglib)
668
- return;
669
- const event = parseUntilOffset({
670
- taglib,
671
- offset: doc.offsetAt(params.position),
672
- text: doc.getText()
673
- });
674
- const handler = event && definitions_exports[event.type];
675
- return handler && handler(taglib, doc, params, event);
1516
+ connection2.onCompletion(async (params, cancel) => {
1517
+ return await service.doComplete(documents.get(params.textDocument.uri), params, cancel) || null;
676
1518
  });
677
- connection.onDocumentFormatting(async ({
678
- textDocument,
679
- options
680
- }) => {
681
- try {
682
- const doc = documents.get(textDocument.uri);
683
- const { fsPath, scheme } = import_vscode_uri6.URI.parse(textDocument.uri);
684
- const text = doc.getText();
685
- const formatted = prettier.format(text, __spreadValues({
686
- parser: "marko",
687
- filepath: fsPath,
688
- plugins: [markoPrettier],
689
- tabWidth: options.tabSize,
690
- useTabs: options.insertSpaces === false
691
- }, scheme === "file" ? await prettier.resolveConfig(fsPath, {
692
- editorconfig: true
693
- }).catch(() => null) : null));
694
- return [
695
- import_node.TextEdit.replace(import_node.Range.create(doc.positionAt(0), doc.positionAt(text.length)), formatted)
696
- ];
697
- } catch (e) {
698
- displayMessage("Error", (0, import_util.inspect)(e, { colors: false }));
699
- }
700
- return [
701
- import_node.TextEdit.replace(import_node.Range.create(import_node.Position.create(0, 0), import_node.Position.create(0, 0)), "")
702
- ];
1519
+ connection2.onDefinition(async (params, cancel) => {
1520
+ return await service.findDefinition(documents.get(params.textDocument.uri), params, cancel) || null;
703
1521
  });
704
- connection.onDidChangeWatchedFiles(() => {
705
- const clearedCompilers = /* @__PURE__ */ new Set();
706
- for (const doc of documents.all()) {
707
- const { compiler } = getCompilerAndTranslatorForDoc(doc);
708
- if (!clearedCompilers.has(compiler)) {
709
- clearCaches(compiler);
710
- clearedCompilers.add(compiler);
711
- }
712
- }
1522
+ connection2.onHover(async (params, cancel) => {
1523
+ return await service.doHover(documents.get(params.textDocument.uri), params, cancel) || null;
713
1524
  });
714
- documents.onDidChangeContent((change) => {
715
- queueValidation(change.document);
716
- if (change.document.version > 1) {
717
- clearCaches(getCompilerAndTranslatorForDoc(change.document).compiler);
718
- }
1525
+ connection2.onDocumentFormatting(async (params, cancel) => {
1526
+ return await service.format(documents.get(params.textDocument.uri), params, cancel) || null;
719
1527
  });
720
1528
  function queueValidation(doc) {
721
1529
  clearTimeout(diagnosticTimeouts.get(doc));
722
- diagnosticTimeouts.set(doc, setTimeout(() => {
1530
+ const id = setTimeout(async () => {
723
1531
  const prevDiag = prevDiagnostics.get(doc);
724
- const nextDiag = doValidate(doc);
725
- if (prevDiag && (0, import_util.isDeepStrictEqual)(prevDiag, nextDiag)) {
1532
+ const nextDiag = await service.doValidate(doc) || [];
1533
+ if (diagnosticTimeouts.get(doc) !== id || prevDiag && (0, import_util2.isDeepStrictEqual)(prevDiag, nextDiag)) {
726
1534
  return;
727
1535
  }
728
1536
  prevDiagnostics.set(doc, nextDiag);
729
- connection.sendDiagnostics({
1537
+ connection2.sendDiagnostics({
730
1538
  uri: doc.uri,
731
1539
  diagnostics: nextDiag
732
1540
  });
733
- }, 800));
734
- }
735
- function doValidate(doc) {
736
- const { fsPath, scheme } = import_vscode_uri6.URI.parse(doc.uri);
737
- if (scheme !== "file") {
738
- return [];
739
- }
740
- const { compiler, translator } = getCompilerAndTranslatorForDoc(doc);
741
- const diagnostics = [];
742
- try {
743
- compiler.compileSync(doc.getText(), fsPath, {
744
- cache: getCacheForCompiler(compiler),
745
- output: "source",
746
- code: false,
747
- translator
748
- });
749
- } catch (e) {
750
- let match;
751
- while (match = markoErrorRegExp.exec(e.message)) {
752
- const [, fileName, rawLine, rawCol, msg] = match;
753
- const line = (parseInt(rawLine, 10) || 1) - 1;
754
- const col = (parseInt(rawCol, 10) || 1) - 1;
755
- diagnostics.push(import_node.Diagnostic.create(import_node.Range.create(line, col, line, col), msg, import_node.DiagnosticSeverity.Error, void 0, fileName));
756
- }
757
- }
758
- return diagnostics;
759
- }
760
- function clearCaches(compiler) {
761
- var _a;
762
- (_a = cacheForCompiler.get(compiler)) == null ? void 0 : _a.clear();
763
- compiler.taglib.clearCaches();
764
- }
765
- function getCacheForCompiler(compiler) {
766
- let cache = cacheForCompiler.get(compiler);
767
- if (!cache) {
768
- cacheForCompiler.set(compiler, cache = /* @__PURE__ */ new Map());
769
- }
770
- return cache;
771
- }
772
- function displayMessage(type, msg) {
773
- setImmediate(() => {
774
- connection.sendNotification(`show${type}`, msg);
775
- });
1541
+ }, 400);
1542
+ diagnosticTimeouts.set(doc, id);
776
1543
  }
777
- documents.listen(connection);
778
- connection.listen();
1544
+ documents.listen(connection2);
1545
+ connection2.listen();
779
1546
  //# sourceMappingURL=index.js.map