@marko/language-server 0.12.3 → 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 (37) hide show
  1. package/dist/index.js +1289 -560
  2. package/dist/index.js.map +3 -3
  3. package/dist/index.mjs +1312 -607
  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 +5 -5
  27. package/dist/utils/completions/index.d.ts +0 -6
  28. package/dist/utils/completions/types/attributeModifier.d.ts +0 -5
  29. package/dist/utils/completions/types/attributeName.d.ts +0 -5
  30. package/dist/utils/completions/types/closeTag.d.ts +0 -5
  31. package/dist/utils/completions/types/openTag.d.ts +0 -5
  32. package/dist/utils/completions/types/openTagName.d.ts +0 -5
  33. package/dist/utils/completions/types/styleContent.d.ts +0 -5
  34. package/dist/utils/definitions/index.d.ts +0 -2
  35. package/dist/utils/definitions/types/attributeName.d.ts +0 -5
  36. package/dist/utils/definitions/types/openTagName.d.ts +0 -5
  37. 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;
68
+ }
69
+ const { var: tagVar } = tag;
70
+ if (tagVar && offset > tagVar.start && offset <= tagVar.end) {
71
+ return tagVar;
64
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;
191
261
  break;
262
+ case "html-comment":
263
+ case "script":
264
+ case "style":
265
+ case "textarea":
266
+ curBodyType = import_htmljs_parser.TagType.text;
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;
454
+ },
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
+ });
198
463
  },
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;
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;
298
- }
299
- function rangeFromEvent(document, event) {
300
- return import_vscode_languageserver2.Range.create(document.positionAt(event.pos), document.positionAt(event.endPos));
544
+ return parsed;
301
545
  }
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();
324
574
  }
325
575
  }
326
- function shiftRange(range, offset) {
327
- if (range) {
328
- shiftPosition(range.start, offset);
329
- shiftPosition(range.end, offset);
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
+ }
330
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);
623
+ }
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));
331
627
  }
332
- function shiftPosition(pos, offset) {
333
- if (pos.line === 0) {
334
- pos.character += offset.character;
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
+ ];
335
672
  }
336
- pos.line += offset.line;
337
- return pos;
338
673
  }
339
674
 
340
- // src/utils/completions/types/attributeName.ts
341
- function attributeName(taglib, document, _params, event) {
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);
699
+ }
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
+ });
742
+ }
743
+
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, doc, params, event) {
433
- const triggerCharacter = params.context && params.context.triggerCharacter || doc.getText(import_vscode_languageserver5.Range.create(import_vscode_languageserver5.Position.create(params.position.line, params.position.character - 1), params.position));
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,223 +930,583 @@ 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
- return [];
1001
+ return;
572
1002
  }
573
1003
  const attrEntryFile = attrDef.filePath || tagDef && tagDef.filePath;
574
1004
  if (!attrEntryFile) {
575
- return [];
1005
+ return;
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_path3 = __toESM(require("path"));
591
- 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
592
1041
  var import_vscode_languageserver9 = require("vscode-languageserver");
593
- function openTagName2(taglib, document, _params, event) {
594
- let tagDef;
595
- let range = START_OF_FILE;
596
- const isAttributeTag = event.tagName[0] === "@";
597
- if (isAttributeTag) {
598
- const parentTag = findNonControlFlowParent(event);
599
- tagDef = parentTag && (parentTag.tagNameExpression ? void 0 : taglib.getTag(parentTag.tagName));
600
- } else {
601
- 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);
602
1069
  }
603
- if (!tagDef) {
604
- 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();
605
1237
  }
606
- const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
607
- if (!import_path3.default.isAbsolute(tagEntryFile)) {
608
- return [];
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
+ }
1314
+ }
1315
+ return result;
609
1316
  }
