@marko/language-server 0.12.3 → 0.12.6

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