@marko/language-server 0.12.8 → 0.12.11

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.
package/dist/index.js CHANGED
@@ -575,7 +575,7 @@ function loadCompilerInfo(dir) {
575
575
  const rootDir = import_lasso_package_root.default.getRootDir(dir);
576
576
  const pkgPath = rootDir && import_resolve_from.default.silent(rootDir, "@marko/compiler/package.json");
577
577
  const pkg = pkgPath && require(pkgPath);
578
- const cache2 = /* @__PURE__ */ new Map();
578
+ const cache3 = /* @__PURE__ */ new Map();
579
579
  let translator = builtinTranslator;
580
580
  let compiler = builtinCompiler;
581
581
  if (pkg && /^5\./.test(pkg.version)) {
@@ -592,16 +592,16 @@ function loadCompilerInfo(dir) {
592
592
  }
593
593
  }
594
594
  return {
595
- cache: cache2,
595
+ cache: cache3,
596
596
  get lookup() {
597
- let lookup = cache2.get(lookupKey);
597
+ let lookup = cache3.get(lookupKey);
598
598
  if (lookup === void 0) {
599
599
  try {
600
600
  lookup = compiler.taglib.buildLookup(dir, translator);
601
601
  } catch {
602
602
  lookup = builtinInfo.lookup;
603
603
  }
604
- cache2.set(lookupKey, lookup);
604
+ cache3.set(lookupKey, lookup);
605
605
  }
606
606
  return lookup;
607
607
  },
@@ -625,10 +625,10 @@ function display(type, data) {
625
625
  }
626
626
 
627
627
  // src/service/index.ts
628
- var import_vscode_languageserver11 = require("vscode-languageserver");
628
+ var import_vscode_languageserver13 = require("vscode-languageserver");
629
629
 
630
630
  // src/service/marko/complete/index.ts
631
- var import_vscode_languageserver4 = require("vscode-languageserver");
631
+ var import_vscode_languageserver5 = require("vscode-languageserver");
632
632
 
633
633
  // src/service/marko/complete/Tag.ts
634
634
  var import_vscode_languageserver = require("vscode-languageserver");
@@ -842,18 +842,150 @@ function AttrName({
842
842
  return completions;
843
843
  }
844
844
 
845
+ // src/service/marko/complete/AttrValue.ts
846
+ var import_path3 = __toESM(require("path"));
847
+ var import_vscode_languageserver4 = require("vscode-languageserver");
848
+
849
+ // src/service/marko/util/is-document-link-attr.ts
850
+ var linkedAttrs = /* @__PURE__ */ new Map([
851
+ [
852
+ "src",
853
+ /* @__PURE__ */ new Set([
854
+ "audio",
855
+ "embed",
856
+ "iframe",
857
+ "img",
858
+ "input",
859
+ "script",
860
+ "source",
861
+ "track",
862
+ "video"
863
+ ])
864
+ ],
865
+ ["href", /* @__PURE__ */ new Set(["a", "area", "link"])],
866
+ ["data", /* @__PURE__ */ new Set(["object"])],
867
+ ["poster", /* @__PURE__ */ new Set(["video"])]
868
+ ]);
869
+ function isDocumentLinkAttr(doc, tag, attr) {
870
+ var _a, _b;
871
+ return tag.nameText && attr.type === 8 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 11 /* AttrValue */ && /^['"]$/.test(doc.getText()[attr.value.value.start]) && ((_b = linkedAttrs.get(doc.getText().slice(attr.name.start, attr.name.end))) == null ? void 0 : _b.has(tag.nameText)) || false;
872
+ }
873
+
874
+ // src/utils/file-system.ts
875
+ var import_promises = __toESM(require("fs/promises"));
876
+ var import_vscode_css_languageservice = require("vscode-css-languageservice");
877
+ var import_url = require("url");
878
+ var file_system_default = {
879
+ stat,
880
+ readDirectory
881
+ };
882
+ async function stat(uri) {
883
+ let type = import_vscode_css_languageservice.FileType.Unknown;
884
+ let ctime = -1;
885
+ let mtime = -1;
886
+ let size = -1;
887
+ try {
888
+ const stat2 = await import_promises.default.stat((0, import_url.fileURLToPath)(uri));
889
+ if (stat2.isDirectory())
890
+ type = import_vscode_css_languageservice.FileType.Directory;
891
+ else if (stat2.isFile())
892
+ type = import_vscode_css_languageservice.FileType.File;
893
+ ctime = stat2.ctimeMs;
894
+ mtime = stat2.mtimeMs;
895
+ size = stat2.size;
896
+ } catch {
897
+ }
898
+ return {
899
+ type,
900
+ ctime,
901
+ mtime,
902
+ size
903
+ };
904
+ }
905
+ async function readDirectory(uri) {
906
+ try {
907
+ const entries = await import_promises.default.readdir((0, import_url.fileURLToPath)(uri));
908
+ const base = uri.at(-1) === "/" ? uri : `${uri}/`;
909
+ return (await Promise.all(entries.map(async (entry) => [entry, (await stat(new URL(entry, base).toString())).type]))).filter(([, type]) => type !== import_vscode_css_languageservice.FileType.Unknown);
910
+ } catch {
911
+ return [];
912
+ }
913
+ }
914
+
915
+ // src/utils/resolve-url.ts
916
+ function resolveUrl(to, base) {
917
+ try {
918
+ const url = new URL(to, base);
919
+ if (url.protocol === "file:")
920
+ return url.toString();
921
+ } catch {
922
+ return void 0;
923
+ }
924
+ }
925
+
926
+ // src/service/marko/complete/AttrValue.ts
927
+ async function AttrValue({
928
+ document,
929
+ offset,
930
+ node,
931
+ parsed,
932
+ code
933
+ }) {
934
+ const attr = node.parent;
935
+ if (isDocumentLinkAttr(document, attr.parent, attr)) {
936
+ const start = node.value.start + 1;
937
+ if (code[start] !== ".")
938
+ return;
939
+ const end = node.value.end - 1;
940
+ const relativeOffset = offset - start;
941
+ const rawValue = parsed.read({
942
+ start,
943
+ end
944
+ });
945
+ const segmentStart = rawValue.lastIndexOf("/", relativeOffset);
946
+ if (segmentStart === -1)
947
+ return;
948
+ const req = rawValue.slice(0, segmentStart);
949
+ const uri = resolveUrl(req, document.uri);
950
+ if (uri) {
951
+ const result = [];
952
+ const curFile = req === "." ? import_path3.default.basename(document.uri) : void 0;
953
+ const replaceRange = import_vscode_languageserver4.Range.create(document.positionAt(start + segmentStart + 1), document.positionAt(start + rawValue.length));
954
+ for (const [entry, type] of await file_system_default.readDirectory(uri)) {
955
+ if (entry[0] !== "." && entry !== curFile) {
956
+ result.push(type === import_vscode_css_languageservice.FileType.Directory ? {
957
+ label: `${entry}/`,
958
+ kind: import_vscode_languageserver4.CompletionItemKind.Folder,
959
+ textEdit: import_vscode_languageserver4.TextEdit.replace(replaceRange, `${entry}/`),
960
+ command: {
961
+ title: "Suggest",
962
+ command: "editor.action.triggerSuggest"
963
+ }
964
+ } : {
965
+ label: entry,
966
+ kind: import_vscode_languageserver4.CompletionItemKind.File,
967
+ textEdit: import_vscode_languageserver4.TextEdit.replace(replaceRange, entry)
968
+ });
969
+ }
970
+ }
971
+ return result;
972
+ }
973
+ }
974
+ }
975
+
845
976
  // src/service/marko/complete/index.ts
846
977
  var handlers = {
847
978
  Tag,
848
979
  OpenTagName,
849
- AttrName
980
+ AttrName,
981
+ AttrValue
850
982
  };
851
983
  var doComplete = async (doc, params) => {
852
984
  var _a;
853
985
  const parsed = parse2(doc);
854
986
  const offset = doc.offsetAt(params.position);
855
987
  const node = parsed.nodeAt(offset);
856
- return import_vscode_languageserver4.CompletionList.create(await ((_a = handlers[NodeType[node.type]]) == null ? void 0 : _a.call(handlers, {
988
+ return import_vscode_languageserver5.CompletionList.create(await ((_a = handlers[NodeType[node.type]]) == null ? void 0 : _a.call(handlers, {
857
989
  document: doc,
858
990
  params,
859
991
  parsed,
@@ -865,15 +997,15 @@ var doComplete = async (doc, params) => {
865
997
  };
866
998
 
867
999
  // src/service/marko/validate.ts
868
- var import_vscode_languageserver5 = require("vscode-languageserver");
1000
+ var import_vscode_languageserver6 = require("vscode-languageserver");
869
1001
  var markoErrorRegExp = /^(.+?)(?:\((\d+)(?:\s*,\s*(\d+))?\))?: (.*)$/gm;
870
1002
  var doValidate = (doc) => {
871
1003
  const fsPath = getDocFile(doc);
872
1004
  const diagnostics = [];
873
- const { compiler, translator, cache: cache2 } = getCompilerInfo(doc);
1005
+ const { compiler, translator, cache: cache3 } = getCompilerInfo(doc);
874
1006
  try {
875
1007
  compiler.compileSync(doc.getText(), fsPath || "untitled.marko", {
876
- cache: cache2,
1008
+ cache: cache3,
877
1009
  translator,
878
1010
  code: false,
879
1011
  output: "source",
@@ -885,16 +1017,16 @@ var doValidate = (doc) => {
885
1017
  const [, fileName, rawLine, rawCol, msg] = match;
886
1018
  const line = (parseInt(rawLine, 10) || 1) - 1;
887
1019
  const col = (parseInt(rawCol, 10) || 1) - 1;
888
- 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));
1020
+ diagnostics.push(import_vscode_languageserver6.Diagnostic.create(import_vscode_languageserver6.Range.create(line, col, line, col), msg, import_vscode_languageserver6.DiagnosticSeverity.Error, void 0, fileName));
889
1021
  }
890
1022
  }
891
1023
  return diagnostics;
892
1024
  };
893
1025
 
894
1026
  // src/service/marko/definition/OpenTagName.ts
895
- var import_path3 = __toESM(require("path"));
1027
+ var import_path4 = __toESM(require("path"));
896
1028
  var import_vscode_uri4 = require("vscode-uri");
897
- var import_vscode_languageserver7 = require("vscode-languageserver");
1029
+ var import_vscode_languageserver8 = require("vscode-languageserver");
898
1030
 
899
1031
  // src/utils/regexp-builder.ts
900
1032
  function RegExpBuilder(strings, ...expressions) {
@@ -923,9 +1055,9 @@ function escape(val) {
923
1055
  // src/utils/utils.ts
924
1056
  var import_fs = __toESM(require("fs"));
925
1057
  var import_vscode_uri3 = require("vscode-uri");
926
- var import_vscode_languageserver6 = require("vscode-languageserver");
1058
+ var import_vscode_languageserver7 = require("vscode-languageserver");
927
1059
  var import_vscode_languageserver_textdocument = require("vscode-languageserver-textdocument");
928
- var START_OF_FILE = import_vscode_languageserver6.Range.create(import_vscode_languageserver6.Position.create(0, 0), import_vscode_languageserver6.Position.create(0, 0));
1060
+ var START_OF_FILE = import_vscode_languageserver7.Range.create(import_vscode_languageserver7.Position.create(0, 0), import_vscode_languageserver7.Position.create(0, 0));
929
1061
  function createTextDocument(filename) {
930
1062
  const uri = import_vscode_uri3.URI.file(filename).toString();
931
1063
  const content = import_fs.default.readFileSync(filename, "utf-8");
@@ -953,24 +1085,24 @@ function OpenTagName2({
953
1085
  return;
954
1086
  }
955
1087
  const tagEntryFile = tagDef.template || tagDef.renderer || tagDef.filePath;
956
- if (!import_path3.default.isAbsolute(tagEntryFile)) {
1088
+ if (!import_path4.default.isAbsolute(tagEntryFile)) {
957
1089
  return;
958
1090
  }
959
1091
  if (/\/marko(?:-tag)?\.json$/.test(tagEntryFile)) {
960
1092
  const tagDefDoc = createTextDocument(tagEntryFile);
961
1093
  const match = RegExpBuilder`/"(?:<${tag.nameText}>|${tag.nameText})"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
962
1094
  if (match && match.index) {
963
- range = import_vscode_languageserver7.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
1095
+ range = import_vscode_languageserver8.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
964
1096
  }
965
1097
  }
966
1098
  return [
967
- import_vscode_languageserver7.LocationLink.create(import_vscode_uri4.URI.file(tagEntryFile).toString(), range, range, parsed.locationAt(node))
1099
+ import_vscode_languageserver8.LocationLink.create(import_vscode_uri4.URI.file(tagEntryFile).toString(), range, range, parsed.locationAt(node))
968
1100
  ];
969
1101
  }
970
1102
 
971
1103
  // src/service/marko/definition/AttrName.ts
972
1104
  var import_vscode_uri5 = require("vscode-uri");
973
- var import_vscode_languageserver8 = require("vscode-languageserver");
1105
+ var import_vscode_languageserver9 = require("vscode-languageserver");
974
1106
  function AttrName2({
975
1107
  lookup,
976
1108
  parsed,
@@ -994,11 +1126,11 @@ function AttrName2({
994
1126
  const tagDefDoc = createTextDocument(attrEntryFile);
995
1127
  const match = RegExpBuilder`/"@${attrName}"\s*:\s*[^\r\n,]+/g`.exec(tagDefDoc.getText());
996
1128
  if (match && match.index) {
997
- range = import_vscode_languageserver8.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
1129
+ range = import_vscode_languageserver9.Range.create(tagDefDoc.positionAt(match.index), tagDefDoc.positionAt(match.index + match[0].length));
998
1130
  }
999
1131
  }
1000
1132
  return [
1001
- import_vscode_languageserver8.LocationLink.create(import_vscode_uri5.URI.file(attrEntryFile).toString(), range, range, parsed.locationAt(node))
1133
+ import_vscode_languageserver9.LocationLink.create(import_vscode_uri5.URI.file(attrEntryFile).toString(), range, range, parsed.locationAt(node))
1002
1134
  ];
1003
1135
  }
1004
1136
 
@@ -1023,14 +1155,83 @@ var findDefinition = async (doc, params) => {
1023
1155
  })) || [];
1024
1156
  };
1025
1157
 
1026
- // src/service/marko/format.ts
1027
- var import_vscode_languageserver9 = require("vscode-languageserver");
1158
+ // src/service/marko/document-links/extract.ts
1159
+ var import_vscode_languageserver10 = require("vscode-languageserver");
1028
1160
  var import_vscode_uri6 = require("vscode-uri");
1161
+ var importTagReg = /(['"])<((?:[^\1\\>]+|\\.)*)>?\1/g;
1162
+ function extractDocumentLinks(doc, parsed, lookup) {
1163
+ if (import_vscode_uri6.URI.parse(doc.uri).scheme === "untitled") {
1164
+ return [];
1165
+ }
1166
+ const links = [];
1167
+ const { program } = parsed;
1168
+ const code = doc.getText();
1169
+ const read = (range) => code.slice(range.start, range.end);
1170
+ const visit = (node) => {
1171
+ switch (node.type) {
1172
+ case 1 /* Tag */:
1173
+ if (node.attrs && node.nameText) {
1174
+ for (const attr of node.attrs) {
1175
+ if (isDocumentLinkAttr(doc, node, attr)) {
1176
+ links.push(import_vscode_languageserver10.DocumentLink.create({
1177
+ start: parsed.positionAt(attr.value.value.start),
1178
+ end: parsed.positionAt(attr.value.value.end)
1179
+ }, resolveUrl(read(attr.value.value).slice(1, -1), doc.uri)));
1180
+ }
1181
+ }
1182
+ }
1183
+ if (node.body) {
1184
+ for (const child of node.body) {
1185
+ visit(child);
1186
+ }
1187
+ }
1188
+ break;
1189
+ }
1190
+ };
1191
+ for (const item of program.static) {
1192
+ if (item.type === 20 /* Statement */ && code[item.start] === "i") {
1193
+ importTagReg.lastIndex = 0;
1194
+ const value = parsed.read(item);
1195
+ const match = importTagReg.exec(value);
1196
+ if (match) {
1197
+ const [{ length }, , tagName] = match;
1198
+ const tagDef = lookup.getTag(tagName);
1199
+ const fileForTag = tagDef && (tagDef.template || tagDef.renderer);
1200
+ if (fileForTag) {
1201
+ links.push(import_vscode_languageserver10.DocumentLink.create({
1202
+ start: parsed.positionAt(item.start + match.index),
1203
+ end: parsed.positionAt(item.start + match.index + length)
1204
+ }, fileForTag));
1205
+ }
1206
+ }
1207
+ }
1208
+ }
1209
+ for (const item of program.body) {
1210
+ visit(item);
1211
+ }
1212
+ return links;
1213
+ }
1214
+
1215
+ // src/service/marko/document-links/index.ts
1216
+ var cache = /* @__PURE__ */ new WeakMap();
1217
+ var findDocumentLinks = async (doc) => {
1218
+ const parsed = parse2(doc);
1219
+ let result = cache.get(parsed);
1220
+ if (!result) {
1221
+ result = extractDocumentLinks(doc, parsed, getCompilerInfo(doc).lookup);
1222
+ cache.set(parsed, result);
1223
+ }
1224
+ return result;
1225
+ };
1226
+
1227
+ // src/service/marko/format.ts
1228
+ var import_vscode_languageserver11 = require("vscode-languageserver");
1229
+ var import_vscode_uri7 = require("vscode-uri");
1029
1230
  var prettier = __toESM(require("prettier"));
1030
1231
  var markoPrettier = __toESM(require("prettier-plugin-marko"));
1031
1232
  var format2 = async (doc, params, cancel) => {
1032
1233
  try {
1033
- const { fsPath, scheme } = import_vscode_uri6.URI.parse(doc.uri);
1234
+ const { fsPath, scheme } = import_vscode_uri7.URI.parse(doc.uri);
1034
1235
  const text = doc.getText();
1035
1236
  const options = {
1036
1237
  parser: "marko",
@@ -1045,7 +1246,7 @@ var format2 = async (doc, params, cancel) => {
1045
1246
  if (cancel.isCancellationRequested)
1046
1247
  return;
1047
1248
  return [
1048
- import_vscode_languageserver9.TextEdit.replace(import_vscode_languageserver9.Range.create(doc.positionAt(0), doc.positionAt(text.length)), prettier.format(text, options))
1249
+ import_vscode_languageserver11.TextEdit.replace(import_vscode_languageserver11.Range.create(doc.positionAt(0), doc.positionAt(text.length)), prettier.format(text, options))
1049
1250
  ];
1050
1251
  } catch (e) {
1051
1252
  displayError(e);
@@ -1057,12 +1258,13 @@ var marko_default = {
1057
1258
  doComplete,
1058
1259
  doValidate,
1059
1260
  findDefinition,
1261
+ findDocumentLinks,
1060
1262
  format: format2
1061
1263
  };
1062
1264
 
1063
1265
  // src/service/stylesheet/index.ts
1064
- var import_vscode_languageserver10 = require("vscode-languageserver");
1065
- var import_vscode_css_languageservice = require("vscode-css-languageservice");
1266
+ var import_vscode_languageserver12 = require("vscode-languageserver");
1267
+ var import_vscode_css_languageservice2 = require("vscode-css-languageservice");
1066
1268
  var import_vscode_languageserver_textdocument2 = require("vscode-languageserver-textdocument");
1067
1269
 
1068
1270
  // src/utils/extractor.ts
@@ -1201,7 +1403,7 @@ function extractStyleSheets(code, program, lookup) {
1201
1403
  for (const attr of node.attrs) {
1202
1404
  if (attr.type === 8 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 11 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])) {
1203
1405
  const name = read(attr.name);
1204
- if (name === "#style" || name === "style" && lookup && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
1406
+ if (name === "#style" || name === "style" && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
1205
1407
  getExtractor("css").write`:root{${{
1206
1408
  start: attr.value.value.start + 1,
1207
1409
  end: attr.value.value.end - 1
@@ -1223,13 +1425,17 @@ function extractStyleSheets(code, program, lookup) {
1223
1425
  }
1224
1426
 
1225
1427
  // src/service/stylesheet/index.ts
1226
- var cache = /* @__PURE__ */ new WeakMap();
1428
+ var cache2 = /* @__PURE__ */ new WeakMap();
1227
1429
  var services = {
1228
- css: import_vscode_css_languageservice.getCSSLanguageService,
1229
- less: import_vscode_css_languageservice.getLESSLanguageService,
1230
- scss: import_vscode_css_languageservice.getSCSSLanguageService
1430
+ css: import_vscode_css_languageservice2.getCSSLanguageService,
1431
+ less: import_vscode_css_languageservice2.getLESSLanguageService,
1432
+ scss: import_vscode_css_languageservice2.getSCSSLanguageService
1231
1433
  };
1434
+ var clientCapabilities;
1232
1435
  var StyleSheetService = {
1436
+ initialize(params) {
1437
+ clientCapabilities = params.capabilities;
1438
+ },
1233
1439
  async doComplete(doc, params) {
1234
1440
  const infoByExt = getStyleSheetInfo(doc);
1235
1441
  const sourceOffset = doc.offsetAt(params.position);
@@ -1239,28 +1445,31 @@ var StyleSheetService = {
1239
1445
  if (generatedOffset === void 0)
1240
1446
  continue;
1241
1447
  const { service: service2, virtualDoc } = info;
1242
- const result = service2.doComplete(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed);
1243
- for (const item of result.items) {
1244
- if (item.additionalTextEdits) {
1245
- for (const textEdit2 of item.additionalTextEdits) {
1246
- updateTextEdit(doc, info, textEdit2);
1448
+ const result = await service2.doComplete2(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed, { resolveReference: resolveUrl });
1449
+ if (result.itemDefaults) {
1450
+ const { editRange } = result.itemDefaults;
1451
+ if (editRange) {
1452
+ if ("start" in editRange) {
1453
+ result.itemDefaults.editRange = getSourceRange(doc, info, editRange);
1454
+ } else {
1455
+ editRange.insert = getSourceRange(doc, info, editRange.insert);
1456
+ editRange.replace = getSourceRange(doc, info, editRange.replace);
1247
1457
  }
1248
1458
  }
1249
- const { textEdit } = item;
1250
- if (textEdit) {
1251
- if (textEdit.range) {
1252
- updateTextEdit(doc, info, textEdit);
1253
- }
1254
- if (textEdit.insert) {
1255
- updateInsertReplaceEdit(doc, info, textEdit);
1256
- }
1459
+ }
1460
+ for (const item of result.items) {
1461
+ if (item.textEdit) {
1462
+ item.textEdit = getSourceInsertReplaceEdit(doc, info, item.textEdit);
1463
+ }
1464
+ if (item.additionalTextEdits) {
1465
+ item.additionalTextEdits = getSourceEdits(doc, info, item.additionalTextEdits);
1257
1466
  }
1258
1467
  }
1259
1468
  return result;
1260
1469
  }
1261
- return import_vscode_languageserver10.CompletionList.create([], true);
1470
+ return import_vscode_languageserver12.CompletionList.create([], true);
1262
1471
  },
1263
- async findDefinition(doc, params) {
1472
+ findDefinition(doc, params) {
1264
1473
  const infoByExt = getStyleSheetInfo(doc);
1265
1474
  const sourceOffset = doc.offsetAt(params.position);
1266
1475
  for (const ext in infoByExt) {
@@ -1270,29 +1479,101 @@ var StyleSheetService = {
1270
1479
  continue;
1271
1480
  const { service: service2, virtualDoc } = info;
1272
1481
  const result = service2.findDefinition(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed);
1273
- if (result && updateRange(doc, info, result.range)) {
1274
- return result;
1482
+ if (result) {
1483
+ const range = getSourceRange(doc, info, result.range);
1484
+ if (range) {
1485
+ return {
1486
+ range,
1487
+ uri: doc.uri
1488
+ };
1489
+ }
1275
1490
  }
1276
1491
  break;
1277
1492
  }
1278
1493
  },
1279
- async findDocumentColors(doc) {
1494
+ findReferences(doc, params) {
1495
+ const infoByExt = getStyleSheetInfo(doc);
1496
+ const sourceOffset = doc.offsetAt(params.position);
1497
+ for (const ext in infoByExt) {
1498
+ const info = infoByExt[ext];
1499
+ const generatedOffset = info.generatedOffsetAt(sourceOffset);
1500
+ if (generatedOffset === void 0)
1501
+ continue;
1502
+ const { service: service2, virtualDoc } = info;
1503
+ const result = [];
1504
+ for (const location of service2.findReferences(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed)) {
1505
+ const range = getSourceRange(doc, info, location.range);
1506
+ if (range) {
1507
+ result.push({
1508
+ range,
1509
+ uri: location.uri
1510
+ });
1511
+ }
1512
+ }
1513
+ return result.length ? result : void 0;
1514
+ }
1515
+ },
1516
+ async findDocumentLinks(doc) {
1280
1517
  const infoByExt = getStyleSheetInfo(doc);
1281
1518
  const result = [];
1282
1519
  for (const ext in infoByExt) {
1283
1520
  const info = infoByExt[ext];
1284
1521
  const { service: service2, virtualDoc } = info;
1285
- for (const colorInfo of service2.findDocumentColors(virtualDoc, info.parsed)) {
1286
- if (updateRange(doc, info, colorInfo.range)) {
1287
- result.push(colorInfo);
1522
+ for (const link of await service2.findDocumentLinks2(virtualDoc, info.parsed, { resolveReference: resolveUrl })) {
1523
+ const range = getSourceRange(doc, info, link.range);
1524
+ if (range) {
1525
+ result.push({
1526
+ range,
1527
+ target: link.target,
1528
+ tooltip: link.tooltip,
1529
+ data: link.data
1530
+ });
1288
1531
  }
1289
1532
  }
1290
1533
  }
1291
- if (result.length) {
1292
- return result;
1534
+ return result.length ? result : void 0;
1535
+ },
1536
+ findDocumentHighlights(doc, params) {
1537
+ const infoByExt = getStyleSheetInfo(doc);
1538
+ const sourceOffset = doc.offsetAt(params.position);
1539
+ for (const ext in infoByExt) {
1540
+ const info = infoByExt[ext];
1541
+ const generatedOffset = info.generatedOffsetAt(sourceOffset);
1542
+ if (generatedOffset === void 0)
1543
+ continue;
1544
+ const { service: service2, virtualDoc } = info;
1545
+ const result = [];
1546
+ for (const highlight of service2.findDocumentHighlights(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed)) {
1547
+ const range = getSourceRange(doc, info, highlight.range);
1548
+ if (range) {
1549
+ result.push({
1550
+ range,
1551
+ kind: highlight.kind
1552
+ });
1553
+ }
1554
+ }
1555
+ return result.length ? result : void 0;
1556
+ }
1557
+ },
1558
+ findDocumentColors(doc) {
1559
+ const infoByExt = getStyleSheetInfo(doc);
1560
+ const result = [];
1561
+ for (const ext in infoByExt) {
1562
+ const info = infoByExt[ext];
1563
+ const { service: service2, virtualDoc } = info;
1564
+ for (const colorInfo of service2.findDocumentColors(virtualDoc, info.parsed)) {
1565
+ const range = getSourceRange(doc, info, colorInfo.range);
1566
+ if (range) {
1567
+ result.push({
1568
+ range,
1569
+ color: colorInfo.color
1570
+ });
1571
+ }
1572
+ }
1293
1573
  }
1574
+ return result.length ? result : void 0;
1294
1575
  },
1295
- async getColorPresentations(doc, params) {
1576
+ getColorPresentations(doc, params) {
1296
1577
  const infoByExt = getStyleSheetInfo(doc);
1297
1578
  const sourceOffset = doc.offsetAt(params.range.start);
1298
1579
  for (const ext in infoByExt) {
@@ -1304,21 +1585,22 @@ var StyleSheetService = {
1304
1585
  if (generatedOffsetEnd === void 0)
1305
1586
  continue;
1306
1587
  const { service: service2, virtualDoc } = info;
1307
- const result = service2.getColorPresentations(virtualDoc, info.parsed, params.color, import_vscode_languageserver10.Range.create(virtualDoc.positionAt(generatedOffsetStart), virtualDoc.positionAt(generatedOffsetEnd)));
1308
- for (const colorPresentation of result) {
1309
- if (colorPresentation.textEdit) {
1310
- updateTextEdit(doc, info, colorPresentation.textEdit);
1311
- }
1312
- if (colorPresentation.additionalTextEdits) {
1313
- for (const textEdit of colorPresentation.additionalTextEdits) {
1314
- updateTextEdit(doc, info, textEdit);
1315
- }
1588
+ const result = [];
1589
+ for (const colorPresentation of service2.getColorPresentations(virtualDoc, info.parsed, params.color, import_vscode_languageserver12.Range.create(virtualDoc.positionAt(generatedOffsetStart), virtualDoc.positionAt(generatedOffsetEnd)))) {
1590
+ const textEdit = colorPresentation.textEdit && getSourceEdit(doc, info, colorPresentation.textEdit);
1591
+ const additionalTextEdits = colorPresentation.additionalTextEdits && getSourceEdits(doc, info, colorPresentation.additionalTextEdits);
1592
+ if (textEdit || additionalTextEdits) {
1593
+ result.push({
1594
+ label: colorPresentation.label,
1595
+ textEdit,
1596
+ additionalTextEdits
1597
+ });
1316
1598
  }
1317
1599
  }
1318
- return result;
1600
+ return result.length ? result : void 0;
1319
1601
  }
1320
1602
  },
1321
- async doHover(doc, params) {
1603
+ doHover(doc, params) {
1322
1604
  const infoByExt = getStyleSheetInfo(doc);
1323
1605
  const sourceOffset = doc.offsetAt(params.position);
1324
1606
  for (const ext in infoByExt) {
@@ -1328,8 +1610,18 @@ var StyleSheetService = {
1328
1610
  continue;
1329
1611
  const { service: service2, virtualDoc } = info;
1330
1612
  const result = service2.doHover(virtualDoc, virtualDoc.positionAt(generatedOffset), info.parsed);
1331
- if (result && (!result.range || updateRange(doc, info, result.range))) {
1332
- return result;
1613
+ if (result) {
1614
+ if (result.range) {
1615
+ const range = getSourceRange(doc, info, result.range);
1616
+ if (range) {
1617
+ return {
1618
+ range,
1619
+ contents: result.contents
1620
+ };
1621
+ }
1622
+ } else {
1623
+ return result;
1624
+ }
1333
1625
  }
1334
1626
  }
1335
1627
  },
@@ -1346,19 +1638,15 @@ var StyleSheetService = {
1346
1638
  if (result.changes) {
1347
1639
  for (const uri in result.changes) {
1348
1640
  if (uri === doc.uri) {
1349
- for (const textEdit of result.changes[uri]) {
1350
- updateTextEdit(doc, info, textEdit);
1351
- }
1641
+ result.changes[uri] = getSourceEdits(doc, info, result.changes[uri]) || [];
1352
1642
  }
1353
1643
  }
1354
1644
  }
1355
1645
  if (result.documentChanges) {
1356
1646
  for (const change of result.documentChanges) {
1357
- if (import_vscode_languageserver10.TextDocumentEdit.is(change)) {
1647
+ if (import_vscode_languageserver12.TextDocumentEdit.is(change)) {
1358
1648
  if (change.textDocument.uri === doc.uri) {
1359
- for (const textEdit of change.edits) {
1360
- updateTextEdit(doc, info, textEdit);
1361
- }
1649
+ change.edits = getSourceEdits(doc, info, change.edits) || [];
1362
1650
  }
1363
1651
  }
1364
1652
  }
@@ -1366,7 +1654,7 @@ var StyleSheetService = {
1366
1654
  return result;
1367
1655
  }
1368
1656
  },
1369
- async doCodeActions(doc, params) {
1657
+ doCodeActions(doc, params) {
1370
1658
  var _a;
1371
1659
  const infoByExt = getStyleSheetInfo(doc);
1372
1660
  const sourceOffset = doc.offsetAt(params.range.start);
@@ -1379,65 +1667,100 @@ var StyleSheetService = {
1379
1667
  if (generatedOffsetEnd === void 0)
1380
1668
  continue;
1381
1669
  const { service: service2, virtualDoc } = info;
1382
- const result = service2.doCodeActions(virtualDoc, import_vscode_languageserver10.Range.create(virtualDoc.positionAt(generatedOffsetStart), virtualDoc.positionAt(generatedOffsetEnd)), params.context, info.parsed);
1383
- if (result) {
1384
- for (const command of result) {
1385
- const edits = (_a = command.arguments) == null ? void 0 : _a[2];
1386
- if (edits) {
1387
- for (const textEdit of edits) {
1388
- updateTextEdit(doc, info, textEdit);
1389
- }
1390
- }
1670
+ const result = service2.doCodeActions(virtualDoc, import_vscode_languageserver12.Range.create(virtualDoc.positionAt(generatedOffsetStart), virtualDoc.positionAt(generatedOffsetEnd)), params.context, info.parsed);
1671
+ for (const command of result) {
1672
+ const edits = (_a = command.arguments) == null ? void 0 : _a[2];
1673
+ if (edits && Array.isArray(edits) && isTextEdit(edits[0])) {
1674
+ command.arguments[2] = getSourceEdits(doc, info, edits);
1391
1675
  }
1392
- return result;
1393
1676
  }
1677
+ return result;
1394
1678
  }
1395
1679
  },
1396
- async doValidate(doc) {
1680
+ doValidate(doc) {
1397
1681
  const infoByExt = getStyleSheetInfo(doc);
1398
1682
  const result = [];
1399
1683
  for (const ext in infoByExt) {
1400
1684
  const info = infoByExt[ext];
1401
1685
  for (const diag of info.service.doValidation(info.virtualDoc, info.parsed)) {
1402
- if (updateRange(doc, info, diag.range)) {
1686
+ const range = getSourceRange(doc, info, diag.range);
1687
+ if (range) {
1688
+ diag.range = range;
1403
1689
  result.push(diag);
1404
1690
  }
1405
1691
  }
1406
1692
  }
1407
- return result;
1693
+ return result.length ? result : void 0;
1408
1694
  }
1409
1695
  };
1410
- function updateTextEdit(doc, info, textEdit) {
1411
- if (!updateRange(doc, info, textEdit.range)) {
1412
- textEdit.newText = "";
1413
- textEdit.range = START_OF_FILE;
1696
+ function getSourceEdits(doc, info, edits) {
1697
+ const result = [];
1698
+ for (const edit of edits) {
1699
+ const sourceEdit = getSourceEdit(doc, info, edit);
1700
+ if (sourceEdit) {
1701
+ result.push(sourceEdit);
1702
+ }
1414
1703
  }
1704
+ return result.length ? result : void 0;
1415
1705
  }
1416
- function updateInsertReplaceEdit(doc, info, insertReplaceEdit) {
1417
- if (!updateRange(doc, info, insertReplaceEdit.insert)) {
1418
- insertReplaceEdit.newText = "";
1419
- insertReplaceEdit.insert = START_OF_FILE;
1706
+ function getSourceEdit(doc, info, textEdit) {
1707
+ const range = getSourceRange(doc, info, textEdit.range);
1708
+ if (range) {
1709
+ return {
1710
+ newText: textEdit.newText,
1711
+ range
1712
+ };
1420
1713
  }
1421
1714
  }
1422
- function updateRange(doc, info, range) {
1715
+ function getSourceInsertReplaceEdit(doc, info, textEdit) {
1716
+ if (isTextEdit(textEdit)) {
1717
+ return getSourceEdit(doc, info, textEdit);
1718
+ } else if (textEdit.replace) {
1719
+ const range = getSourceRange(doc, info, textEdit.replace);
1720
+ if (range) {
1721
+ return {
1722
+ newText: textEdit.newText,
1723
+ replace: range
1724
+ };
1725
+ }
1726
+ } else {
1727
+ const range = getSourceRange(doc, info, textEdit.insert);
1728
+ if (range) {
1729
+ return {
1730
+ newText: textEdit.newText,
1731
+ insert: range
1732
+ };
1733
+ }
1734
+ }
1735
+ }
1736
+ function getSourceRange(doc, info, range) {
1423
1737
  const start = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.start));
1424
- const end = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.end));
1425
- if (start !== void 0 || end !== void 0) {
1426
- range.start = doc.positionAt(start ?? end);
1427
- range.end = doc.positionAt(end ?? start);
1428
- return true;
1738
+ if (start === void 0)
1739
+ return;
1740
+ let end = start;
1741
+ if (range.start.line !== range.end.line || range.start.character !== range.end.character) {
1742
+ end = info.sourceOffsetAt(info.virtualDoc.offsetAt(range.end));
1743
+ if (end === void 0)
1744
+ return;
1429
1745
  }
1430
- return false;
1746
+ const pos = doc.positionAt(start);
1747
+ return {
1748
+ start: pos,
1749
+ end: start === end ? pos : doc.positionAt(end)
1750
+ };
1431
1751
  }
1432
1752
  function getStyleSheetInfo(doc) {
1433
1753
  var _a;
1434
1754
  const parsed = parse2(doc);
1435
- let cached = cache.get(parsed);
1755
+ let cached = cache2.get(parsed);
1436
1756
  if (!cached) {
1437
1757
  const results = extractStyleSheets(doc.getText(), parsed.program, getCompilerInfo(doc).lookup);
1438
1758
  cached = {};
1439
1759
  for (const ext in results) {
1440
- const service2 = (_a = services[ext]) == null ? void 0 : _a.call(services);
1760
+ const service2 = (_a = services[ext]) == null ? void 0 : _a.call(services, {
1761
+ fileSystemProvider: file_system_default,
1762
+ clientCapabilities
1763
+ });
1441
1764
  if (!service2)
1442
1765
  continue;
1443
1766
  const { generated, sourceOffsetAt, generatedOffsetAt } = results[ext];
@@ -1450,16 +1773,25 @@ function getStyleSheetInfo(doc) {
1450
1773
  parsed: service2.parseStylesheet(virtualDoc)
1451
1774
  };
1452
1775
  }
1453
- cache.set(parsed, cached);
1776
+ cache2.set(parsed, cached);
1454
1777
  }
1455
1778
  return cached;
1456
1779
  }
1780
+ function isTextEdit(edit) {
1781
+ return edit.range !== void 0;
1782
+ }
1457
1783
 
1458
1784
  // src/service/index.ts
1459
1785
  var plugins = [marko_default, StyleSheetService];
1460
1786
  var service = {
1787
+ async initialize(params) {
1788
+ await Promise.all(plugins.map((plugin) => {
1789
+ var _a;
1790
+ return (_a = plugin.initialize) == null ? void 0 : _a.call(plugin, params);
1791
+ }));
1792
+ },
1461
1793
  async doComplete(doc, params, cancel) {
1462
- const result = import_vscode_languageserver11.CompletionList.create([], false);
1794
+ const result = import_vscode_languageserver13.CompletionList.create([], false);
1463
1795
  try {
1464
1796
  const requests = plugins.map((plugin) => {
1465
1797
  var _a;
@@ -1510,6 +1842,78 @@ var service = {
1510
1842
  }
1511
1843
  return result;
1512
1844
  },
1845
+ async findReferences(doc, params, cancel) {
1846
+ let result;
1847
+ try {
1848
+ const requests = plugins.map((plugin) => {
1849
+ var _a;
1850
+ return (_a = plugin.findReferences) == null ? void 0 : _a.call(plugin, doc, params, cancel);
1851
+ });
1852
+ for (const pending of requests) {
1853
+ const cur = await pending;
1854
+ if (cancel.isCancellationRequested)
1855
+ return;
1856
+ if (cur) {
1857
+ if (result) {
1858
+ result.push(...cur);
1859
+ } else {
1860
+ result = cur;
1861
+ }
1862
+ }
1863
+ }
1864
+ } catch (err) {
1865
+ displayError(err);
1866
+ }
1867
+ return result;
1868
+ },
1869
+ async findDocumentLinks(doc, params, cancel) {
1870
+ let result;
1871
+ try {
1872
+ const requests = plugins.map((plugin) => {
1873
+ var _a;
1874
+ return (_a = plugin.findDocumentLinks) == null ? void 0 : _a.call(plugin, doc, params, cancel);
1875
+ });
1876
+ for (const pending of requests) {
1877
+ const cur = await pending;
1878
+ if (cancel.isCancellationRequested)
1879
+ return;
1880
+ if (cur) {
1881
+ if (result) {
1882
+ result.push(...cur);
1883
+ } else {
1884
+ result = cur;
1885
+ }
1886
+ }
1887
+ }
1888
+ } catch (err) {
1889
+ displayError(err);
1890
+ }
1891
+ return result;
1892
+ },
1893
+ async findDocumentHighlights(doc, params, cancel) {
1894
+ let result;
1895
+ try {
1896
+ const requests = plugins.map((plugin) => {
1897
+ var _a;
1898
+ return (_a = plugin.findDocumentHighlights) == null ? void 0 : _a.call(plugin, doc, params, cancel);
1899
+ });
1900
+ for (const pending of requests) {
1901
+ const cur = await pending;
1902
+ if (cancel.isCancellationRequested)
1903
+ return;
1904
+ if (cur) {
1905
+ if (result) {
1906
+ result.push(...cur);
1907
+ } else {
1908
+ result = cur;
1909
+ }
1910
+ }
1911
+ }
1912
+ } catch (err) {
1913
+ displayError(err);
1914
+ }
1915
+ return result;
1916
+ },
1513
1917
  async findDocumentColors(doc, params, cancel) {
1514
1918
  let result;
1515
1919
  try {
@@ -1683,8 +2087,9 @@ console.error = (...args) => {
1683
2087
  };
1684
2088
  process.on("uncaughtException", console.error);
1685
2089
  process.on("unhandledRejection", console.error);
1686
- connection2.onInitialize(() => {
2090
+ connection2.onInitialize(async (params) => {
1687
2091
  setup(connection2);
2092
+ await service.initialize(params);
1688
2093
  return {
1689
2094
  capabilities: {
1690
2095
  textDocumentSync: import_node.TextDocumentSyncKind.Incremental,
@@ -1693,7 +2098,10 @@ connection2.onInitialize(() => {
1693
2098
  hoverProvider: true,
1694
2099
  renameProvider: true,
1695
2100
  codeActionProvider: true,
2101
+ referencesProvider: true,
2102
+ documentLinkProvider: { resolveProvider: false },
1696
2103
  colorProvider: true,
2104
+ documentHighlightProvider: true,
1697
2105
  completionProvider: {
1698
2106
  triggerCharacters: [
1699
2107
  ".",
@@ -1733,6 +2141,15 @@ connection2.onCompletion(async (params, cancel) => {
1733
2141
  connection2.onDefinition(async (params, cancel) => {
1734
2142
  return await service.findDefinition(documents.get(params.textDocument.uri), params, cancel) || null;
1735
2143
  });
2144
+ connection2.onReferences(async (params, cancel) => {
2145
+ return await service.findReferences(documents.get(params.textDocument.uri), params, cancel) || null;
2146
+ });
2147
+ connection2.onDocumentLinks(async (params, cancel) => {
2148
+ return await service.findDocumentLinks(documents.get(params.textDocument.uri), params, cancel) || null;
2149
+ });
2150
+ connection2.onDocumentHighlight(async (params, cancel) => {
2151
+ return await service.findDocumentHighlights(documents.get(params.textDocument.uri), params, cancel) || null;
2152
+ });
1736
2153
  connection2.onDocumentColor(async (params, cancel) => {
1737
2154
  return await service.findDocumentColors(documents.get(params.textDocument.uri), params, cancel) || null;
1738
2155
  });