610
- if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
611
- const tagDefDoc = createTextDocument(tagEntryFile);
612
- const match = RegExpBuilder`/"(?:<${event.tagName}>|${event.tagName})"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
613
- if (match && match.index) {
614
- range = import_vscode_languageserver9.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
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;
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
+ };
615
1348
  }
1349
+ cache.set(parsed, cached);
616
1350
  }
617
- return [
618
- import_vscode_languageserver9.LocationLink.create(import_vscode_uri5.URI.file(tagEntryFile).toString(), range, range, rangeFromEvent(document, event))
619
- ];
1351
+ return cached;
620
1352
  }
621
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
+ };
1428
+
622
1429
  // src/index.ts
623
1430
  if (typeof require !== "undefined" && require.extensions && !(".ts" in require.extensions)) {
624
1431
  require.extensions[".ts"] = void 0;
625
1432
  }
626
- var cacheForCompiler = /* @__PURE__ */ new WeakMap();
627
- 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);
628
1435
  var prevDiagnostics = /* @__PURE__ */ new WeakMap();
629
1436
  var diagnosticTimeouts = /* @__PURE__ */ new WeakMap();
630
- var documents = new import_node.TextDocuments(import_vscode_languageserver_textdocument3.TextDocument);
631
- var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
632
1437
  console.log = (...args) => {
633
- 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(" "));
634
1439
  };
635
1440
  console.error = (...args) => {
636
- 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(" "));
637
1442
  };
638
1443
  process.on("uncaughtException", console.error);
639
1444
  process.on("unhandledRejection", console.error);
640
- connection.onInitialize(() => {
1445
+ connection2.onInitialize(() => {
1446
+ setup2(connection2);
1447
+ setup(connection2, documents);
641
1448
  return {
642
1449
  capabilities: {
643
1450
  textDocumentSync: import_node.TextDocumentSyncKind.Incremental,
644
1451
  documentFormattingProvider: true,
645
1452
  definitionProvider: true,
646
1453
  completionProvider: {
647
- triggerCharacters: [".", ":", "<", ">", "@", "/"]
1454
+ triggerCharacters: [
1455
+ ".",
1456
+ ":",
1457
+ "<",
1458
+ ">",
1459
+ "@",
1460
+ "/",
1461
+ '"',
1462
+ "'",
1463
+ "`",
1464
+ " ",
1465
+ "=",
1466
+ "*",
1467
+ "#",
1468
+ "$",
1469
+ "+",
1470
+ "^",
1471
+ "(",
1472
+ "[",
1473
+ "-"
1474
+ ]
648
1475
  }
649
1476
  }
650
1477
  };
651
1478
  });
