@marko/language-server 0.12.1 → 0.12.4

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