@marko/language-server 0.11.0 → 0.12.2

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 (48) hide show
  1. package/LICENSE +1 -1
  2. package/bin.js +2 -0
  3. package/dist/index.js +744 -139
  4. package/dist/index.js.map +7 -1
  5. package/dist/index.mjs +822 -0
  6. package/dist/index.mjs.map +7 -0
  7. package/dist/utils/compiler.d.ts +5 -61
  8. package/dist/utils/completions/types/attributeModifier.d.ts +5 -5
  9. package/dist/utils/completions/types/attributeName.d.ts +5 -5
  10. package/dist/utils/completions/types/closeTag.d.ts +5 -5
  11. package/dist/utils/completions/types/openTag.d.ts +5 -5
  12. package/dist/utils/completions/types/openTagName.d.ts +5 -5
  13. package/dist/utils/completions/types/styleContent.d.ts +4 -4
  14. package/dist/utils/definitions/types/attributeName.d.ts +5 -5
  15. package/dist/utils/definitions/types/openTagName.d.ts +5 -5
  16. package/dist/utils/htmljs-parser.d.ts +2 -2
  17. package/dist/utils/utils.d.ts +2 -2
  18. package/package.json +30 -16
  19. package/dist/bin.js +0 -5
  20. package/dist/bin.js.map +0 -1
  21. package/dist/utils/compiler.js +0 -54
  22. package/dist/utils/compiler.js.map +0 -1
  23. package/dist/utils/completions/index.js +0 -10
  24. package/dist/utils/completions/index.js.map +0 -1
  25. package/dist/utils/completions/types/attributeModifier.js +0 -20
  26. package/dist/utils/completions/types/attributeModifier.js.map +0 -1
  27. package/dist/utils/completions/types/attributeName.js +0 -84
  28. package/dist/utils/completions/types/attributeName.js.map +0 -1
  29. package/dist/utils/completions/types/closeTag.js +0 -21
  30. package/dist/utils/completions/types/closeTag.js.map +0 -1
  31. package/dist/utils/completions/types/openTag.js +0 -21
  32. package/dist/utils/completions/types/openTag.js.map +0 -1
  33. package/dist/utils/completions/types/openTagName.js +0 -75
  34. package/dist/utils/completions/types/openTagName.js.map +0 -1
  35. package/dist/utils/completions/types/styleContent.js +0 -22
  36. package/dist/utils/completions/types/styleContent.js.map +0 -1
  37. package/dist/utils/definitions/index.js +0 -6
  38. package/dist/utils/definitions/index.js.map +0 -1
  39. package/dist/utils/definitions/types/attributeName.js +0 -31
  40. package/dist/utils/definitions/types/attributeName.js.map +0 -1
  41. package/dist/utils/definitions/types/openTagName.js +0 -38
  42. package/dist/utils/definitions/types/openTagName.js.map +0 -1
  43. package/dist/utils/htmljs-parser.js +0 -179
  44. package/dist/utils/htmljs-parser.js.map +0 -1
  45. package/dist/utils/regexp-builder.js +0 -27
  46. package/dist/utils/regexp-builder.js.map +0 -1
  47. package/dist/utils/utils.js +0 -68
  48. package/dist/utils/utils.js.map +0 -1
