@rohal12/spindle-lsp 0.14.1 → 0.14.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.
package/dist/bin.js CHANGED
@@ -16694,12 +16694,13 @@ function parsePassageHeader(line, lineNumber) {
16694
16694
  if (!name) return null;
16695
16695
  const escapedName = name.replace(/\\./g, "ec");
16696
16696
  if (/[\[\]\{\}]/.test(escapedName)) return null;
16697
- const tagsStr = rawTags.trim();
16697
+ const tagsStr = line.slice(nameEnd, nameEnd + rawTags.length).trim();
16698
16698
  let tags = [];
16699
16699
  if (tagsStr) {
16700
- const inner = tagsStr.substring(1, tagsStr.length - 1).trim();
16700
+ const inner = tagsStr.substring(1, tagsStr.length - 1);
16701
16701
  if (/[\[\]\{\}]/.test(inner.replace(/\\./g, "ec"))) return null;
16702
- tags = inner ? inner.split(/\s+/) : [];
16702
+ const decoded = inner.replace(/\\(.)/g, "$1").trim();
16703
+ tags = decoded ? decoded.split(/\s+/) : [];
16703
16704
  }
16704
16705
  let meta3;
16705
16706
  const metaStr = rawMeta.trim();
@@ -16742,7 +16743,7 @@ var passageHeaderRegex, SPECIAL_PASSAGES, CODE_PASSAGE_TAGS, RESERVED_PASSAGE_NA
16742
16743
  var init_passage_parser = __esm({
16743
16744
  "src/core/parsing/passage-parser.ts"() {
16744
16745
  "use strict";
16745
- passageHeaderRegex = /^(::\s+)(.*?)(\[.*?\]\s*)?(\{.*?\}\s*)?\r?$/;
16746
+ passageHeaderRegex = /^(::\s*)(.*?)(\[.*?\]\s*)?(\{.*?\}\s*)?\r?$/;
16746
16747
  SPECIAL_PASSAGES = /* @__PURE__ */ new Set([
16747
16748
  "StoryVariables",
16748
16749
  "StoryInit",
@@ -24365,6 +24366,12 @@ var init_config_loader = __esm({
24365
24366
  });
24366
24367
 
24367
24368
  // src/core/workspace/macro-registry.ts
24369
+ function applySupplement(info, entry) {
24370
+ for (const field of ["description", "parameters", "parameterDocs", "children", "parents", "skipArgs"]) {
24371
+ if (entry[field] !== void 0) Object.assign(info, { [field]: entry[field] });
24372
+ }
24373
+ if (entry.container !== void 0) info.block = entry.container;
24374
+ }
24368
24375
  var MacroRegistry;
24369
24376
  var init_macro_registry2 = __esm({
24370
24377
  "src/core/workspace/macro-registry.ts"() {
@@ -24537,30 +24544,20 @@ var init_macro_registry2 = __esm({
24537
24544
  const found = this.discovered.get(key);
24538
24545
  if (!found) return base;
24539
24546
  const info = {
24540
- ...base,
24541
- name: base?.name ?? found.name,
24542
- block: found.block ?? base?.block ?? false,
24543
- subMacros: found.subMacros?.length ? found.subMacros : base?.subMacros ?? [],
24547
+ name: found.name,
24548
+ block: found.block ?? false,
24549
+ subMacros: found.subMacros ?? [],
24544
24550
  source: "user",
24545
- storeVar: found.storeVar ?? base?.storeVar,
24546
- interpolate: found.interpolate ?? base?.interpolate,
24547
- merged: found.merged ?? base?.merged,
24548
- description: found.description ?? base?.description,
24551
+ storeVar: found.storeVar,
24552
+ interpolate: found.interpolate,
24553
+ merged: found.merged,
24554
+ description: found.description,
24549
24555
  // A definition replaces the macro it names, parameters included
24550
24556
  parameterDefs: found.parameterDefs,
24551
- // A discovered sub-macro may also belong to other (e.g. built-in) parents
24552
- parents: found.parents ? [.../* @__PURE__ */ new Set([...base?.parents ?? [], ...found.parents])] : base?.parents
24557
+ parents: found.parents
24553
24558
  };
24554
24559
  const config2 = this.configEntries.get(key);
24555
- if (config2) {
24556
- if (config2.description !== void 0) info.description = config2.description;
24557
- if (config2.parameters !== void 0) info.parameters = config2.parameters;
24558
- if (config2.parameterDocs !== void 0) info.parameterDocs = config2.parameterDocs;
24559
- if (config2.children !== void 0) info.children = config2.children;
24560
- if (config2.parents !== void 0) info.parents = config2.parents;
24561
- if (config2.skipArgs !== void 0) info.skipArgs = config2.skipArgs;
24562
- if (config2.container !== void 0) info.block = config2.container;
24563
- }
24560
+ if (config2) applySupplement(info, config2);
24564
24561
  return info;
24565
24562
  }
24566
24563
  /** Merge a set of supplement/config entries into the registry. */
@@ -24569,13 +24566,7 @@ var init_macro_registry2 = __esm({
24569
24566
  const key = rawKey.toLowerCase();
24570
24567
  const existing = this.macros.get(key);
24571
24568
  if (existing) {
24572
- if (entry.description !== void 0) existing.description = entry.description;
24573
- if (entry.parameters !== void 0) existing.parameters = entry.parameters;
24574
- if (entry.parameterDocs !== void 0) existing.parameterDocs = entry.parameterDocs;
24575
- if (entry.children !== void 0) existing.children = entry.children;
24576
- if (entry.parents !== void 0) existing.parents = entry.parents;
24577
- if (entry.skipArgs !== void 0) existing.skipArgs = entry.skipArgs;
24578
- if (entry.container !== void 0) existing.block = entry.container;
24569
+ applySupplement(existing, entry);
24579
24570
  } else {
24580
24571
  this.macros.set(key, {
24581
24572
  name: entry.name ?? rawKey,
@@ -24970,6 +24961,27 @@ var init_variable_tracker = __esm({
24970
24961
  getUsages(name) {
24971
24962
  return usagesOf(this.usagesByUri, name);
24972
24963
  }
24964
+ /** The executable usage or declaration containing the cursor, in source coordinates. */
24965
+ referenceAt(uri, position) {
24966
+ const contains = (range) => (position.line > range.start.line || position.line === range.start.line && position.character >= range.start.character) && (position.line < range.end.line || position.line === range.end.line && position.character <= range.end.character);
24967
+ let atEnd = null;
24968
+ for (const [sigil, usages, declarations] of [
24969
+ ["$", this.usagesByUri.get(uri), this.variables.declared],
24970
+ ["%", this.transientUsagesByUri.get(uri), this.transients.declared]
24971
+ ]) {
24972
+ const candidates = (usages ?? []).map((u) => ({ name: u.baseName, range: u.range }));
24973
+ for (const [name, declaration] of declarations) {
24974
+ if (declaration.declarationUri === uri && declaration.declarationRange) candidates.push({ name, range: declaration.declarationRange });
24975
+ }
24976
+ for (const candidate of candidates) {
24977
+ if (!contains(candidate.range)) continue;
24978
+ const symbol2 = { sigil, ...candidate };
24979
+ if (position.line !== candidate.range.end.line || position.character < candidate.range.end.character) return symbol2;
24980
+ atEnd ??= symbol2;
24981
+ }
24982
+ }
24983
+ return atEnd;
24984
+ }
24973
24985
  /** Whether a StoryVariables passage has been parsed. */
24974
24986
  hasStoryVariables() {
24975
24987
  return this.variables.present;
@@ -26205,6 +26217,36 @@ var init_diagnostic_codes = __esm({
26205
26217
  }
26206
26218
  });
26207
26219
 
26220
+ // src/core/markup/source-view.ts
26221
+ function viewIndex(view, offset2) {
26222
+ if (!view.sourceOffsets) return offset2 - view.offset;
26223
+ let low = 0;
26224
+ let high = view.sourceOffsets.length - 1;
26225
+ while (low < high) {
26226
+ const mid = Math.ceil((low + high) / 2);
26227
+ if (view.sourceOffsets[mid] <= offset2) low = mid;
26228
+ else high = mid - 1;
26229
+ }
26230
+ return low;
26231
+ }
26232
+ function textAt(passage, start, end) {
26233
+ return passage.pieces.filter((piece) => piece.kind === "text" && piece.offset <= start && pieceOffset(piece, piece.text.length) >= end).at(-1);
26234
+ }
26235
+ function sourceView(passage, start, end) {
26236
+ const owner = passage.pieces.filter((piece) => {
26237
+ const value = piece.kind === "text" ? piece.text : piece.kind === "code" ? piece.code : void 0;
26238
+ return value !== void 0 && piece.offset <= start && pieceOffset(piece, value.length) >= end;
26239
+ }).at(-1);
26240
+ if (owner?.kind === "code") return { ...owner, text: owner.code };
26241
+ return owner?.kind === "text" ? owner : { offset: 0, text: passage.content };
26242
+ }
26243
+ var init_source_view = __esm({
26244
+ "src/core/markup/source-view.ts"() {
26245
+ "use strict";
26246
+ init_tooling();
26247
+ }
26248
+ });
26249
+
26208
26250
  // src/core/parsing/argument-lexer.ts
26209
26251
  function lexArguments(source) {
26210
26252
  let from = 0;
@@ -26553,6 +26595,7 @@ var TypeError2, TypeWarning, parameterTypes, LEX_LIMIT, wsRe, identStartRe, iden
26553
26595
  var init_parameter_validator = __esm({
26554
26596
  "src/core/parsing/parameter-validator.ts"() {
26555
26597
  "use strict";
26598
+ init_tooling();
26556
26599
  init_argument_lexer();
26557
26600
  TypeError2 = class {
26558
26601
  constructor(message) {
@@ -26666,7 +26709,8 @@ var init_parameter_validator = __esm({
26666
26709
  validate(arg, _args, _index, state) {
26667
26710
  let passageName;
26668
26711
  if (arg.type === 0 /* String */) {
26669
- passageName = arg.text.slice(1, -1);
26712
+ const target = passageTarget(arg.text);
26713
+ if (target.kind === "name") passageName = target.name;
26670
26714
  } else if (arg.type === 8 /* Bareword */) {
26671
26715
  passageName = arg.text;
26672
26716
  } else if (arg.type === 1 /* Number */) {
@@ -26675,7 +26719,6 @@ var init_parameter_validator = __esm({
26675
26719
  passageName = "NaN";
26676
26720
  }
26677
26721
  if (passageName !== void 0) {
26678
- passageName = passageName.replace(/\\/g, "");
26679
26722
  if (state && state.passages.length > 0) {
26680
26723
  if (!state.passages.includes(passageName)) {
26681
26724
  return new TypeWarning(`Nonexistent passage: "${passageName}"`);
@@ -27167,7 +27210,9 @@ function fromMarkup(passage, found, workspace) {
27167
27210
  if (element) code = DiagnosticCode.MalformedElement;
27168
27211
  else if (found.code === "stray-closer" && !workspace.isContainer(name)) code = DiagnosticCode.IllegalClosingTag;
27169
27212
  if (found.code === "unclosed-block") {
27170
- data2 = { kind: "unclosed-block", closer: element ? `</${name}>` : `{/${name}}`, at: passage.position(passage.content.trimEnd().length) };
27213
+ const owner = textAt(passage, found.start, found.end);
27214
+ const end = owner ? pieceOffset(owner, owner.text.trimEnd().length) : passage.content.trimEnd().length;
27215
+ data2 = { kind: "unclosed-block", closer: element ? `</${name}>` : `{/${name}}`, at: passage.position(end) };
27171
27216
  }
27172
27217
  break;
27173
27218
  }
@@ -27399,10 +27444,9 @@ function loopDiagnostics(passage, token, ancestors) {
27399
27444
  if (!loop || !close) return [];
27400
27445
  const targets = macro === "computed" ? computedTemporaryTarget(token.rawArgs) : setTemporaryTargets(token.rawArgs);
27401
27446
  const bodyStart = loop.node.token.end;
27402
- const body = passage.content.slice(bodyStart, close.start);
27403
27447
  const diagnostics = [];
27404
27448
  for (const target of targets) {
27405
- if (!isReadInBody(body, bodyStart, target.name, token.start, token.end)) continue;
27449
+ if (!isReadInBody(passage, bodyStart, close.start, target.name, token.start, token.end)) continue;
27406
27450
  const start = token.argsStart + target.offset;
27407
27451
  diagnostics.push(makeDiag(
27408
27452
  passage.range(start, start + 1 + target.name.length),
@@ -27412,22 +27456,28 @@ function loopDiagnostics(passage, token, ancestors) {
27412
27456
  }
27413
27457
  return diagnostics;
27414
27458
  }
27415
- function isReadInBody(body, bodyOffset, name, macroStart, macroEnd) {
27416
- const re2 = temporaryRefRegex(name);
27417
- let m;
27418
- while ((m = re2.exec(body)) !== null) {
27419
- const offset2 = bodyOffset + m.index;
27420
- if (offset2 >= macroStart && offset2 < macroEnd) continue;
27421
- const after = body.slice(m.index + m[0].length);
27422
- if (/^\s*=(?![=>])/.test(after)) continue;
27423
- return true;
27459
+ function isReadInBody(passage, bodyStart, bodyEnd, name, macroStart, macroEnd) {
27460
+ const eligible = (offset2) => offset2 >= bodyStart && offset2 < bodyEnd && !(offset2 >= macroStart && offset2 < macroEnd);
27461
+ for (const token of markupTokens(passage)) {
27462
+ if (token.type === "variable" && token.scope === "temporary" && token.name.split(".")[0] === name && eligible(token.start)) return true;
27463
+ }
27464
+ for (const piece of passage.pieces) {
27465
+ if (piece.kind !== "code") continue;
27466
+ let read = false;
27467
+ lexJs(piece.code, {
27468
+ variable(sigil, found, index, _nesting, end) {
27469
+ if (sigil !== "_" || found !== name || !eligible(pieceOffset(piece, index))) return;
27470
+ if (!/^\s*=(?![=>])/.test(maskLiterals(piece.code.slice(end)))) read = true;
27471
+ }
27472
+ }, piece.goal);
27473
+ if (read) return true;
27424
27474
  }
27425
27475
  return false;
27426
27476
  }
27427
27477
  function argumentDiagnostics(passage, workspace) {
27428
27478
  const diagnostics = [];
27429
27479
  const passageNames = Array.from(workspace.passages.getAllPassages(), (candidate) => candidate.name);
27430
- for (const token of passage.isMarkup ? passage.tokens : []) {
27480
+ for (const token of passage.isMarkup ? macroTokens(passage) : []) {
27431
27481
  if (token.type !== "macro" || token.isClose) continue;
27432
27482
  const info = workspace.macros.getMacro(token.name);
27433
27483
  if (!info?.parameters || info.skipArgs || SPINDLE_MACROS.has(token.name.toLowerCase())) continue;
@@ -27588,6 +27638,7 @@ var init_diagnostics = __esm({
27588
27638
  init_tooling();
27589
27639
  init_diagnostic_codes();
27590
27640
  init_tokens();
27641
+ init_source_view();
27591
27642
  init_argument_lexer();
27592
27643
  init_parameter_validator();
27593
27644
  init_link_parser();
@@ -28043,7 +28094,7 @@ function splitPassages(text2) {
28043
28094
  }
28044
28095
  }
28045
28096
  for (let i2 = 0; i2 < lines.length; i2++) {
28046
- if (PASSAGE_HEADER_REGEX.test(lines[i2])) {
28097
+ if (parsePassageHeader(lines[i2], i2)) {
28047
28098
  pushPassage();
28048
28099
  currentHeader = lines[i2];
28049
28100
  bodyLines = [];
@@ -28056,7 +28107,7 @@ function splitPassages(text2) {
28056
28107
  return passages;
28057
28108
  }
28058
28109
  function classifyPassage(header) {
28059
- const tags = headerTags(header).map((t) => t.toLowerCase());
28110
+ const tags = headerTags(header);
28060
28111
  if (tags.includes("script")) return "script";
28061
28112
  if (tags.includes("stylesheet")) return "stylesheet";
28062
28113
  return "normal";
@@ -28067,22 +28118,23 @@ function headerTags(header) {
28067
28118
  const unescaped = header.replace(/\\./g, "ec");
28068
28119
  return (unescaped.match(/\[[^\]]*\]/g) ?? []).flatMap((t) => t.slice(1, -1).split(/\s+/));
28069
28120
  }
28070
- var PASSAGE_HEADER_REGEX;
28071
28121
  var init_segment = __esm({
28072
28122
  "src/plugins/format/segment.ts"() {
28073
28123
  "use strict";
28074
28124
  init_passage_parser();
28075
- PASSAGE_HEADER_REGEX = /^::\s+/;
28076
28125
  }
28077
28126
  });
28078
28127
 
28079
28128
  // src/plugins/format/prettier-bridge.ts
28080
- async function loadPrettier() {
28129
+ import { resolve as resolve4 } from "node:path";
28130
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
28131
+ async function loadPrettier(filePath) {
28081
28132
  prettier ??= import("prettier").catch(() => null);
28082
28133
  const p = await prettier;
28083
28134
  if (!p) return void 0;
28084
28135
  try {
28085
- const resolved = await p.resolveConfig(process.cwd());
28136
+ const path = filePath?.startsWith("file:") ? fileURLToPath2(filePath) : filePath;
28137
+ const resolved = await p.resolveConfig(path ?? resolve4(process.cwd(), "story.tw"));
28086
28138
  return { prettier: p, options: { tabWidth: 2, ...resolved ?? {} } };
28087
28139
  } catch {
28088
28140
  return { prettier: p, options: { tabWidth: 2 } };
@@ -28122,7 +28174,7 @@ function dominantEol2(text2) {
28122
28174
  async function formatLf2(text2, options) {
28123
28175
  const isBlock = options?.isBlock ?? buildDefaultIsBlock(text2);
28124
28176
  const isDedentingSubMacro = options?.isDedentingSubMacro ?? ((name) => DEFAULT_DEDENTING2.has(name.toLowerCase()));
28125
- const prettier2 = await loadPrettier();
28177
+ const prettier2 = await loadPrettier(options?.filePath);
28126
28178
  const passages = splitPassages(text2);
28127
28179
  const resultLines = [];
28128
28180
  for (let pi2 = 0; pi2 < passages.length; pi2++) {
@@ -28136,7 +28188,7 @@ async function formatLf2(text2, options) {
28136
28188
  }
28137
28189
  }
28138
28190
  if (passage.header) {
28139
- const header = PASSAGE_HEADER_REGEX2.test(passage.header) ? normalizePassageHeader(passage.header) : passage.header;
28191
+ const header = PASSAGE_HEADER_REGEX.test(passage.header) ? normalizePassageHeader(passage.header) : passage.header;
28140
28192
  resultLines.push(header.replace(/\s+$/, ""));
28141
28193
  }
28142
28194
  if (passage.body === "") continue;
@@ -28156,7 +28208,7 @@ async function formatRange(text2, _range, options) {
28156
28208
  return formatDocument(text2, options);
28157
28209
  }
28158
28210
  function normalizePassageHeader(line) {
28159
- const headerMatch = line.match(/^::\s+(.*)/);
28211
+ const headerMatch = line.match(/^::\s*(.*)/);
28160
28212
  if (!headerMatch) return line;
28161
28213
  const rest = headerMatch[1];
28162
28214
  const unescaped = rest.replace(/\\./g, "ec");
@@ -28175,14 +28227,14 @@ function normalizePassageHeader(line) {
28175
28227
  }
28176
28228
  return `:: ${name}${suffix}`;
28177
28229
  }
28178
- var PASSAGE_HEADER_REGEX2, DEFAULT_DEDENTING2, BUILTIN_CONTAINERS, formatPlugin;
28230
+ var PASSAGE_HEADER_REGEX, DEFAULT_DEDENTING2, BUILTIN_CONTAINERS, formatPlugin;
28179
28231
  var init_format = __esm({
28180
28232
  "src/plugins/format.ts"() {
28181
28233
  "use strict";
28182
28234
  init_tooling();
28183
28235
  init_segment();
28184
28236
  init_prettier_bridge();
28185
- PASSAGE_HEADER_REGEX2 = /^(::)\s+/;
28237
+ PASSAGE_HEADER_REGEX = /^(::)\s*/;
28186
28238
  DEFAULT_DEDENTING2 = /* @__PURE__ */ new Set(["else", "elseif", "next", "case", "default"]);
28187
28239
  BUILTIN_CONTAINERS = new Set(builtinMacros.filter((m) => m.block).map((m) => m.name.toLowerCase()));
28188
28240
  formatPlugin = {
@@ -28200,7 +28252,7 @@ var init_format = __esm({
28200
28252
  ctx.connection.onDocumentFormatting(async (params) => {
28201
28253
  const text2 = ctx.workspace.documents.getText(params.textDocument.uri);
28202
28254
  if (text2 === void 0) return [];
28203
- const formatted = await formatDocument(text2, formatOpts);
28255
+ const formatted = await formatDocument(text2, { ...formatOpts, filePath: params.textDocument.uri });
28204
28256
  if (formatted === text2) return [];
28205
28257
  const lines = text2.split("\n");
28206
28258
  return [{
@@ -28218,7 +28270,7 @@ var init_format = __esm({
28218
28270
  start: { line: params.range.start.line, character: params.range.start.character },
28219
28271
  end: { line: params.range.end.line, character: params.range.end.character }
28220
28272
  };
28221
- const formatted = await formatRange(text2, range, formatOpts);
28273
+ const formatted = await formatRange(text2, range, { ...formatOpts, filePath: params.textDocument.uri });
28222
28274
  if (formatted === text2) return [];
28223
28275
  const lines = text2.split("\n");
28224
28276
  return [{
@@ -28310,7 +28362,7 @@ async function runFormat(args2) {
28310
28362
  const unformatted = [];
28311
28363
  for (const [filePath, text2] of texts) {
28312
28364
  try {
28313
- const formatted = await formatDocument(text2, formatOpts);
28365
+ const formatted = await formatDocument(text2, { ...formatOpts, filePath });
28314
28366
  if (formatted !== text2) {
28315
28367
  if (options.check) {
28316
28368
  const relative2 = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
@@ -50599,7 +50651,7 @@ var init_protocol = __esm({
50599
50651
  return;
50600
50652
  }
50601
50653
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
50602
- await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
50654
+ await new Promise((resolve6) => setTimeout(resolve6, pollInterval));
50603
50655
  options?.signal?.throwIfAborted();
50604
50656
  }
50605
50657
  } catch (error48) {
@@ -50616,7 +50668,7 @@ var init_protocol = __esm({
50616
50668
  */
50617
50669
  request(request, resultSchema, options) {
50618
50670
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
50619
- return new Promise((resolve5, reject) => {
50671
+ return new Promise((resolve6, reject) => {
50620
50672
  const earlyReject = (error48) => {
50621
50673
  reject(error48);
50622
50674
  };
@@ -50694,7 +50746,7 @@ var init_protocol = __esm({
50694
50746
  if (!parseResult.success) {
50695
50747
  reject(parseResult.error);
50696
50748
  } else {
50697
- resolve5(parseResult.data);
50749
+ resolve6(parseResult.data);
50698
50750
  }
50699
50751
  } catch (error48) {
50700
50752
  reject(error48);
@@ -50956,12 +51008,12 @@ var init_protocol = __esm({
50956
51008
  }
50957
51009
  } catch {
50958
51010
  }
50959
- return new Promise((resolve5, reject) => {
51011
+ return new Promise((resolve6, reject) => {
50960
51012
  if (signal.aborted) {
50961
51013
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
50962
51014
  return;
50963
51015
  }
50964
- const timeoutId = setTimeout(resolve5, interval);
51016
+ const timeoutId = setTimeout(resolve6, interval);
50965
51017
  signal.addEventListener("abort", () => {
50966
51018
  clearTimeout(timeoutId);
50967
51019
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -53988,7 +54040,7 @@ var require_compile = __commonJS({
53988
54040
  const schOrFunc = root.refs[ref2];
53989
54041
  if (schOrFunc)
53990
54042
  return schOrFunc;
53991
- let _sch = resolve5.call(this, root, ref2);
54043
+ let _sch = resolve6.call(this, root, ref2);
53992
54044
  if (_sch === void 0) {
53993
54045
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref2];
53994
54046
  const { schemaId } = this.opts;
@@ -54015,7 +54067,7 @@ var require_compile = __commonJS({
54015
54067
  function sameSchemaEnv(s1, s2) {
54016
54068
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
54017
54069
  }
54018
- function resolve5(root, ref2) {
54070
+ function resolve6(root, ref2) {
54019
54071
  let sch;
54020
54072
  while (typeof (sch = this.refs[ref2]) == "string")
54021
54073
  ref2 = sch;
@@ -54590,7 +54642,7 @@ var require_fast_uri = __commonJS({
54590
54642
  }
54591
54643
  return uri;
54592
54644
  }
54593
- function resolve5(baseURI, relativeURI, options) {
54645
+ function resolve6(baseURI, relativeURI, options) {
54594
54646
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
54595
54647
  const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
54596
54648
  schemelessOptions.skipEscape = true;
@@ -54817,7 +54869,7 @@ var require_fast_uri = __commonJS({
54817
54869
  var fastUri = {
54818
54870
  SCHEMES,
54819
54871
  normalize,
54820
- resolve: resolve5,
54872
+ resolve: resolve6,
54821
54873
  resolveComponent,
54822
54874
  equal,
54823
54875
  serialize,
@@ -58975,7 +59027,7 @@ var init_mcp = __esm({
58975
59027
  let task = createTaskResult.task;
58976
59028
  const pollInterval = task.pollInterval ?? 5e3;
58977
59029
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
58978
- await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
59030
+ await new Promise((resolve6) => setTimeout(resolve6, pollInterval));
58979
59031
  const updatedTask = await extra.taskStore.getTask(taskId);
58980
59032
  if (!updatedTask) {
58981
59033
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -59584,12 +59636,12 @@ var init_stdio2 = __esm({
59584
59636
  this.onclose?.();
59585
59637
  }
59586
59638
  send(message) {
59587
- return new Promise((resolve5) => {
59639
+ return new Promise((resolve6) => {
59588
59640
  const json2 = serializeMessage(message);
59589
59641
  if (this._stdout.write(json2)) {
59590
- resolve5();
59642
+ resolve6();
59591
59643
  } else {
59592
- this._stdout.once("drain", resolve5);
59644
+ this._stdout.once("drain", resolve6);
59593
59645
  }
59594
59646
  });
59595
59647
  }
@@ -59607,7 +59659,7 @@ __export(server_exports, {
59607
59659
  startMcpServer: () => startMcpServer
59608
59660
  });
59609
59661
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync2, statSync } from "node:fs";
59610
- import { resolve as resolve4 } from "node:path";
59662
+ import { resolve as resolve5 } from "node:path";
59611
59663
  import { pathToFileURL as pathToFileURL4 } from "node:url";
59612
59664
  function filterBySeverity2(diagnostics, minSeverity) {
59613
59665
  const minIdx = SEVERITY_ORDER2.indexOf(minSeverity);
@@ -59620,7 +59672,7 @@ async function resolveFiles(pattern, cwd) {
59620
59672
  let input = pattern;
59621
59673
  let directory = cwd;
59622
59674
  try {
59623
- const literal3 = resolve4(cwd, pattern);
59675
+ const literal3 = resolve5(cwd, pattern);
59624
59676
  const stat = statSync(literal3);
59625
59677
  if (stat.isFile()) return [literal3];
59626
59678
  if (stat.isDirectory()) {
@@ -59721,7 +59773,7 @@ async function formatFiles(pattern, cwd = process.cwd()) {
59721
59773
  const text2 = contents.get(pathToFileURL4(filePath).toString());
59722
59774
  if (text2 === void 0) continue;
59723
59775
  try {
59724
- const result = await formatDocument(text2);
59776
+ const result = await formatDocument(text2, { filePath });
59725
59777
  if (result !== text2) {
59726
59778
  writeFileSync2(filePath, result, "utf-8");
59727
59779
  formatted++;
@@ -59746,7 +59798,7 @@ async function checkFormatting(pattern, cwd = process.cwd()) {
59746
59798
  const text2 = contents.get(pathToFileURL4(filePath).toString());
59747
59799
  if (text2 === void 0) continue;
59748
59800
  try {
59749
- const result = await formatDocument(text2);
59801
+ const result = await formatDocument(text2, { filePath });
59750
59802
  (result !== text2 ? needsFormatting : alreadyFormatted).push(relativeTo(cwd, filePath));
59751
59803
  } catch {
59752
59804
  }
@@ -61083,8 +61135,8 @@ var require_semaphore = __commonJS({
61083
61135
  this._waiting = [];
61084
61136
  }
61085
61137
  lock(thunk) {
61086
- return new Promise((resolve5, reject) => {
61087
- this._waiting.push({ thunk, resolve: resolve5, reject });
61138
+ return new Promise((resolve6, reject) => {
61139
+ this._waiting.push({ thunk, resolve: resolve6, reject });
61088
61140
  this.runNext();
61089
61141
  });
61090
61142
  }
@@ -62710,9 +62762,9 @@ ${JSON.stringify(message, null, 4)}`);
62710
62762
  if (typeof cancellationStrategy.sender.enableCancellation === "function") {
62711
62763
  cancellationStrategy.sender.enableCancellation(requestMessage);
62712
62764
  }
62713
- return new Promise(async (resolve5, reject) => {
62765
+ return new Promise(async (resolve6, reject) => {
62714
62766
  const resolveWithCleanup = (r) => {
62715
- resolve5(r);
62767
+ resolve6(r);
62716
62768
  cancellationStrategy.sender.cleanup(id);
62717
62769
  disposable?.dispose();
62718
62770
  };
@@ -68354,8 +68406,8 @@ var require_server = __commonJS({
68354
68406
  if (value instanceof Promise) {
68355
68407
  return value;
68356
68408
  } else if (Is3.thenable(value)) {
68357
- return new Promise((resolve5, reject) => {
68358
- value.then((resolved) => resolve5(resolved), (error48) => reject(error48));
68409
+ return new Promise((resolve6, reject) => {
68410
+ value.then((resolved) => resolve6(resolved), (error48) => reject(error48));
68359
68411
  });
68360
68412
  } else {
68361
68413
  return Promise.resolve(value);
@@ -68639,7 +68691,7 @@ var require_files = __commonJS({
68639
68691
  Object.defineProperty(exports, "__esModule", { value: true });
68640
68692
  exports.FileSystem = void 0;
68641
68693
  exports.uriToFilePath = uriToFilePath;
68642
- exports.resolve = resolve5;
68694
+ exports.resolve = resolve6;
68643
68695
  exports.resolveGlobalNodePath = resolveGlobalNodePath;
68644
68696
  exports.resolveGlobalYarnPath = resolveGlobalYarnPath;
68645
68697
  exports.resolveModulePath = resolveModulePath;
@@ -68668,7 +68720,7 @@ var require_files = __commonJS({
68668
68720
  function isWindows() {
68669
68721
  return process.platform === "win32";
68670
68722
  }
68671
- function resolve5(moduleName, nodePath, cwd, tracer) {
68723
+ function resolve6(moduleName, nodePath, cwd, tracer) {
68672
68724
  const nodePathKey = "NODE_PATH";
68673
68725
  const app = [
68674
68726
  "var p = process;",
@@ -68687,7 +68739,7 @@ var require_files = __commonJS({
68687
68739
  "}",
68688
68740
  "});"
68689
68741
  ].join("");
68690
- return new Promise((resolve6, reject) => {
68742
+ return new Promise((resolve7, reject) => {
68691
68743
  const env = process.env;
68692
68744
  const newEnv = /* @__PURE__ */ Object.create(null);
68693
68745
  Object.keys(env).forEach((key) => newEnv[key] = env[key]);
@@ -68719,7 +68771,7 @@ var require_files = __commonJS({
68719
68771
  if (message2.c === "r") {
68720
68772
  cp.send({ c: "e" });
68721
68773
  if (message2.s) {
68722
- resolve6(message2.r);
68774
+ resolve7(message2.r);
68723
68775
  } else {
68724
68776
  reject(new Error(`Failed to resolve module: ${moduleName}`));
68725
68777
  }
@@ -68847,17 +68899,17 @@ var require_files = __commonJS({
68847
68899
  if (!path.isAbsolute(nodePath)) {
68848
68900
  nodePath = path.join(workspaceRoot, nodePath);
68849
68901
  }
68850
- return resolve5(moduleName, nodePath, nodePath, tracer).then((value) => {
68902
+ return resolve6(moduleName, nodePath, nodePath, tracer).then((value) => {
68851
68903
  if (FileSystem.isParent(nodePath, value)) {
68852
68904
  return value;
68853
68905
  } else {
68854
68906
  return Promise.reject(new Error(`Failed to load ${moduleName} from node path location.`));
68855
68907
  }
68856
68908
  }).then(void 0, (_error) => {
68857
- return resolve5(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
68909
+ return resolve6(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
68858
68910
  });
68859
68911
  } else {
68860
- return resolve5(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
68912
+ return resolve6(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
68861
68913
  }
68862
68914
  }
68863
68915
  }
@@ -68939,10 +68991,10 @@ var require_ril = __commonJS({
68939
68991
  return api_1.Disposable.create(() => this.stream.off("end", listener));
68940
68992
  }
68941
68993
  write(data2, encoding) {
68942
- return new Promise((resolve5, reject) => {
68994
+ return new Promise((resolve6, reject) => {
68943
68995
  const callback = (error48) => {
68944
68996
  if (error48 === void 0 || error48 === null) {
68945
- resolve5();
68997
+ resolve6();
68946
68998
  } else {
68947
68999
  reject(error48);
68948
69000
  }
@@ -69234,10 +69286,10 @@ var require_main = __commonJS({
69234
69286
  }
69235
69287
  function createClientPipeTransport(pipeName, encoding = "utf-8") {
69236
69288
  let connectResolve;
69237
- const connected = new Promise((resolve5, _reject) => {
69238
- connectResolve = resolve5;
69289
+ const connected = new Promise((resolve6, _reject) => {
69290
+ connectResolve = resolve6;
69239
69291
  });
69240
- return new Promise((resolve5, reject) => {
69292
+ return new Promise((resolve6, reject) => {
69241
69293
  const server = (0, net_1.createServer)((socket) => {
69242
69294
  server.close();
69243
69295
  connectResolve([
@@ -69248,7 +69300,7 @@ var require_main = __commonJS({
69248
69300
  server.on("error", reject);
69249
69301
  server.listen(pipeName, () => {
69250
69302
  server.removeListener("error", reject);
69251
- resolve5({
69303
+ resolve6({
69252
69304
  onConnected: () => {
69253
69305
  return connected;
69254
69306
  }
@@ -69265,10 +69317,10 @@ var require_main = __commonJS({
69265
69317
  }
69266
69318
  function createClientSocketTransport(port, encoding = "utf-8") {
69267
69319
  let connectResolve;
69268
- const connected = new Promise((resolve5, _reject) => {
69269
- connectResolve = resolve5;
69320
+ const connected = new Promise((resolve6, _reject) => {
69321
+ connectResolve = resolve6;
69270
69322
  });
69271
- return new Promise((resolve5, reject) => {
69323
+ return new Promise((resolve6, reject) => {
69272
69324
  const server = (0, net_1.createServer)((socket) => {
69273
69325
  server.close();
69274
69326
  connectResolve([
@@ -69285,7 +69337,7 @@ var require_main = __commonJS({
69285
69337
  return;
69286
69338
  }
69287
69339
  const boundPort = address.port;
69288
- resolve5({
69340
+ resolve6({
69289
69341
  port: () => boundPort,
69290
69342
  onConnected: () => {
69291
69343
  return connected;
@@ -70079,6 +70131,7 @@ var init_markup_cursor = __esm({
70079
70131
  init_tooling();
70080
70132
  init_passage_markup();
70081
70133
  init_tree();
70134
+ init_source_view();
70082
70135
  init_text();
70083
70136
  MarkupCursor = class {
70084
70137
  constructor(passage, at3, workspace) {
@@ -70104,6 +70157,7 @@ var init_markup_cursor = __esm({
70104
70157
  start: 0,
70105
70158
  end: content.length,
70106
70159
  text: false,
70160
+ view: { offset: 0, text: content },
70107
70161
  tokens: passage.tokens,
70108
70162
  errors: passage.tokenization.errors,
70109
70163
  nodes: () => passage.pairing.nodes
@@ -70116,6 +70170,7 @@ var init_markup_cursor = __esm({
70116
70170
  start: piece.offset,
70117
70171
  end,
70118
70172
  text: true,
70173
+ view: piece,
70119
70174
  tokens: piece.tokens,
70120
70175
  errors: piece.errors,
70121
70176
  nodes: () => pairMarkup(piece.tokens, { isBlock: (name) => this.workspace.isContainer(name), source: content }).nodes
@@ -70130,17 +70185,19 @@ var init_markup_cursor = __esm({
70130
70185
  * of its name.
70131
70186
  */
70132
70187
  enclosingMacro(known) {
70133
- const { content, at: at3 } = this;
70188
+ const { at: at3 } = this;
70134
70189
  for (const region of this.regions) {
70135
70190
  const found = [];
70136
70191
  for (const token of region.tokens) {
70137
70192
  if (token.type !== "macro" || token.isClose || token.nameEnd >= at3 || at3 >= token.end) continue;
70138
- found.push({ start: token.start, name: token.name, argsBefore: at3 >= token.argsStart ? content.slice(token.argsStart, at3) : "" });
70193
+ found.push({ start: token.start, name: token.name, argsBefore: at3 >= token.argsStart ? region.view.text.slice(viewIndex(region.view, token.argsStart), viewIndex(region.view, at3)) : "" });
70139
70194
  }
70140
70195
  for (const error48 of region.errors) {
70141
- if (error48.code !== "unclosed-macro" || error48.offset >= at3 || error48.end >= at3 || !/\s/.test(content[error48.end] ?? "")) continue;
70142
- const name = content.slice(parseSelectors(content, error48.offset + 1).end, error48.end);
70143
- if (name && name[0] !== "/") found.push({ start: error48.offset, name, argsBefore: content.slice(error48.end, at3).trimStart() });
70196
+ const source = region.view.text;
70197
+ const end = viewIndex(region.view, error48.end);
70198
+ if (error48.code !== "unclosed-macro" || error48.offset >= at3 || error48.end >= at3 || !/\s/.test(source[end] ?? "")) continue;
70199
+ const name = source.slice(parseSelectors(source, viewIndex(region.view, error48.offset) + 1).end, end);
70200
+ if (name && name[0] !== "/") found.push({ start: error48.offset, name, argsBefore: source.slice(end, viewIndex(region.view, at3)).trimStart() });
70144
70201
  }
70145
70202
  const innermost = found.filter((macro) => known(macro.name)).sort((a, b) => b.start - a.start)[0];
70146
70203
  if (innermost) return { name: innermost.name, argsBefore: innermost.argsBefore };
@@ -70229,10 +70286,9 @@ function variableUses(passage) {
70229
70286
  for (const piece of passage.pieces) {
70230
70287
  if (piece.kind !== "code") continue;
70231
70288
  lexJs(piece.code, {
70232
- variable(sigil, name, index) {
70233
- const nameEnd = index + 1 + name.length;
70289
+ variable(sigil, name, index, _nesting, nameEnd) {
70234
70290
  const pathEnd = nameEnd + pathLength(piece.code, nameEnd);
70235
- uses.push({ sigil, name, start: pieceOffset(piece, index), end: pieceOffset(piece, pathEnd - 1) + 1 });
70291
+ uses.push({ sigil, name, start: pieceOffset(piece, index), end: pieceOffset(piece, pathEnd) });
70236
70292
  }
70237
70293
  }, piece.goal);
70238
70294
  }
@@ -70824,27 +70880,7 @@ function findReferences(uri, position, workspace, includeDeclaration) {
70824
70880
  return [];
70825
70881
  }
70826
70882
  function variableAt(uri, position, workspace) {
70827
- const line = workspace.documents.getText(uri)?.split("\n")[position.line];
70828
- if (line === void 0) return null;
70829
- let atEnd = null;
70830
- VARIABLE_CANDIDATE.lastIndex = 0;
70831
- let found;
70832
- while ((found = VARIABLE_CANDIDATE.exec(line)) !== null) {
70833
- const match = VARIABLE_PATH.exec(line.slice(found.index));
70834
- const start = found.index;
70835
- const end = start + match[0].length;
70836
- VARIABLE_CANDIDATE.lastIndex = start + 1;
70837
- if (position.character < start || position.character > end) continue;
70838
- const sigil = match[1];
70839
- const name = match[2].split(".")[0];
70840
- const refs = sigil === "%" ? findTransientReferences(name, workspace, true) : findVariableReferences(name, workspace, true);
70841
- const hit = refs.find((r) => r.uri === uri && r.range.start.line === position.line && r.range.start.character === start);
70842
- if (!hit) continue;
70843
- const symbol2 = { sigil, name, range: hit.range };
70844
- if (position.character < end) return symbol2;
70845
- atEnd ??= symbol2;
70846
- }
70847
- return atEnd;
70883
+ return workspace.variables.referenceAt(uri, position);
70848
70884
  }
70849
70885
  function findPassageReferences(passageName, workspace, includeDeclaration) {
70850
70886
  const locations = [];
@@ -70927,15 +70963,13 @@ function toLspRange3(r) {
70927
70963
  end: { line: r.end.line, character: r.end.character }
70928
70964
  };
70929
70965
  }
70930
- var VARIABLE_CANDIDATE, VARIABLE_PATH, referencesPlugin;
70966
+ var referencesPlugin;
70931
70967
  var init_references = __esm({
70932
70968
  "src/plugins/references.ts"() {
70933
70969
  "use strict";
70934
70970
  init_macro_heads();
70935
70971
  init_passage_refs();
70936
70972
  init_passage_parser();
70937
- VARIABLE_CANDIDATE = /(?:\$|(?<!\w)%)(?=\w)/g;
70938
- VARIABLE_PATH = /^([$%])(\w+(?:\.[A-Za-z_$][\w$]*)*)/;
70939
70973
  referencesPlugin = {
70940
70974
  id: "references",
70941
70975
  capabilities: {
@@ -71039,17 +71073,32 @@ function computeRename(uri, position, newName, workspace) {
71039
71073
  `Cannot rename to ${JSON.stringify(newName)}: a transient name cannot start with a digit, \`%5\` is the modulo operator in code.`
71040
71074
  ).at(uri, symbol2.range);
71041
71075
  }
71076
+ const declaration = parseDeclarations(`${symbol2.sigil}${bareName} = 0`, symbol2.sigil);
71077
+ if (declaration.errors.length || declaration.declarations[0]?.name !== bareName) {
71078
+ throw new RenameError(`Cannot rename to ${JSON.stringify(newName)}: ${declaration.errors[0]?.message ?? "invalid variable name"}.`).at(uri, symbol2.range);
71079
+ }
71042
71080
  if (bareName === symbol2.name) return /* @__PURE__ */ new Map();
71043
71081
  if (workspace.variables.getDeclared().has(bareName) || workspace.variables.getDeclaredTransient().has(bareName)) {
71044
71082
  throw new RenameError(`Cannot rename to ${JSON.stringify(newName)}: a variable with that name already exists.`).at(uri, symbol2.range);
71045
71083
  }
71046
71084
  const refs = symbol2.sigil === "%" ? findTransientReferences(symbol2.name, workspace, true) : findVariableReferences(symbol2.name, workspace, true);
71047
71085
  for (const ref2 of refs) {
71048
- const start = ref2.range.start.character + 1;
71049
- addEdit(ref2.uri, {
71050
- start: { line: ref2.range.start.line, character: start },
71051
- end: { line: ref2.range.start.line, character: start + symbol2.name.length }
71052
- }, bareName);
71086
+ const doc = workspace.markup.get(ref2.uri);
71087
+ const passage = doc.passageAt(ref2.range.start);
71088
+ const start = passage.contentOffset(positionToOffset(ref2.range.start, doc.lineStarts));
71089
+ const end = passage.contentOffset(positionToOffset(ref2.range.end, doc.lineStarts));
71090
+ const view = sourceView(passage, start, end);
71091
+ const index = viewIndex(view, start);
71092
+ let base;
71093
+ lexJs(view.text.slice(index, viewIndex(view, end)), {
71094
+ variable(sigil, name, at3, _nesting, nameEnd) {
71095
+ if (at3 === 0 && sigil === symbol2.sigil && name === symbol2.name) {
71096
+ base = [pieceOffset(view, index + 1), pieceOffset(view, index + nameEnd)];
71097
+ }
71098
+ }
71099
+ });
71100
+ if (!base) throw new RenameError("Cannot locate the variable name safely.").at(ref2.uri, ref2.range);
71101
+ addEdit(ref2.uri, passage.range(...base), bareName);
71053
71102
  }
71054
71103
  break;
71055
71104
  }
@@ -71204,6 +71253,8 @@ var init_rename = __esm({
71204
71253
  "use strict";
71205
71254
  import_vscode_languageserver2 = __toESM(require_api3(), 1);
71206
71255
  init_tooling();
71256
+ init_source_view();
71257
+ init_text();
71207
71258
  init_link_runtime();
71208
71259
  init_passage_refs();
71209
71260
  init_js_string_literal();
@@ -71358,7 +71409,8 @@ var init_code_lens = __esm({
71358
71409
  range: toLspRange5(l.range),
71359
71410
  command: {
71360
71411
  title: l.command.title,
71361
- command: "spindle.findReferences"
71412
+ // Informational counts: no editor-specific navigation command is registered.
71413
+ command: ""
71362
71414
  }
71363
71415
  }));
71364
71416
  });
@@ -71387,13 +71439,15 @@ function addWidgetParamHints(passages, inRange, workspace, hints) {
71387
71439
  const widget = workspace.widgets.getWidget(token.name);
71388
71440
  if (!widget || widget.params.length === 0) continue;
71389
71441
  const args2 = splitArgs(token.rawArgs);
71442
+ const view = textAt(passage, token.start, token.end) ?? { offset: 0 };
71443
+ const argsStart = viewIndex(view, token.argsStart);
71390
71444
  let from = 0;
71391
71445
  for (let i2 = 0; i2 < Math.min(args2.length, widget.params.length); i2++) {
71392
71446
  const at3 = token.rawArgs.indexOf(args2[i2], from);
71393
71447
  if (at3 === -1) break;
71394
71448
  from = at3 + args2[i2].length;
71395
71449
  hints.push({
71396
- position: passage.position(token.argsStart + at3),
71450
+ position: passage.position(pieceOffset(view, argsStart + at3)),
71397
71451
  label: `${widget.params[i2]}:`,
71398
71452
  kind: "parameter"
71399
71453
  });
@@ -71416,6 +71470,7 @@ var init_inlay_hints = __esm({
71416
71470
  "src/plugins/inlay-hints.ts"() {
71417
71471
  "use strict";
71418
71472
  init_tooling();
71473
+ init_source_view();
71419
71474
  init_tokens();
71420
71475
  inlayHintsPlugin = {
71421
71476
  id: "inlay-hints",
@@ -71582,7 +71637,7 @@ var init_semantic_tokens = __esm({
71582
71637
  // src/plugins/code-actions.ts
71583
71638
  import { readFileSync as readFileSync9 } from "node:fs";
71584
71639
  import { basename, dirname as dirname3, join as join4 } from "node:path";
71585
- import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL5 } from "node:url";
71640
+ import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL5 } from "node:url";
71586
71641
  function computeCodeActions(uri, diagnostics, workspace, options = {}) {
71587
71642
  const actions = [];
71588
71643
  for (const diag of diagnostics) {
@@ -71665,10 +71720,10 @@ function addMacroToConfig(uri, macroName, workspace, options) {
71665
71720
  }
71666
71721
  function resolveConfigRoot(uri, workspaceRoot) {
71667
71722
  if (workspaceRoot) {
71668
- return workspaceRoot.startsWith("file:") ? fileURLToPath2(workspaceRoot) : workspaceRoot;
71723
+ return workspaceRoot.startsWith("file:") ? fileURLToPath3(workspaceRoot) : workspaceRoot;
71669
71724
  }
71670
71725
  if (!uri.startsWith("file:")) return null;
71671
- const docDir = dirname3(fileURLToPath2(uri));
71726
+ const docDir = dirname3(fileURLToPath3(uri));
71672
71727
  let search = docDir;
71673
71728
  for (let i2 = 0; i2 < 10; i2++) {
71674
71729
  if (findConfigFile(search)) return search;
@@ -72298,12 +72353,12 @@ var server_exports2 = {};
72298
72353
  __export(server_exports2, {
72299
72354
  startServer: () => startServer
72300
72355
  });
72301
- import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL6 } from "node:url";
72356
+ import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL6 } from "node:url";
72302
72357
  import { readFileSync as readFileSync10 } from "node:fs";
72303
72358
  import { basename as basename2 } from "node:path";
72304
72359
  function uriToFsPath(uri) {
72305
72360
  try {
72306
- return fileURLToPath3(uri);
72361
+ return fileURLToPath4(uri);
72307
72362
  } catch {
72308
72363
  return uri;
72309
72364
  }
@@ -72539,7 +72594,7 @@ var init_server4 = __esm({
72539
72594
 
72540
72595
  // src/bin.ts
72541
72596
  var args = process.argv.slice(2);
72542
- var VERSION = "0.14.1";
72597
+ var VERSION = "0.14.2";
72543
72598
  var HELP = `spindle-lsp v${VERSION}
72544
72599
  Language Server Protocol server for Spindle story format
72545
72600