652
- connection.onInitialized(() => {
1479
+ connection2.onInitialized(() => {
653
1480
  documents.all().forEach((doc) => queueValidation(doc));
654
1481
  });
655
- connection.onCompletion((params) => {
656
- const doc = documents.get(params.textDocument.uri);
657
- const taglib = getTagLibLookup(doc);
658
- if (!taglib)
659
- return import_node.CompletionList.create([], true);
660
- const event = parseUntilOffset({
661
- taglib,
662
- offset: doc.offsetAt(params.position),
663
- text: doc.getText()
664
- });
665
- const handler = event && completions_exports[event.type];
666
- return handler && handler(taglib, doc, params, event) || import_node.CompletionList.create([], true);
667
- });
668
- connection.onDefinition((params) => {
669
- const doc = documents.get(params.textDocument.uri);
670
- const taglib = getTagLibLookup(doc);
671
- if (!taglib)
672
- return;
673
- const event = parseUntilOffset({
674
- taglib,
675
- offset: doc.offsetAt(params.position),
676
- text: doc.getText()
677
- });
678
- const handler = event && definitions_exports[event.type];
679
- return handler && handler(taglib, doc, params, event);
1482
+ documents.onDidChangeContent((change) => {
1483
+ queueValidation(change.document);
680
1484
  });
681
- connection.onDocumentFormatting(async ({
682
- textDocument,
683
- options
684
- }) => {
685
- try {
686
- const doc = documents.get(textDocument.uri);
687
- const { fsPath, scheme } = import_vscode_uri6.URI.parse(textDocument.uri);
688
- const text = doc.getText();
689
- const formatted = prettier.format(text, __spreadValues({
690
- parser: "marko",
691
- filepath: fsPath,
692
- plugins: [markoPrettier],
693
- tabWidth: options.tabSize,
694
- useTabs: options.insertSpaces === false
695
- }, scheme === "file" ? await prettier.resolveConfig(fsPath, {
696
- editorconfig: true
697
- }).catch(() => null) : null));
698
- return [
699
- import_node.TextEdit.replace(import_node.Range.create(doc.positionAt(0), doc.positionAt(text.length)), formatted)
700
- ];
701
- } catch (e) {
702
- displayMessage("Error", (0, import_util.inspect)(e, { colors: false }));
703
- }
704
- return [
705
- import_node.TextEdit.replace(import_node.Range.create(import_node.Position.create(0, 0), import_node.Position.create(0, 0)), "")
706
- ];
1485
+ connection2.onCompletion(async (params, cancel) => {
1486
+ return await service.doComplete(documents.get(params.textDocument.uri), params, cancel) || null;
707
1487
  });
708
- connection.onDidChangeWatchedFiles(() => {
709
- const clearedCompilers = /* @__PURE__ */ new Set();
710
- for (const doc of documents.all()) {
711
- const { compiler } = getCompilerAndTranslatorForDoc(doc);
712
- if (!clearedCompilers.has(compiler)) {
713
- clearCaches(compiler);
714
- clearedCompilers.add(compiler);
715
- }
716
- }
1488
+ connection2.onDefinition(async (params, cancel) => {
1489
+ return await service.findDefinition(documents.get(params.textDocument.uri), params, cancel) || null;
717
1490
  });
718
- documents.onDidChangeContent((change) => {
719
- queueValidation(change.document);
720
- if (change.document.version > 1) {
721
- clearCaches(getCompilerAndTranslatorForDoc(change.document).compiler);
722
- }
1491
+ connection2.onDocumentFormatting(async (params, cancel) => {
1492
+ return await service.format(documents.get(params.textDocument.uri), params, cancel) || null;
723
1493
  });
724
1494
  function queueValidation(doc) {
725
1495
  clearTimeout(diagnosticTimeouts.get(doc));
726
- diagnosticTimeouts.set(doc, setTimeout(() => {
1496
+ const id = setTimeout(async () => {
727
1497
  const prevDiag = prevDiagnostics.get(doc);
728
- const nextDiag = doValidate(doc);
729
- 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)) {
730
1500
  return;
731
1501
  }
732
1502
  prevDiagnostics.set(doc, nextDiag);
733
- connection.sendDiagnostics({
1503
+ connection2.sendDiagnostics({
734
1504
  uri: doc.uri,
735
1505
  diagnostics: nextDiag
736
1506
  });
737
- }, 800));
738
- }
739
- function doValidate(doc) {
740
- const { fsPath, scheme } = import_vscode_uri6.URI.parse(doc.uri);
741
- if (scheme !== "file") {
742
- return [];
743
- }
744
- const { compiler, translator } = getCompilerAndTranslatorForDoc(doc);
745
- const diagnostics = [];
746
- try {
747
- compiler.compileSync(doc.getText(), fsPath, {
748
- cache: getCacheForCompiler(compiler),
749
- output: "source",
750
- code: false,
751
- translator
752
- });
753
- } catch (e) {
754
- let match;
755
- while (match = markoErrorRegExp.exec(e.message)) {
756
- const [, fileName, rawLine, rawCol, msg] = match;
757
- const line = (parseInt(rawLine, 10) || 1) - 1;
758
- const col = (parseInt(rawCol, 10) || 1) - 1;
759
- diagnostics.push(import_node.Diagnostic.create(import_node.Range.create(line, col, line, col), msg, import_node.DiagnosticSeverity.Error, void 0, fileName));
760
- }
761
- }
762
- return diagnostics;
763
- }
764
- function clearCaches(compiler) {
765
- var _a;
766
- (_a = cacheForCompiler.get(compiler)) == null ? void 0 : _a.clear();
767
- compiler.taglib.clearCaches();
768
- }
769
- function getCacheForCompiler(compiler) {
770
- let cache = cacheForCompiler.get(compiler);
771
- if (!cache) {
772
- cacheForCompiler.set(compiler, cache = /* @__PURE__ */ new Map());
773
- }
774
- return cache;
775
- }
776
- function displayMessage(type, msg) {
777
- setImmediate(() => {
778
- connection.sendNotification(`show${type}`, msg);
779
- });
1507
+ }, 400);
1508
+ diagnosticTimeouts.set(doc, id);
780
1509
  }
781
- documents.listen(connection);
782
- connection.listen();
1510
+ documents.listen(connection2);
1511
+ connection2.listen();
783
1512
  //# sourceMappingURL=index.js.map