package/dist/index.mjs ADDED
@@ -0,0 +1,822 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
17
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
18
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
19
+ }) : x)(function(x) {
20
+ if (typeof require !== "undefined")
21
+ return require.apply(this, arguments);
22
+ throw new Error('Dynamic require of "' + x + '" is not supported');
23
+ });
24
+ var __export = (target, all) => {
25
+ for (var name in all)
26
+ __defProp(target, name, { get: all[name], enumerable: true });
27
+ };
28
+
29
+ // src/index.ts
30
+ import {
31
+ createConnection,
32
+ ProposedFeatures,
33
+ Range as Range4,
34
+ Position as Position3,
35
+ CompletionList as CompletionList6,
36
+ Diagnostic,
37
+ DiagnosticSeverity,
38
+ TextDocuments,
39
+ TextEdit as TextEdit5,
40
+ TextDocumentSyncKind
41
+ } from "vscode-languageserver/node";
42
+ import { URI as URI6 } from "vscode-uri";
43
+ import { TextDocument as TextDocument3 } from "vscode-languageserver-textdocument";
44
+ import * as prettier from "prettier";
45
+ import * as markoPrettier from "prettier-plugin-marko";
46
+ import { inspect, isDeepStrictEqual } from "util";
47
+
48
+ // src/utils/compiler.ts
49
+ import path from "path";
50
+ import { URI } from "vscode-uri";
51
+ import resolveFrom from "resolve-from";
52
+ import lassoPackageRoot from "lasso-package-root";
53
+ import * as builtinCompiler from "@marko/compiler";
54
+ import * as builtinTranslator from "@marko/translator-default";
55
+ builtinCompiler.configure({ translator: builtinTranslator });
56
+ var compilerAndTranslatorForDoc = /* @__PURE__ */ new WeakMap();
57
+ function getCompilerAndTranslatorForDoc(doc) {
58
+ let compilerAndTranslator = compilerAndTranslatorForDoc.get(doc);
59
+ if (!compilerAndTranslator) {
60
+ compilerAndTranslatorForDoc.set(doc, compilerAndTranslator = loadCompiler(path.dirname(URI.parse(doc.uri).fsPath)));
61
+ }
62
+ return compilerAndTranslator;
63
+ }
64
+ function getTagLibLookup(document) {
65
+ try {
66
+ const { compiler, translator } = getCompilerAndTranslatorForDoc(document);
67
+ return compiler.taglib.buildLookup(URI.parse(document.uri).fsPath, translator);
68
+ } catch {
69
+ }
70
+ }
71
+ function loadCompiler(dir) {
72
+ const rootDir = lassoPackageRoot.getRootDir(dir);
73
+ const pkgPath = rootDir && resolveFrom.silent(rootDir, "@marko/compiler/package.json");
74
+ const pkg = pkgPath && __require(pkgPath);
75
+ if (pkg && /^5\./.test(pkg.version)) {
76
+ try {
77
+ let translator = [].concat(Object.keys(pkg.dependencies), Object.keys(pkg.peerDependencies), Object.keys(pkg.devDependencies)).find((name) => /^marko$|^(@\/marko\/|marko-)translator-/.test(name));
78
+ if (translator === "marko" || !translator) {
79
+ translator = __require(resolveFrom(dir, "@marko/compiler/config")).translator;
80
+ }
81
+ __require(resolveFrom(dir, translator));
82
+ return {
83
+ compiler: __require(resolveFrom(dir, "@marko/compiler")),
84
+ translator
85
+ };
86
+ } catch {
87
+ }
88
+ }
89
+ return {
90
+ compiler: builtinCompiler,
91
+ translator: builtinTranslator
92
+ };
93
+ }
94
+
95
+ // src/utils/htmljs-parser.ts
96
+ import { createParser } from "htmljs-parser";
97
+ var SUPPORTED_STYLE_LANGS = {
98
+ css: true,
99
+ scss: true,
100
+ less: true
101
+ };
102
+ function parseUntilOffset(options) {
103
+ const { offset, text, taglib, includeErrors } = options;
104
+ let result = null;
105
+ let parentTag = null;
106
+ const parser = createParser({
107
+ onError: includeErrors && finish,
108
+ onScriptlet: finish,
109
+ onPlaceholder: finish,
110
+ onOpenTagName(ev) {
111
+ if (parentTag) {
112
+ ev.parent = parentTag;
113
+ }
114
+ if (!ev.concise) {
115
+ ev.pos += 1;
116
+ }
117
+ ev.endPos = ev.pos + ev.tagName.length;
118
+ parentTag = ev;
119
+ finish(ev);
120
+ },
121
+ onOpenTag(ev) {
122
+ ev.parent = parentTag.parent;
123
+ parentTag = ev;
124
+ if (ev.tagName === "style") {
125
+ const firstAttr = ev.attributes[0];
126
+ const isBlock = firstAttr && firstAttr.name.startsWith("{");
127
+ if (isBlock) {
128
+ const content = firstAttr.name.slice(1, -1);
129
+ const pos = text.indexOf(content, ev.tagNameEndPos);
130
+ const endPos = pos + content.length;
131
+ const requestedLanguage = ev.shorthandClassNames && ev.shorthandClassNames[0].rawParts[0] && ev.shorthandClassNames[0].rawParts[0].text;
132
+ const language = requestedLanguage && SUPPORTED_STYLE_LANGS[requestedLanguage] ? requestedLanguage : "css";
133
+ finish({
134
+ type: "styleContent",
135
+ language,
136
+ block: true,
137
+ content: text.slice(pos, endPos),
138
+ pos,
139
+ endPos
140
+ });
141
+ return;
142
+ }
143
+ }
144
+ let attrEndPos = ev.tagNameEndPos;
145
+ for (const attr of ev.attributes) {
146
+ if (!attr.name) {
147
+ if (attr.value !== void 0) {
148
+ attrEndPos += attr.value.length;
149
+ }
150
+ continue;
151
+ }
152
+ if (attr.name.slice(0, 3) === "...") {
153
+ attrEndPos = attr.argument ? attr.argument.endPos + 1 : attr.endPos;
154
+ continue;
155
+ }
156
+ const attrStartPos = text.indexOf(attr.name, attrEndPos);
157
+ const match = /:(.*)$/.exec(attr.name);
158
+ const modifier = match && match[1];
159
+ let name = attr.name;
160
+ if (modifier) {
161
+ name = name.slice(0, name.length - modifier.length - 1);
162
+ const modifierStartPos = attrStartPos + name.length;
163
+ const modifierEndPos = modifierStartPos + modifier.length + 1;
164
+ if (finish({
165
+ type: "attributeModifier",
166
+ tag: ev,
167
+ name,
168
+ modifier,
169
+ pos: modifierStartPos,
170
+ endPos: modifierEndPos
171
+ })) {
172
+ return;
173
+ }
174
+ }
175
+ const attrNameEndPos = attrStartPos + name.length;
176
+ if (finish({
177
+ type: "attributeName",
178
+ tag: ev,
179
+ name,
180
+ pos: attrStartPos,
181
+ endPos: attrNameEndPos
182
+ })) {
183
+ return;
184
+ }
185
+ if (attr.value) {
186
+ attrEndPos = attr.endPos;
187
+ const valueStartPos = attr.pos + 1;
188
+ if (finish({
189
+ type: "attributeValue",
190
+ tag: ev,
191
+ name,
192
+ value: text.slice(valueStartPos, attrEndPos),
193
+ pos: valueStartPos,
194
+ endPos: attr.endPos
195
+ })) {
196
+ break;
197
+ }
198
+ } else {
199
+ attrEndPos = attr.argument ? attr.argument.endPos + 1 : attr.endPos;
200
+ }
201
+ }
202
+ finish(ev);
203
+ },
204
+ onText(ev) {
205
+ ev.endPos = parser.pos;
206
+ ev.pos = ev.endPos - ev.value.length;
207
+ if (parentTag) {
208
+ ev.parent = parentTag;
209
+ if (parentTag.tagName === "style") {
210
+ finish({
211
+ type: "styleContent",
212
+ language: "css",
213
+ block: false,
214
+ content: ev.value,
215
+ pos: ev.pos,
216
+ endPos: ev.endPos
217
+ });
218
+ return;
219
+ }
220
+ }
221
+ finish(ev);
222
+ },
223
+ onCloseTag(ev) {
224
+ parentTag = parentTag && parentTag.parent;
225
+ finish(ev);
226
+ }
227
+ }, {
228
+ isOpenTagOnly(ev) {
229
+ const tagDef = taglib.getTag(ev);
230
+ return tagDef && tagDef.openTagOnly;
231
+ }
232
+ });
233
+ try {
234
+ parser.parse(`${text}
235
+ `);
236
+ } catch (err) {
237
+ return includeErrors ? {
238
+ type: "error",
239
+ code: "UNEXPECTED_TOKEN",
240
+ message: err.message,
241
+ pos: parser.pos,
242
+ endPos: parser.pos
243
+ } : null;
244
+ }
245
+ return result;
246
+ function finish(event) {
247
+ const { type, pos, endPos } = event;
248
+ if (!result && (type === "error" || pos != null && pos <= offset && endPos != null && endPos >= offset)) {
249
+ result = event;
250
+ parser.end();
251
+ return true;
252
+ }
253
+ return false;
254
+ }
255
+ }
256
+
257
+ // src/utils/completions/index.ts
258
+ var completions_exports = {};
259
+ __export(completions_exports, {
260
+ attributeModifier: () => attributeModifier,
261
+ attributeName: () => attributeName,
262
+ closeTag: () => closeTag,
263
+ openTag: () => openTag,
264
+ openTagName: () => openTagName,
265
+ styleContent: () => styleContent
266
+ });
267
+
268
+ // src/utils/completions/types/attributeModifier.ts
269
+ import {
270
+ CompletionList,
271
+ CompletionItemKind
272
+ } from "vscode-languageserver";
273
+ function attributeModifier(_taglib, _document, _params, _event) {
274
+ return CompletionList.create([
275
+ {
276
+ label: "scoped",
277
+ kind: CompletionItemKind.Keyword,
278
+ detail: "Use to prefix with a unique ID"
279
+ },
280
+ {
281
+ label: "no-update",
282
+ kind: CompletionItemKind.Keyword,
283
+ detail: "Use to skip future updates to this attribute"
284
+ }
285
+ ], true);
286
+ }
287
+
288
+ // src/utils/completions/types/attributeName.ts
289
+ import {
290
+ CompletionList as CompletionList2,
291
+ CompletionItemKind as CompletionItemKind2,
292
+ MarkupKind,
293
+ InsertTextFormat,
294
+ TextEdit as TextEdit2
295
+ } from "vscode-languageserver";
296
+
297
+ // src/utils/utils.ts
298
+ import fs from "fs";
299
+ import { URI as URI2 } from "vscode-uri";
300
+ import {
301
+ TextEdit,
302
+ Position,
303
+ Range
304
+ } from "vscode-languageserver";
305
+ import { TextDocument } from "vscode-languageserver-textdocument";
306
+ var START_OF_FILE = Range.create(Position.create(0, 0), Position.create(0, 0));
307
+ function findNonControlFlowParent(tag) {
308
+ let parent = tag.parent;
309
+ while (parent) {
310
+ if (!/^(?:else-)?if|else|for|while$/.test(parent.tagName)) {
311
+ return parent;
312
+ }
313
+ parent = parent.parent;
314
+ }
315
+ return null;
316
+ }
317
+ function rangeFromEvent(document, event) {
318
+ return Range.create(document.positionAt(event.pos), document.positionAt(event.endPos));
319
+ }
320
+ function createTextDocument(filename) {
321
+ const uri = URI2.file(filename).toString();
322
+ const content = fs.readFileSync(filename, "utf-8");
323
+ return TextDocument.create(uri, "plaintext", 0, content);
324
+ }
325
+ function shiftCompletionRanges(list, offset) {
326
+ list.items.forEach((item) => {
327
+ if (item.additionalTextEdits) {
328
+ item.additionalTextEdits.forEach((edit) => shiftRange(edit.range, offset));
329
+ }
330
+ if (item.textEdit) {
331
+ shiftEdit(item.textEdit, offset);
332
+ }
333
+ });
334
+ return list;
335
+ }
336
+ function shiftEdit(edit, offset) {
337
+ if (TextEdit.is(edit)) {
338
+ shiftRange(edit.range, offset);
339
+ } else {
340
+ shiftRange(edit.insert, offset);
341
+ shiftRange(edit.replace, offset);
342
+ }
343
+ }
344
+ function shiftRange(range, offset) {
345
+ if (range) {
346
+ shiftPosition(range.start, offset);
347
+ shiftPosition(range.end, offset);
348
+ }
349
+ }
350
+ function shiftPosition(pos, offset) {
351
+ if (pos.line === 0) {
352
+ pos.character += offset.character;
353
+ }
354
+ pos.line += offset.line;
355
+ return pos;
356
+ }
357
+
358
+ // src/utils/completions/types/attributeName.ts
359
+ function attributeName(taglib, document, _params, event) {
360
+ const completions = [];
361
+ const attrNameRange = rangeFromEvent(document, event);
362
+ const tagDef = !event.tag.tagNameExpression && taglib.getTag(event.tag.tagName);
363
+ const tagName = tagDef && tagDef.name || "*";
364
+ const nestedTagAttrs = {};
365
+ const neverAttrs = /* @__PURE__ */ new Set();
366
+ if (tagDef && tagDef.nestedTags) {
367
+ for (const key in tagDef.nestedTags) {
368
+ const nestedTagDef = tagDef.nestedTags[key];
369
+ nestedTagAttrs[nestedTagDef.targetProperty] = true;
370
+ }
371
+ }
372
+ taglib.forEachAttribute(tagName, (attr) => {
373
+ if (attr.type === "never") {
374
+ neverAttrs.add(attr.name);
375
+ }
376
+ });
377
+ taglib.forEachAttribute(tagName, (attr, parent) => {
378
+ if (attr.deprecated || nestedTagAttrs[attr.name] || attr.name === "*" || neverAttrs.has(attr.name) || attr.name[0] === "_" && /\/node_modules\//.test(attr.filePath || parent.filePath)) {
379
+ return;
380
+ }
381
+ const type = attr.type || (attr.html ? "string" : null);
382
+ const documentation = {
383
+ kind: MarkupKind.Markdown,
384
+ value: attr.description || ""
385
+ };
386
+ let label = attr.name;
387
+ let snippet = attr.name;
388
+ if (attr.enum) {
389
+ snippet += `="\${1|${attr.enum.join()}|}"$0`;
390
+ } else {
391
+ switch (type) {
392
+ case "string":
393
+ snippet += '="$1"$0';
394
+ break;
395
+ case "function":
396
+ snippet += "=($1)$0";
397
+ break;
398
+ case "statement":
399
+ case "boolean":
400
+ case "flag":
401
+ break;
402
+ default:
403
+ snippet += "=";
404
+ break;
405
+ }
406
+ }
407
+ const autocomplete = attr.autocomplete && Array.isArray(attr.autocomplete) ? attr.autocomplete[0] : attr.autocomplete;
408
+ if (autocomplete) {
409
+ label = autocomplete.displayText || label;
410
+ snippet = autocomplete.snippet || snippet;
411
+ if (autocomplete.descriptionMoreURL) {
412
+ if (documentation.value) {
413
+ documentation.value += `
414
+
415
+ `;
416
+ }
417
+ documentation.value += `[More Info](${autocomplete.descriptionMoreURL})`;
418
+ }
419
+ }
420
+ completions.push({
421
+ label,
422
+ documentation: documentation.value ? documentation : void 0,
423
+ kind: CompletionItemKind2.Property,
424
+ insertTextFormat: InsertTextFormat.Snippet,
425
+ textEdit: TextEdit2.replace(attrNameRange, snippet)
426
+ });
427
+ });
428
+ return CompletionList2.create(completions, true);
429
+ }
430
+
431
+ // src/utils/completions/types/closeTag.ts
432
+ import {
433
+ CompletionList as CompletionList3,
434
+ CompletionItemKind as CompletionItemKind3,
435
+ InsertTextFormat as InsertTextFormat2,
436
+ TextEdit as TextEdit3
437
+ } from "vscode-languageserver";
438
+ function closeTag(_taglib, document, _params, event) {
439
+ if (event.tagName[0] === "$") {
440
+ return;
441
+ }
442
+ const closingTagStr = `</${event.tagName}>`;
443
+ return CompletionList3.create([
444
+ {
445
+ label: closingTagStr,
446
+ kind: CompletionItemKind3.Class,
447
+ insertTextFormat: InsertTextFormat2.Snippet,
448
+ textEdit: TextEdit3.replace(rangeFromEvent(document, event), closingTagStr)
449
+ }
450
+ ], true);
451
+ }
452
+
453
+ // src/utils/completions/types/openTag.ts
454
+ import {
455
+ CompletionList as CompletionList4,
456
+ CompletionItemKind as CompletionItemKind4,
457
+ InsertTextFormat as InsertTextFormat3
458
+ } from "vscode-languageserver";
459
+ function openTag(_taglib, _document, params, event) {
460
+ const triggerCharacter = params.context && params.context.triggerCharacter;
461
+ if (triggerCharacter !== ">" || event.openTagOnly || event.selfClosed) {
462
+ return;
463
+ }
464
+ const closingTagStr = `</${event.tagName[0] === "$" ? "" : event.tagName}>`;
465
+ return CompletionList4.create([
466
+ {
467
+ label: closingTagStr,
468
+ kind: CompletionItemKind4.Class,
469
+ insertTextFormat: InsertTextFormat3.Snippet,
470
+ insertText: `
471
+ $0
472
+ ${closingTagStr}`
473
+ }
474
+ ], true);
475
+ }
476
+
477
+ // src/utils/completions/types/openTagName.ts
478
+ import path2 from "path";
479
+ import { URI as URI3 } from "vscode-uri";
480
+ import {
481
+ CompletionItemKind as CompletionItemKind5,
482
+ CompletionList as CompletionList5,
483
+ InsertTextFormat as InsertTextFormat4,
484
+ MarkupKind as MarkupKind2,
485
+ TextEdit as TextEdit4
486
+ } from "vscode-languageserver";
487
+ function openTagName(taglib, document, params, event) {
488
+ const { fsPath: currentTemplateFilePath } = URI3.parse(document.uri);
489
+ let tags;
490
+ const triggerCharacter = params.context && params.context.triggerCharacter || event.tagName[0];
491
+ const isAttributeTag = triggerCharacter === "@";
492
+ const tagNameRange = rangeFromEvent(document, event);
493
+ if (isAttributeTag) {
494
+ const parentTag = findNonControlFlowParent(event);
495
+ const parentTagDef = parentTag && !parentTag.tagNameExpression && taglib.getTag(parentTag.tagName);
496
+ tags = parentTagDef && parentTagDef.nestedTags && Object.values(parentTagDef.nestedTags) || [];
497
+ } else {
498
+ tags = taglib.getTagsSorted().filter((it) => !it.isNestedTag);
499
+ }
500
+ return CompletionList5.create(tags.filter((it) => !it.deprecated).filter((it) => it.name !== "*").filter((it) => /^[^_]/.test(it.name) || !/\/node_modules\//.test(it.filePath)).map((it) => {
501
+ let label = it.isNestedTag ? `@${it.name}` : it.name;
502
+ const fileForTag = it.template || it.renderer || it.filePath;
503
+ const fileURIForTag = URI3.file(fileForTag).toString();
504
+ const nodeModuleMatch = /\/node_modules\/((?:@[^/]+\/)?[^/]+)/.exec(fileForTag);
505
+ const nodeModuleName = nodeModuleMatch && nodeModuleMatch[1];
506
+ const isCoreTag = nodeModuleName === "marko";
507
+ const documentation = {
508
+ kind: MarkupKind2.Markdown,
509
+ 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:
510
+
511
+ [${path2.relative(currentTemplateFilePath, fileForTag)}](${fileURIForTag})`
512
+ };
513
+ if (it.description) {
514
+ documentation.value += `
515
+
516
+ ${it.description}`;
517
+ }
518
+ const autocomplete = it.autocomplete && it.autocomplete[0];
519
+ if (autocomplete) {
520
+ if (autocomplete.displayText) {
521
+ label = autocomplete.displayText;
522
+ }
523
+ if (autocomplete.description) {
524
+ documentation.value += `
525
+
526
+ ${autocomplete.description}`;
527
+ }
528
+ if (autocomplete.descriptionMoreURL) {
529
+ documentation.value += `
530
+
531
+ [More Info](${autocomplete.descriptionMoreURL})`;
532
+ }
533
+ }
534
+ return {
535
+ label,
536
+ documentation,
537
+ kind: CompletionItemKind5.Class,
538
+ insertTextFormat: InsertTextFormat4.Snippet,
539
+ textEdit: TextEdit4.replace(tagNameRange, autocomplete && autocomplete.snippet || label)
540
+ };
541
+ }), true);
542
+ }
543
+
544
+ // src/utils/completions/types/styleContent.ts
545
+ import { Position as Position2 } from "vscode-languageserver";
546
+ import { TextDocument as TextDocument2 } from "vscode-languageserver-textdocument";
547
+ import {
548
+ getCSSLanguageService,
549
+ getSCSSLanguageService,
550
+ getLESSLanguageService
551
+ } from "vscode-css-languageservice";
552
+ var services = {
553
+ css: getCSSLanguageService,
554
+ scss: getSCSSLanguageService,
555
+ less: getLESSLanguageService
556
+ };
557
+ function styleContent(_taglib, document, params, event) {
558
+ const service = services[event.language]();
559
+ const startPos = document.positionAt(event.pos);
560
+ const relativePos = shiftPosition(params.position, Position2.create(startPos.line * -1, startPos.character * -1));
561
+ const contentDocument = TextDocument2.create(document.uri, event.language, document.version, event.content);
562
+ const completions = service.doComplete(contentDocument, relativePos, service.parseStylesheet(contentDocument));
563
+ return shiftCompletionRanges(completions, startPos);
564
+ }
565
+
566
+ // src/utils/definitions/index.ts
567
+ var definitions_exports = {};
568
+ __export(definitions_exports, {
569
+ attributeName: () => attributeName2,
570
+ openTagName: () => openTagName2
571
+ });
572
+
573
+ // src/utils/definitions/types/attributeName.ts
574
+ import { URI as URI4 } from "vscode-uri";
575
+ import {
576
+ Range as Range2,
577
+ LocationLink
578
+ } from "vscode-languageserver";
579
+
580
+ // src/utils/regexp-builder.ts
581
+ function RegExpBuilder(strings, ...expressions) {
582
+ let i = 0;
583
+ let src = strings[0].slice(strings[0].indexOf("/") + 1);
584
+ const secondLastExprIndex = strings.length - 2;
585
+ for (; i < secondLastExprIndex; i++) {
586
+ src += escape(expressions[i]) + strings[i + 1];
587
+ }
588
+ src += escape(expressions[i]);
589
+ const lastStr = strings[i + 1];
590
+ const lastSlashIndex = lastStr.lastIndexOf("/");
591
+ let flags = "";
592
+ if (lastSlashIndex === -1) {
593
+ src += lastStr;
594
+ } else {
595
+ flags = lastStr.slice(lastSlashIndex + 1);
596
+ src += lastStr.slice(0, lastSlashIndex);
597
+ }
598
+ return new RegExp(src, flags);
599
+ }
600
+ function escape(val) {
601
+ return String(val).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
602
+ }
603
+
604
+ // src/utils/definitions/types/attributeName.ts
605
+ function attributeName2(taglib, document, _params, event) {
606
+ const tagName = event.tag.tagNameExpression ? void 0 : event.tag.tagName;
607
+ const tagDef = tagName && taglib.getTag(tagName);
608
+ const attrDef = taglib.getAttribute(tagName || "*", event.name);
609
+ let range = START_OF_FILE;
610
+ if (!attrDef) {
611
+ return;
612
+ }
613
+ const attrEntryFile = attrDef.filePath || tagDef && tagDef.filePath;
614
+ if (!attrEntryFile) {
615
+ return;
616
+ }
617
+ if (/\/marko(?:-tag)?\.json$/.test(attrEntryFile)) {
618
+ const tagDefDoc = createTextDocument(attrEntryFile);
619
+ const match = RegExpBuilder`/"@${event.name}"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
620
+ if (match && match.index) {
621
+ range = Range2.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
622
+ }
623
+ }
624
+ return [
625
+ LocationLink.create(URI4.file(attrEntryFile).toString(), range, range, rangeFromEvent(document, event))
626
+ ];
627
+ }
628
+
629
+ // src/utils/definitions/types/openTagName.ts
630
+ import { URI as URI5 } from "vscode-uri";
631
+ import {
632
+ Range as Range3,
633
+ LocationLink as LocationLink2
634
+ } from "vscode-languageserver";
635
+ function openTagName2(taglib, document, _params, event) {
636
+ let tagDef;
637
+ let range = START_OF_FILE;
638
+ const isAttributeTag = event.tagName[0] === "@";
639
+ if (isAttributeTag) {
640
+ const parentTag = findNonControlFlowParent(event);
641
+ tagDef = parentTag && (parentTag.tagNameExpression ? void 0 : taglib.getTag(parentTag.tagName));
642
+ } else {
643
+ tagDef = taglib.getTag(event.tagName);
644
+ }
645
+ if (!tagDef) {
646
+ return;
647
+ }
648
+ const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
649
+ if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
650
+ const tagDefDoc = createTextDocument(tagEntryFile);
651
+ const match = RegExpBuilder`/"<${event.tagName}>"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
652
+ if (match && match.index) {
653
+ range = Range3.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
654
+ }
655
+ }
656
+ return [
657
+ LocationLink2.create(URI5.file(tagEntryFile).toString(), range, range, rangeFromEvent(document, event))
658
+ ];
659
+ }
660
+
661
+ // src/index.ts
662
+ if (typeof __require !== "undefined" && __require.extensions && !(".ts" in __require.extensions)) {
663
+ __require.extensions[".ts"] = void 0;
664
+ }
665
+ var cacheForCompiler = /* @__PURE__ */ new WeakMap();
666
+ var connection = createConnection(ProposedFeatures.all);
667
+ var prevDiagnostics = /* @__PURE__ */ new WeakMap();
668
+ var diagnosticTimeouts = /* @__PURE__ */ new WeakMap();
669
+ var documents = new TextDocuments(TextDocument3);
670
+ var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
671
+ console.log = (...args) => {
672
+ connection.console.log(args.map((v) => inspect(v)).join(" "));
673
+ };
674
+ console.error = (...args) => {
675
+ connection.console.error(args.map((v) => inspect(v)).join(" "));
676
+ };
677
+ process.on("uncaughtException", console.error);
678
+ process.on("unhandledRejection", console.error);
679
+ connection.onInitialize(() => {
680
+ return {
681
+ capabilities: {
682
+ textDocumentSync: TextDocumentSyncKind.Incremental,
683
+ documentFormattingProvider: true,
684
+ definitionProvider: true,
685
+ completionProvider: {
686
+ triggerCharacters: [".", ":", "<", ">", "@", "/"]
687
+ }
688
+ }
689
+ };
690
+ });
691
+ connection.onInitialized(() => {
692
+ documents.all().forEach((doc) => queueValidation(doc));
693
+ });
694
+ connection.onCompletion((params) => {
695
+ const doc = documents.get(params.textDocument.uri);
696
+ const taglib = getTagLibLookup(doc);
697
+ if (!taglib)
698
+ return CompletionList6.create([], true);
699
+ const event = parseUntilOffset({
700
+ taglib,
701
+ offset: doc.offsetAt(params.position),
702
+ text: doc.getText()
703
+ });
704
+ const handler = event && completions_exports[event.type];
705
+ return handler && handler(taglib, doc, params, event) || CompletionList6.create([], true);
706
+ });
707
+ connection.onDefinition((params) => {
708
+ const doc = documents.get(params.textDocument.uri);
709
+ const taglib = getTagLibLookup(doc);
710
+ if (!taglib)
711
+ return;
712
+ const event = parseUntilOffset({
713
+ taglib,
714
+ offset: doc.offsetAt(params.position),
715
+ text: doc.getText()
716
+ });
717
+ const handler = event && definitions_exports[event.type];
718
+ return handler && handler(taglib, doc, params, event);
719
+ });
720
+ connection.onDocumentFormatting(async ({
721
+ textDocument,
722
+ options
723
+ }) => {
724
+ try {
725
+ const doc = documents.get(textDocument.uri);
726
+ const { fsPath, scheme } = URI6.parse(textDocument.uri);
727
+ const text = doc.getText();
728
+ const formatted = prettier.format(text, __spreadValues({
729
+ parser: "marko",
730
+ filepath: fsPath,
731
+ plugins: [markoPrettier],
732
+ tabWidth: options.tabSize,
733
+ useTabs: options.insertSpaces === false
734
+ }, scheme === "file" ? await prettier.resolveConfig(fsPath, {
735
+ editorconfig: true
736
+ }).catch(() => null) : null));
737
+ return [
738
+ TextEdit5.replace(Range4.create(doc.positionAt(0), doc.positionAt(text.length)), formatted)
739
+ ];
740
+ } catch (e) {
741
+ displayMessage("Error", inspect(e, { colors: false }));
742
+ }
743
+ return [
744
+ TextEdit5.replace(Range4.create(Position3.create(0, 0), Position3.create(0, 0)), "")
745
+ ];
746
+ });
747
+ connection.onDidChangeWatchedFiles(() => {
748
+ const clearedCompilers = /* @__PURE__ */ new Set();
749
+ for (const doc of documents.all()) {
750
+ const { compiler } = getCompilerAndTranslatorForDoc(doc);
751
+ if (!clearedCompilers.has(compiler)) {
752
+ clearCaches(compiler);
753
+ clearedCompilers.add(compiler);
754
+ }
755
+ }
756
+ });
757
+ documents.onDidChangeContent((change) => {
758
+ queueValidation(change.document);
759
+ if (change.document.version > 1) {
760
+ clearCaches(getCompilerAndTranslatorForDoc(change.document).compiler);
761
+ }
762
+ });
763
+ function queueValidation(doc) {
764
+ clearTimeout(diagnosticTimeouts.get(doc));
765
+ diagnosticTimeouts.set(doc, setTimeout(() => {
766
+ const prevDiag = prevDiagnostics.get(doc);
767
+ const nextDiag = doValidate(doc);
768
+ if (prevDiag && isDeepStrictEqual(prevDiag, nextDiag)) {
769
+ return;
770
+ }
771
+ prevDiagnostics.set(doc, nextDiag);
772
+ connection.sendDiagnostics({
773
+ uri: doc.uri,
774
+ diagnostics: nextDiag
775
+ });
776
+ }, 800));
777
+ }
778
+ function doValidate(doc) {
779
+ const { fsPath, scheme } = URI6.parse(doc.uri);
780
+ if (scheme !== "file") {
781
+ return [];
782
+ }
783
+ const { compiler, translator } = getCompilerAndTranslatorForDoc(doc);
784
+ const diagnostics = [];
785
+ try {
786
+ compiler.compileSync(doc.getText(), fsPath, {
787
+ cache: getCacheForCompiler(compiler),
788
+ output: "source",
789
+ code: false,
790
+ translator
791
+ });
792
+ } catch (e) {
793
+ let match;
794
+ while (match = markoErrorRegExp.exec(e.message)) {
795
+ const [, fileName, rawLine, rawCol, msg] = match;
796
+ const line = (parseInt(rawLine, 10) || 1) - 1;
797
+ const col = (parseInt(rawCol, 10) || 1) - 1;
798
+ diagnostics.push(Diagnostic.create(Range4.create(line, col, line, col), msg, DiagnosticSeverity.Error, void 0, fileName));
799
+ }
800
+ }
801
+ return diagnostics;
802
+ }
803
+ function clearCaches(compiler) {
804
+ var _a;
805
+ (_a = cacheForCompiler.get(compiler)) == null ? void 0 : _a.clear();
806
+ compiler.taglib.clearCaches();
807
+ }
808
+ function getCacheForCompiler(compiler) {
809
+ let cache = cacheForCompiler.get(compiler);
810
+ if (!cache) {
811
+ cacheForCompiler.set(compiler, cache = /* @__PURE__ */ new Map());
812
+ }
813
+ return cache;
814
+ }
815
+ function displayMessage(type, msg) {
816
+ setImmediate(() => {
817
+ connection.sendNotification(`show${type}`, msg);
818
+ });
819
+ }
820
+ documents.listen(connection);
821
+ connection.listen();
822
+ //# sourceMappingURL=index.mjs.map