@rohal12/spindle-lsp 0.14.1 → 0.14.3
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 +334 -316
- package/dist/bin.js.map +4 -4
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -3039,6 +3039,40 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
3039
3039
|
}
|
|
3040
3040
|
});
|
|
3041
3041
|
|
|
3042
|
+
// src/core/workspace/file-inputs.ts
|
|
3043
|
+
import { readFileSync, statSync } from "node:fs";
|
|
3044
|
+
import { resolve } from "node:path";
|
|
3045
|
+
async function resolveFiles(pattern, cwd) {
|
|
3046
|
+
let input = pattern;
|
|
3047
|
+
let directory = cwd;
|
|
3048
|
+
const literal3 = resolve(cwd, pattern);
|
|
3049
|
+
try {
|
|
3050
|
+
const stat = statSync(literal3);
|
|
3051
|
+
if (stat.isFile()) return [literal3];
|
|
3052
|
+
if (stat.isDirectory()) {
|
|
3053
|
+
directory = literal3;
|
|
3054
|
+
input = "**/*.{tw,twee}";
|
|
3055
|
+
}
|
|
3056
|
+
} catch (error48) {
|
|
3057
|
+
const code = error48.code;
|
|
3058
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") throw error48;
|
|
3059
|
+
}
|
|
3060
|
+
return [...new Set(await Ze(input, { cwd: directory, absolute: true, nodir: true }))];
|
|
3061
|
+
}
|
|
3062
|
+
function readFileContents(files) {
|
|
3063
|
+
return new Map(files.map((file2) => [file2, readFileSync(file2, "utf8")]));
|
|
3064
|
+
}
|
|
3065
|
+
async function resolveInputs(patterns, cwd) {
|
|
3066
|
+
const files = await Promise.all(patterns.map((pattern) => resolveFiles(pattern, cwd)));
|
|
3067
|
+
return [...new Set(files.flat())];
|
|
3068
|
+
}
|
|
3069
|
+
var init_file_inputs = __esm({
|
|
3070
|
+
"src/core/workspace/file-inputs.ts"() {
|
|
3071
|
+
"use strict";
|
|
3072
|
+
init_index_min();
|
|
3073
|
+
}
|
|
3074
|
+
});
|
|
3075
|
+
|
|
3042
3076
|
// node_modules/@rohal12/spindle/dist/pkg/story-variables.js
|
|
3043
3077
|
function isSigil(c) {
|
|
3044
3078
|
return c !== void 0 && SIGIL_CHARS.has(c);
|
|
@@ -16619,7 +16653,7 @@ var init_tooling = __esm({
|
|
|
16619
16653
|
|
|
16620
16654
|
// src/core/workspace/document-store.ts
|
|
16621
16655
|
import { EventEmitter } from "node:events";
|
|
16622
|
-
import { readFileSync } from "node:fs";
|
|
16656
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
16623
16657
|
import { pathToFileURL } from "node:url";
|
|
16624
16658
|
function stripBom(text2) {
|
|
16625
16659
|
return text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
@@ -16667,7 +16701,7 @@ var init_document_store = __esm({
|
|
|
16667
16701
|
loadFromDisk(paths) {
|
|
16668
16702
|
for (const filePath of paths) {
|
|
16669
16703
|
try {
|
|
16670
|
-
const text2 =
|
|
16704
|
+
const text2 = readFileSync2(filePath, "utf-8");
|
|
16671
16705
|
const uri = pathToFileURL(filePath).href;
|
|
16672
16706
|
this.open(uri, text2);
|
|
16673
16707
|
} catch {
|
|
@@ -16681,31 +16715,32 @@ var init_document_store = __esm({
|
|
|
16681
16715
|
// src/core/parsing/passage-parser.ts
|
|
16682
16716
|
function parsePassageHeader(line, lineNumber) {
|
|
16683
16717
|
const bomLength = lineNumber === 0 && line.charCodeAt(0) === 65279 ? 1 : 0;
|
|
16684
|
-
const escaped = line.
|
|
16685
|
-
const
|
|
16686
|
-
if (!
|
|
16687
|
-
const
|
|
16688
|
-
const
|
|
16689
|
-
|
|
16690
|
-
const
|
|
16691
|
-
const
|
|
16692
|
-
const
|
|
16693
|
-
const name = line.substring(nameStart, nameEnd).trim();
|
|
16718
|
+
const escaped = line.replace(/\\./g, "ec");
|
|
16719
|
+
const prefix = /^::\s*/.exec(escaped.slice(bomLength));
|
|
16720
|
+
if (!prefix) return null;
|
|
16721
|
+
const nameStart = bomLength + prefix[0].length;
|
|
16722
|
+
const delimiter = /[\[\]{}]/g;
|
|
16723
|
+
delimiter.lastIndex = nameStart;
|
|
16724
|
+
const first = delimiter.exec(escaped);
|
|
16725
|
+
const nameEnd = first?.index ?? line.length;
|
|
16726
|
+
const name = line.slice(nameStart, nameEnd).trim();
|
|
16694
16727
|
if (!name) return null;
|
|
16695
|
-
|
|
16696
|
-
if (/[\[\]\{\}]/.test(escapedName)) return null;
|
|
16697
|
-
const tagsStr = rawTags.trim();
|
|
16728
|
+
let rest = nameEnd;
|
|
16698
16729
|
let tags = [];
|
|
16699
|
-
if (
|
|
16700
|
-
const
|
|
16701
|
-
if (/[\[
|
|
16702
|
-
|
|
16730
|
+
if (escaped[rest] === "[") {
|
|
16731
|
+
const end = escaped.indexOf("]", rest + 1);
|
|
16732
|
+
if (end === -1 || /[\[{}]/.test(escaped.slice(rest + 1, end))) return null;
|
|
16733
|
+
const decoded = line.slice(rest + 1, end).replace(/\\(.)/g, "$1").trim();
|
|
16734
|
+
tags = decoded ? decoded.split(/\s+/) : [];
|
|
16735
|
+
rest = end + 1;
|
|
16736
|
+
while (rest < line.length && /\s/.test(escaped[rest])) rest++;
|
|
16703
16737
|
}
|
|
16704
16738
|
let meta3;
|
|
16705
|
-
|
|
16706
|
-
|
|
16739
|
+
if (rest < line.length) {
|
|
16740
|
+
const raw = line.slice(rest).trim();
|
|
16741
|
+
if (escaped[rest] !== "{" || !raw.endsWith("}")) return null;
|
|
16707
16742
|
try {
|
|
16708
|
-
meta3 = JSON.parse(
|
|
16743
|
+
meta3 = JSON.parse(raw);
|
|
16709
16744
|
} catch {
|
|
16710
16745
|
return null;
|
|
16711
16746
|
}
|
|
@@ -16738,11 +16773,10 @@ function isScriptOrStylesheetPassage(passage) {
|
|
|
16738
16773
|
function isMarkupPassage(passage) {
|
|
16739
16774
|
return !(passage.name !== void 0 && NON_MARKUP_PASSAGES.has(passage.name)) && !isScriptOrStylesheetPassage(passage);
|
|
16740
16775
|
}
|
|
16741
|
-
var
|
|
16776
|
+
var SPECIAL_PASSAGES, CODE_PASSAGE_TAGS, RESERVED_PASSAGE_NAMES, NON_MARKUP_PASSAGES;
|
|
16742
16777
|
var init_passage_parser = __esm({
|
|
16743
16778
|
"src/core/parsing/passage-parser.ts"() {
|
|
16744
16779
|
"use strict";
|
|
16745
|
-
passageHeaderRegex = /^(::\s+)(.*?)(\[.*?\]\s*)?(\{.*?\}\s*)?\r?$/;
|
|
16746
16780
|
SPECIAL_PASSAGES = /* @__PURE__ */ new Set([
|
|
16747
16781
|
"StoryVariables",
|
|
16748
16782
|
"StoryInit",
|
|
@@ -24255,8 +24289,8 @@ var require_dist = __commonJS({
|
|
|
24255
24289
|
});
|
|
24256
24290
|
|
|
24257
24291
|
// src/core/workspace/config-loader.ts
|
|
24258
|
-
import { readFileSync as
|
|
24259
|
-
import { join, resolve } from "node:path";
|
|
24292
|
+
import { readFileSync as readFileSync3, existsSync } from "node:fs";
|
|
24293
|
+
import { join, resolve as resolve2 } from "node:path";
|
|
24260
24294
|
function parseConfig(content, format) {
|
|
24261
24295
|
if (!content.trim()) {
|
|
24262
24296
|
return { macros: {} };
|
|
@@ -24316,7 +24350,7 @@ function findConfigRoot(directory) {
|
|
|
24316
24350
|
let search = directory;
|
|
24317
24351
|
for (let i2 = 0; i2 < 10; i2++) {
|
|
24318
24352
|
if (findConfigFile(search)) return search;
|
|
24319
|
-
const parent =
|
|
24353
|
+
const parent = resolve2(search, "..");
|
|
24320
24354
|
if (parent === search) break;
|
|
24321
24355
|
search = parent;
|
|
24322
24356
|
}
|
|
@@ -24325,7 +24359,7 @@ function findConfigRoot(directory) {
|
|
|
24325
24359
|
function loadConfigFile(configPath) {
|
|
24326
24360
|
let content;
|
|
24327
24361
|
try {
|
|
24328
|
-
content =
|
|
24362
|
+
content = readFileSync3(configPath, "utf-8");
|
|
24329
24363
|
} catch (err) {
|
|
24330
24364
|
const reason = err?.code === "ENOENT" ? "file not found" : err instanceof Error ? err.message : String(err);
|
|
24331
24365
|
throw new Error(`Cannot read config file '${configPath}': ${reason}`);
|
|
@@ -24343,7 +24377,7 @@ function loadConfigFromDisk(workspaceRoot) {
|
|
|
24343
24377
|
if (!configPath) {
|
|
24344
24378
|
return { ...EMPTY_CONFIG };
|
|
24345
24379
|
}
|
|
24346
|
-
const content =
|
|
24380
|
+
const content = readFileSync3(configPath, "utf-8");
|
|
24347
24381
|
const format = configPath.endsWith(".json") ? "json" : "yaml";
|
|
24348
24382
|
return parseConfig(content, format);
|
|
24349
24383
|
}
|
|
@@ -24365,6 +24399,12 @@ var init_config_loader = __esm({
|
|
|
24365
24399
|
});
|
|
24366
24400
|
|
|
24367
24401
|
// src/core/workspace/macro-registry.ts
|
|
24402
|
+
function applySupplement(info, entry) {
|
|
24403
|
+
for (const field of ["description", "parameters", "parameterDocs", "children", "parents", "skipArgs"]) {
|
|
24404
|
+
if (entry[field] !== void 0) Object.assign(info, { [field]: entry[field] });
|
|
24405
|
+
}
|
|
24406
|
+
if (entry.container !== void 0) info.block = entry.container;
|
|
24407
|
+
}
|
|
24368
24408
|
var MacroRegistry;
|
|
24369
24409
|
var init_macro_registry2 = __esm({
|
|
24370
24410
|
"src/core/workspace/macro-registry.ts"() {
|
|
@@ -24537,30 +24577,20 @@ var init_macro_registry2 = __esm({
|
|
|
24537
24577
|
const found = this.discovered.get(key);
|
|
24538
24578
|
if (!found) return base;
|
|
24539
24579
|
const info = {
|
|
24540
|
-
|
|
24541
|
-
|
|
24542
|
-
|
|
24543
|
-
subMacros: found.subMacros?.length ? found.subMacros : base?.subMacros ?? [],
|
|
24580
|
+
name: found.name,
|
|
24581
|
+
block: found.block ?? false,
|
|
24582
|
+
subMacros: found.subMacros ?? [],
|
|
24544
24583
|
source: "user",
|
|
24545
|
-
storeVar: found.storeVar
|
|
24546
|
-
interpolate: found.interpolate
|
|
24547
|
-
merged: found.merged
|
|
24548
|
-
description: found.description
|
|
24584
|
+
storeVar: found.storeVar,
|
|
24585
|
+
interpolate: found.interpolate,
|
|
24586
|
+
merged: found.merged,
|
|
24587
|
+
description: found.description,
|
|
24549
24588
|
// A definition replaces the macro it names, parameters included
|
|
24550
24589
|
parameterDefs: found.parameterDefs,
|
|
24551
|
-
|
|
24552
|
-
parents: found.parents ? [.../* @__PURE__ */ new Set([...base?.parents ?? [], ...found.parents])] : base?.parents
|
|
24590
|
+
parents: found.parents
|
|
24553
24591
|
};
|
|
24554
24592
|
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
|
-
}
|
|
24593
|
+
if (config2) applySupplement(info, config2);
|
|
24564
24594
|
return info;
|
|
24565
24595
|
}
|
|
24566
24596
|
/** Merge a set of supplement/config entries into the registry. */
|
|
@@ -24569,13 +24599,7 @@ var init_macro_registry2 = __esm({
|
|
|
24569
24599
|
const key = rawKey.toLowerCase();
|
|
24570
24600
|
const existing = this.macros.get(key);
|
|
24571
24601
|
if (existing) {
|
|
24572
|
-
|
|
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;
|
|
24602
|
+
applySupplement(existing, entry);
|
|
24579
24603
|
} else {
|
|
24580
24604
|
this.macros.set(key, {
|
|
24581
24605
|
name: entry.name ?? rawKey,
|
|
@@ -24970,6 +24994,27 @@ var init_variable_tracker = __esm({
|
|
|
24970
24994
|
getUsages(name) {
|
|
24971
24995
|
return usagesOf(this.usagesByUri, name);
|
|
24972
24996
|
}
|
|
24997
|
+
/** The executable usage or declaration containing the cursor, in source coordinates. */
|
|
24998
|
+
referenceAt(uri, position) {
|
|
24999
|
+
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);
|
|
25000
|
+
let atEnd = null;
|
|
25001
|
+
for (const [sigil, usages, declarations] of [
|
|
25002
|
+
["$", this.usagesByUri.get(uri), this.variables.declared],
|
|
25003
|
+
["%", this.transientUsagesByUri.get(uri), this.transients.declared]
|
|
25004
|
+
]) {
|
|
25005
|
+
const candidates = (usages ?? []).map((u) => ({ name: u.baseName, range: u.range }));
|
|
25006
|
+
for (const [name, declaration] of declarations) {
|
|
25007
|
+
if (declaration.declarationUri === uri && declaration.declarationRange) candidates.push({ name, range: declaration.declarationRange });
|
|
25008
|
+
}
|
|
25009
|
+
for (const candidate of candidates) {
|
|
25010
|
+
if (!contains(candidate.range)) continue;
|
|
25011
|
+
const symbol2 = { sigil, ...candidate };
|
|
25012
|
+
if (position.line !== candidate.range.end.line || position.character < candidate.range.end.character) return symbol2;
|
|
25013
|
+
atEnd ??= symbol2;
|
|
25014
|
+
}
|
|
25015
|
+
}
|
|
25016
|
+
return atEnd;
|
|
25017
|
+
}
|
|
24973
25018
|
/** Whether a StoryVariables passage has been parsed. */
|
|
24974
25019
|
hasStoryVariables() {
|
|
24975
25020
|
return this.variables.present;
|
|
@@ -25076,6 +25121,7 @@ var init_widget_registry = __esm({
|
|
|
25076
25121
|
const { name, tags } = markup.passage;
|
|
25077
25122
|
for (const definition of widgetDefinitions([{ name, tags, content: markup.content }], known)) {
|
|
25078
25123
|
this.widgets.set(definition.name.toLowerCase(), {
|
|
25124
|
+
tooling: definition,
|
|
25079
25125
|
name: definition.name,
|
|
25080
25126
|
params: definition.params,
|
|
25081
25127
|
uri: markup.passage.uri,
|
|
@@ -25163,7 +25209,7 @@ var init_markup_index = __esm({
|
|
|
25163
25209
|
});
|
|
25164
25210
|
|
|
25165
25211
|
// src/core/workspace/macro-sources.ts
|
|
25166
|
-
import { existsSync as existsSync2, readFileSync as
|
|
25212
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
25167
25213
|
import { dirname, isAbsolute, join as join2, relative } from "node:path";
|
|
25168
25214
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
25169
25215
|
function isExcludedSegment(segment) {
|
|
@@ -25212,7 +25258,7 @@ async function addProjectMacroSources(contents, dir) {
|
|
|
25212
25258
|
const uri = pathToFileURL2(filePath).toString();
|
|
25213
25259
|
if (contents.has(uri)) continue;
|
|
25214
25260
|
try {
|
|
25215
|
-
contents.set(uri,
|
|
25261
|
+
contents.set(uri, readFileSync4(filePath, "utf-8"));
|
|
25216
25262
|
} catch {
|
|
25217
25263
|
}
|
|
25218
25264
|
}
|
|
@@ -25231,8 +25277,8 @@ var init_macro_sources = __esm({
|
|
|
25231
25277
|
});
|
|
25232
25278
|
|
|
25233
25279
|
// src/core/workspace/spindle-version.ts
|
|
25234
|
-
import { existsSync as existsSync3, readFileSync as
|
|
25235
|
-
import { dirname as dirname2, join as join3, resolve as
|
|
25280
|
+
import { existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
|
|
25281
|
+
import { dirname as dirname2, join as join3, resolve as resolve3 } from "node:path";
|
|
25236
25282
|
function parseSpindleVersion(text2) {
|
|
25237
25283
|
const m = /^\s*v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?\s*$/.exec(text2);
|
|
25238
25284
|
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : void 0;
|
|
@@ -25246,12 +25292,12 @@ function atLeast(version2, minimum) {
|
|
|
25246
25292
|
}
|
|
25247
25293
|
function readInstalledSpindleVersion(startDir) {
|
|
25248
25294
|
const target = join3("node_modules", "@rohal12", "spindle", "package.json");
|
|
25249
|
-
let dir =
|
|
25295
|
+
let dir = resolve3(startDir);
|
|
25250
25296
|
for (; ; ) {
|
|
25251
25297
|
const candidate = join3(dir, target);
|
|
25252
25298
|
if (existsSync3(candidate)) {
|
|
25253
25299
|
try {
|
|
25254
|
-
const version2 = JSON.parse(
|
|
25300
|
+
const version2 = JSON.parse(readFileSync5(candidate, "utf-8")).version;
|
|
25255
25301
|
return typeof version2 === "string" && parseSpindleVersion(version2) ? version2 : void 0;
|
|
25256
25302
|
} catch {
|
|
25257
25303
|
return void 0;
|
|
@@ -25282,7 +25328,7 @@ var init_spindle_version = __esm({
|
|
|
25282
25328
|
});
|
|
25283
25329
|
|
|
25284
25330
|
// src/core/workspace/story-format.ts
|
|
25285
|
-
import { readFileSync as
|
|
25331
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
25286
25332
|
function isSpindleFormatName(name) {
|
|
25287
25333
|
return name.trim().toLowerCase() === "spindle";
|
|
25288
25334
|
}
|
|
@@ -25362,7 +25408,7 @@ async function findStoryFormat(texts, dir) {
|
|
|
25362
25408
|
const projectTexts = [];
|
|
25363
25409
|
for (const file2 of await findProjectFiles(findProjectRoot(dir), "**/*.{tw,twee}")) {
|
|
25364
25410
|
try {
|
|
25365
|
-
projectTexts.push(stripBom(
|
|
25411
|
+
projectTexts.push(stripBom(readFileSync6(file2, "utf-8")));
|
|
25366
25412
|
} catch {
|
|
25367
25413
|
}
|
|
25368
25414
|
}
|
|
@@ -25389,7 +25435,7 @@ async function findSpindleTarget(texts, dir) {
|
|
|
25389
25435
|
const projectTexts = [];
|
|
25390
25436
|
for (const file2 of await findProjectFiles(findProjectRoot(dir), "**/*.{tw,twee}")) {
|
|
25391
25437
|
try {
|
|
25392
|
-
projectTexts.push(
|
|
25438
|
+
projectTexts.push(readFileSync6(file2, "utf-8"));
|
|
25393
25439
|
} catch {
|
|
25394
25440
|
}
|
|
25395
25441
|
}
|
|
@@ -25865,7 +25911,7 @@ var init_workspace_model = __esm({
|
|
|
25865
25911
|
text: (uri) => this.documents.getText(uri),
|
|
25866
25912
|
passages: (uri) => this.passages.getPassagesInDocument(uri),
|
|
25867
25913
|
context: () => ({
|
|
25868
|
-
macros: this.
|
|
25914
|
+
macros: this.toolingMacros(),
|
|
25869
25915
|
isBlock: (name) => this.isContainer(name)
|
|
25870
25916
|
})
|
|
25871
25917
|
});
|
|
@@ -26042,60 +26088,38 @@ var init_workspace_model = __esm({
|
|
|
26042
26088
|
this.markup.invalidate();
|
|
26043
26089
|
this.declaredVersion = storyDataFormatVersion(this.passages.getAllPassages(), (uri) => this.documents.getText(uri));
|
|
26044
26090
|
this.target = resolveSpindleTarget(this.installedVersion, this.declaredVersion);
|
|
26045
|
-
const
|
|
26046
|
-
|
|
26047
|
-
|
|
26048
|
-
|
|
26049
|
-
|
|
26050
|
-
|
|
26051
|
-
|
|
26052
|
-
|
|
26053
|
-
|
|
26054
|
-
|
|
26055
|
-
|
|
26056
|
-
}
|
|
26057
|
-
}
|
|
26058
|
-
const content = lines.slice(contentStart, contentEnd).join("\n");
|
|
26059
|
-
this.variables.parseStoryVariables(content, contentStart, storyVars.uri);
|
|
26060
|
-
}
|
|
26061
|
-
} else {
|
|
26062
|
-
this.variables.clearStoryVariables();
|
|
26063
|
-
}
|
|
26064
|
-
const storyTransients = this.passages.getStoryTransients();
|
|
26065
|
-
if (storyTransients) {
|
|
26066
|
-
const text2 = this.documents.getText(storyTransients.uri);
|
|
26067
|
-
if (text2) {
|
|
26068
|
-
const lines = text2.split("\n");
|
|
26069
|
-
const contentStart = storyTransients.headerEnd.end.line + 1;
|
|
26070
|
-
let contentEnd = lines.length;
|
|
26071
|
-
for (let i2 = contentStart; i2 < lines.length; i2++) {
|
|
26072
|
-
if (/^\uFEFF?::\s+/.test(lines[i2])) {
|
|
26073
|
-
contentEnd = i2;
|
|
26074
|
-
break;
|
|
26075
|
-
}
|
|
26076
|
-
}
|
|
26077
|
-
const content = lines.slice(contentStart, contentEnd).join("\n");
|
|
26078
|
-
this.variables.parseStoryTransients(content, contentStart, storyTransients.uri);
|
|
26079
|
-
}
|
|
26080
|
-
} else {
|
|
26081
|
-
this.variables.clearStoryTransients();
|
|
26082
|
-
}
|
|
26083
|
-
const documents = this.documents.getUris().flatMap((uri) => {
|
|
26091
|
+
const declarations = (name) => {
|
|
26092
|
+
const passage = this.passages.getPassage(name);
|
|
26093
|
+
return passage ? this.markup.get(passage.uri)?.passages.find((p) => p.passage === passage) : void 0;
|
|
26094
|
+
};
|
|
26095
|
+
const variables = declarations("StoryVariables");
|
|
26096
|
+
if (variables) this.variables.parseStoryVariables(variables.content, variables.passage.headerEnd.end.line + 1, variables.doc.uri);
|
|
26097
|
+
else this.variables.clearStoryVariables();
|
|
26098
|
+
const transients = declarations("StoryTransients");
|
|
26099
|
+
if (transients) this.variables.parseStoryTransients(transients.content, transients.passage.headerEnd.end.line + 1, transients.doc.uri);
|
|
26100
|
+
else this.variables.clearStoryTransients();
|
|
26101
|
+
const readDocuments = () => this.documents.getUris().flatMap((uri) => {
|
|
26084
26102
|
const markup = isMacroSource(uri) ? void 0 : this.markup.get(uri);
|
|
26085
26103
|
return markup ? [markup] : [];
|
|
26086
26104
|
});
|
|
26087
26105
|
const markups = /* @__PURE__ */ new Map();
|
|
26088
|
-
for (const doc of
|
|
26106
|
+
for (const doc of readDocuments()) for (const passage of doc.passages) markups.set(passage.passage, passage);
|
|
26089
26107
|
this.widgets.scan(
|
|
26090
26108
|
this.passages.getAllPassages().flatMap((passage) => markups.get(passage) ?? []),
|
|
26091
26109
|
this.macros.toolingMacros()
|
|
26092
26110
|
);
|
|
26111
|
+
this.markup.invalidate();
|
|
26093
26112
|
this.widgets.clearInvocations();
|
|
26094
|
-
for (const doc of
|
|
26113
|
+
for (const doc of readDocuments()) {
|
|
26095
26114
|
this.variables.scanDocument(doc.uri, doc.text, doc);
|
|
26096
26115
|
this.widgets.recordInvocations(doc.uri, doc.passages);
|
|
26097
26116
|
}
|
|
26098
26117
|
}
|
|
26118
|
+
/** All runtime metadata, with real macros taking precedence over widgets. */
|
|
26119
|
+
toolingMacros() {
|
|
26120
|
+
const macros = this.macros.toolingMacros();
|
|
26121
|
+
return [...macros, ...this.widgets.getAllWidgets().filter((widget) => !this.macros.getMacro(widget.name)).map((widget) => ({ name: widget.name, block: widget.block, subMacros: [], widget: widget.tooling }))];
|
|
26122
|
+
}
|
|
26099
26123
|
/** Debounce modelReady emission. */
|
|
26100
26124
|
scheduleModelReady() {
|
|
26101
26125
|
if (this.debounceTimer) {
|
|
@@ -26205,6 +26229,36 @@ var init_diagnostic_codes = __esm({
|
|
|
26205
26229
|
}
|
|
26206
26230
|
});
|
|
26207
26231
|
|
|
26232
|
+
// src/core/markup/source-view.ts
|
|
26233
|
+
function viewIndex(view, offset2) {
|
|
26234
|
+
if (!view.sourceOffsets) return offset2 - view.offset;
|
|
26235
|
+
let low = 0;
|
|
26236
|
+
let high = view.sourceOffsets.length - 1;
|
|
26237
|
+
while (low < high) {
|
|
26238
|
+
const mid = Math.ceil((low + high) / 2);
|
|
26239
|
+
if (view.sourceOffsets[mid] <= offset2) low = mid;
|
|
26240
|
+
else high = mid - 1;
|
|
26241
|
+
}
|
|
26242
|
+
return low;
|
|
26243
|
+
}
|
|
26244
|
+
function textAt(passage, start, end) {
|
|
26245
|
+
return passage.pieces.filter((piece) => piece.kind === "text" && piece.offset <= start && pieceOffset(piece, piece.text.length) >= end).at(-1);
|
|
26246
|
+
}
|
|
26247
|
+
function sourceView(passage, start, end) {
|
|
26248
|
+
const owner = passage.pieces.filter((piece) => {
|
|
26249
|
+
const value = piece.kind === "text" ? piece.text : piece.kind === "code" ? piece.code : void 0;
|
|
26250
|
+
return value !== void 0 && piece.offset <= start && pieceOffset(piece, value.length) >= end;
|
|
26251
|
+
}).at(-1);
|
|
26252
|
+
if (owner?.kind === "code") return { ...owner, text: owner.code };
|
|
26253
|
+
return owner?.kind === "text" ? owner : { offset: 0, text: passage.content };
|
|
26254
|
+
}
|
|
26255
|
+
var init_source_view = __esm({
|
|
26256
|
+
"src/core/markup/source-view.ts"() {
|
|
26257
|
+
"use strict";
|
|
26258
|
+
init_tooling();
|
|
26259
|
+
}
|
|
26260
|
+
});
|
|
26261
|
+
|
|
26208
26262
|
// src/core/parsing/argument-lexer.ts
|
|
26209
26263
|
function lexArguments(source) {
|
|
26210
26264
|
let from = 0;
|
|
@@ -26553,6 +26607,7 @@ var TypeError2, TypeWarning, parameterTypes, LEX_LIMIT, wsRe, identStartRe, iden
|
|
|
26553
26607
|
var init_parameter_validator = __esm({
|
|
26554
26608
|
"src/core/parsing/parameter-validator.ts"() {
|
|
26555
26609
|
"use strict";
|
|
26610
|
+
init_tooling();
|
|
26556
26611
|
init_argument_lexer();
|
|
26557
26612
|
TypeError2 = class {
|
|
26558
26613
|
constructor(message) {
|
|
@@ -26666,7 +26721,8 @@ var init_parameter_validator = __esm({
|
|
|
26666
26721
|
validate(arg, _args, _index, state) {
|
|
26667
26722
|
let passageName;
|
|
26668
26723
|
if (arg.type === 0 /* String */) {
|
|
26669
|
-
|
|
26724
|
+
const target = passageTarget(arg.text);
|
|
26725
|
+
if (target.kind === "name") passageName = target.name;
|
|
26670
26726
|
} else if (arg.type === 8 /* Bareword */) {
|
|
26671
26727
|
passageName = arg.text;
|
|
26672
26728
|
} else if (arg.type === 1 /* Number */) {
|
|
@@ -26675,7 +26731,6 @@ var init_parameter_validator = __esm({
|
|
|
26675
26731
|
passageName = "NaN";
|
|
26676
26732
|
}
|
|
26677
26733
|
if (passageName !== void 0) {
|
|
26678
|
-
passageName = passageName.replace(/\\/g, "");
|
|
26679
26734
|
if (state && state.passages.length > 0) {
|
|
26680
26735
|
if (!state.passages.includes(passageName)) {
|
|
26681
26736
|
return new TypeWarning(`Nonexistent passage: "${passageName}"`);
|
|
@@ -27167,7 +27222,9 @@ function fromMarkup(passage, found, workspace) {
|
|
|
27167
27222
|
if (element) code = DiagnosticCode.MalformedElement;
|
|
27168
27223
|
else if (found.code === "stray-closer" && !workspace.isContainer(name)) code = DiagnosticCode.IllegalClosingTag;
|
|
27169
27224
|
if (found.code === "unclosed-block") {
|
|
27170
|
-
|
|
27225
|
+
const owner = textAt(passage, found.start, found.end);
|
|
27226
|
+
const end = owner ? pieceOffset(owner, owner.text.trimEnd().length) : passage.content.trimEnd().length;
|
|
27227
|
+
data2 = { kind: "unclosed-block", closer: element ? `</${name}>` : `{/${name}}`, at: passage.position(end) };
|
|
27171
27228
|
}
|
|
27172
27229
|
break;
|
|
27173
27230
|
}
|
|
@@ -27399,10 +27456,9 @@ function loopDiagnostics(passage, token, ancestors) {
|
|
|
27399
27456
|
if (!loop || !close) return [];
|
|
27400
27457
|
const targets = macro === "computed" ? computedTemporaryTarget(token.rawArgs) : setTemporaryTargets(token.rawArgs);
|
|
27401
27458
|
const bodyStart = loop.node.token.end;
|
|
27402
|
-
const body = passage.content.slice(bodyStart, close.start);
|
|
27403
27459
|
const diagnostics = [];
|
|
27404
27460
|
for (const target of targets) {
|
|
27405
|
-
if (!isReadInBody(
|
|
27461
|
+
if (!isReadInBody(passage, bodyStart, close.start, target.name, token.start, token.end)) continue;
|
|
27406
27462
|
const start = token.argsStart + target.offset;
|
|
27407
27463
|
diagnostics.push(makeDiag(
|
|
27408
27464
|
passage.range(start, start + 1 + target.name.length),
|
|
@@ -27412,22 +27468,28 @@ function loopDiagnostics(passage, token, ancestors) {
|
|
|
27412
27468
|
}
|
|
27413
27469
|
return diagnostics;
|
|
27414
27470
|
}
|
|
27415
|
-
function isReadInBody(
|
|
27416
|
-
const
|
|
27417
|
-
|
|
27418
|
-
|
|
27419
|
-
|
|
27420
|
-
|
|
27421
|
-
|
|
27422
|
-
|
|
27423
|
-
|
|
27471
|
+
function isReadInBody(passage, bodyStart, bodyEnd, name, macroStart, macroEnd) {
|
|
27472
|
+
const eligible = (offset2) => offset2 >= bodyStart && offset2 < bodyEnd && !(offset2 >= macroStart && offset2 < macroEnd);
|
|
27473
|
+
for (const token of markupTokens(passage)) {
|
|
27474
|
+
if (token.type === "variable" && token.scope === "temporary" && token.name.split(".")[0] === name && eligible(token.start)) return true;
|
|
27475
|
+
}
|
|
27476
|
+
for (const piece of passage.pieces) {
|
|
27477
|
+
if (piece.kind !== "code") continue;
|
|
27478
|
+
let read = false;
|
|
27479
|
+
lexJs(piece.code, {
|
|
27480
|
+
variable(sigil, found, index, _nesting, end) {
|
|
27481
|
+
if (sigil !== "_" || found !== name || !eligible(pieceOffset(piece, index))) return;
|
|
27482
|
+
if (!/^\s*=(?![=>])/.test(maskLiterals(piece.code.slice(end)))) read = true;
|
|
27483
|
+
}
|
|
27484
|
+
}, piece.goal);
|
|
27485
|
+
if (read) return true;
|
|
27424
27486
|
}
|
|
27425
27487
|
return false;
|
|
27426
27488
|
}
|
|
27427
27489
|
function argumentDiagnostics(passage, workspace) {
|
|
27428
27490
|
const diagnostics = [];
|
|
27429
27491
|
const passageNames = Array.from(workspace.passages.getAllPassages(), (candidate) => candidate.name);
|
|
27430
|
-
for (const token of passage.isMarkup ? passage
|
|
27492
|
+
for (const token of passage.isMarkup ? macroTokens(passage) : []) {
|
|
27431
27493
|
if (token.type !== "macro" || token.isClose) continue;
|
|
27432
27494
|
const info = workspace.macros.getMacro(token.name);
|
|
27433
27495
|
if (!info?.parameters || info.skipArgs || SPINDLE_MACROS.has(token.name.toLowerCase())) continue;
|
|
@@ -27588,6 +27650,7 @@ var init_diagnostics = __esm({
|
|
|
27588
27650
|
init_tooling();
|
|
27589
27651
|
init_diagnostic_codes();
|
|
27590
27652
|
init_tokens();
|
|
27653
|
+
init_source_view();
|
|
27591
27654
|
init_argument_lexer();
|
|
27592
27655
|
init_parameter_validator();
|
|
27593
27656
|
init_link_parser();
|
|
@@ -27830,8 +27893,7 @@ var check_exports = {};
|
|
|
27830
27893
|
__export(check_exports, {
|
|
27831
27894
|
runCheck: () => runCheck
|
|
27832
27895
|
});
|
|
27833
|
-
import {
|
|
27834
|
-
import { resolve as resolve3 } from "node:path";
|
|
27896
|
+
import { resolve as resolve4 } from "node:path";
|
|
27835
27897
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
27836
27898
|
function parseArgs(args2) {
|
|
27837
27899
|
const options = {
|
|
@@ -27907,22 +27969,21 @@ async function runCheck(args2) {
|
|
|
27907
27969
|
let explicitConfig = null;
|
|
27908
27970
|
if (options.configPath) {
|
|
27909
27971
|
try {
|
|
27910
|
-
explicitConfig = loadConfigFile(
|
|
27972
|
+
explicitConfig = loadConfigFile(resolve4(cwd, options.configPath));
|
|
27911
27973
|
} catch (err) {
|
|
27912
27974
|
console.error(`spindle-lsp check: ${err instanceof Error ? err.message : String(err)}`);
|
|
27913
27975
|
return 2;
|
|
27914
27976
|
}
|
|
27915
27977
|
}
|
|
27916
|
-
|
|
27917
|
-
|
|
27918
|
-
|
|
27919
|
-
|
|
27920
|
-
|
|
27921
|
-
|
|
27922
|
-
});
|
|
27923
|
-
|
|
27978
|
+
let uniqueFiles;
|
|
27979
|
+
let contents;
|
|
27980
|
+
try {
|
|
27981
|
+
uniqueFiles = await resolveInputs(options.patterns, cwd);
|
|
27982
|
+
contents = readFileContents(uniqueFiles);
|
|
27983
|
+
} catch (error48) {
|
|
27984
|
+
console.error(`spindle-lsp check: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
27985
|
+
return 2;
|
|
27924
27986
|
}
|
|
27925
|
-
const uniqueFiles = [...new Set(files)];
|
|
27926
27987
|
if (uniqueFiles.length === 0) {
|
|
27927
27988
|
if (options.format === "pretty") {
|
|
27928
27989
|
console.log("No files found");
|
|
@@ -27946,15 +28007,7 @@ async function runCheck(args2) {
|
|
|
27946
28007
|
return 1;
|
|
27947
28008
|
}
|
|
27948
28009
|
}
|
|
27949
|
-
const fileContents =
|
|
27950
|
-
for (const filePath of uniqueFiles) {
|
|
27951
|
-
try {
|
|
27952
|
-
const text2 = readFileSync6(filePath, "utf-8");
|
|
27953
|
-
const uri = pathToFileURL3(filePath).toString();
|
|
27954
|
-
fileContents.set(uri, text2);
|
|
27955
|
-
} catch {
|
|
27956
|
-
}
|
|
27957
|
-
}
|
|
28010
|
+
const fileContents = new Map([...contents].map(([path, text2]) => [pathToFileURL3(path).toString(), text2]));
|
|
27958
28011
|
const storyFormat = await findStoryFormat(fileContents.values(), commonDir);
|
|
27959
28012
|
if (!storyFormat.isSpindle) {
|
|
27960
28013
|
console.error(skippedFormatNote(storyFormat));
|
|
@@ -28007,7 +28060,7 @@ var SEVERITY_ORDER;
|
|
|
28007
28060
|
var init_check = __esm({
|
|
28008
28061
|
"src/cli/check.ts"() {
|
|
28009
28062
|
"use strict";
|
|
28010
|
-
|
|
28063
|
+
init_file_inputs();
|
|
28011
28064
|
init_workspace_model();
|
|
28012
28065
|
init_diagnostics();
|
|
28013
28066
|
init_config_loader();
|
|
@@ -28043,7 +28096,7 @@ function splitPassages(text2) {
|
|
|
28043
28096
|
}
|
|
28044
28097
|
}
|
|
28045
28098
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
28046
|
-
if (
|
|
28099
|
+
if (parsePassageHeader(lines[i2], i2)) {
|
|
28047
28100
|
pushPassage();
|
|
28048
28101
|
currentHeader = lines[i2];
|
|
28049
28102
|
bodyLines = [];
|
|
@@ -28056,7 +28109,7 @@ function splitPassages(text2) {
|
|
|
28056
28109
|
return passages;
|
|
28057
28110
|
}
|
|
28058
28111
|
function classifyPassage(header) {
|
|
28059
|
-
const tags = headerTags(header)
|
|
28112
|
+
const tags = headerTags(header);
|
|
28060
28113
|
if (tags.includes("script")) return "script";
|
|
28061
28114
|
if (tags.includes("stylesheet")) return "stylesheet";
|
|
28062
28115
|
return "normal";
|
|
@@ -28067,22 +28120,23 @@ function headerTags(header) {
|
|
|
28067
28120
|
const unescaped = header.replace(/\\./g, "ec");
|
|
28068
28121
|
return (unescaped.match(/\[[^\]]*\]/g) ?? []).flatMap((t) => t.slice(1, -1).split(/\s+/));
|
|
28069
28122
|
}
|
|
28070
|
-
var PASSAGE_HEADER_REGEX;
|
|
28071
28123
|
var init_segment = __esm({
|
|
28072
28124
|
"src/plugins/format/segment.ts"() {
|
|
28073
28125
|
"use strict";
|
|
28074
28126
|
init_passage_parser();
|
|
28075
|
-
PASSAGE_HEADER_REGEX = /^::\s+/;
|
|
28076
28127
|
}
|
|
28077
28128
|
});
|
|
28078
28129
|
|
|
28079
28130
|
// src/plugins/format/prettier-bridge.ts
|
|
28080
|
-
|
|
28131
|
+
import { resolve as resolve5 } from "node:path";
|
|
28132
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
28133
|
+
async function loadPrettier(filePath) {
|
|
28081
28134
|
prettier ??= import("prettier").catch(() => null);
|
|
28082
28135
|
const p = await prettier;
|
|
28083
28136
|
if (!p) return void 0;
|
|
28084
28137
|
try {
|
|
28085
|
-
const
|
|
28138
|
+
const path = filePath?.startsWith("file:") ? fileURLToPath2(filePath) : filePath;
|
|
28139
|
+
const resolved = await p.resolveConfig(path ?? resolve5(process.cwd(), "story.tw"));
|
|
28086
28140
|
return { prettier: p, options: { tabWidth: 2, ...resolved ?? {} } };
|
|
28087
28141
|
} catch {
|
|
28088
28142
|
return { prettier: p, options: { tabWidth: 2 } };
|
|
@@ -28122,7 +28176,7 @@ function dominantEol2(text2) {
|
|
|
28122
28176
|
async function formatLf2(text2, options) {
|
|
28123
28177
|
const isBlock = options?.isBlock ?? buildDefaultIsBlock(text2);
|
|
28124
28178
|
const isDedentingSubMacro = options?.isDedentingSubMacro ?? ((name) => DEFAULT_DEDENTING2.has(name.toLowerCase()));
|
|
28125
|
-
const prettier2 = await loadPrettier();
|
|
28179
|
+
const prettier2 = await loadPrettier(options?.filePath);
|
|
28126
28180
|
const passages = splitPassages(text2);
|
|
28127
28181
|
const resultLines = [];
|
|
28128
28182
|
for (let pi2 = 0; pi2 < passages.length; pi2++) {
|
|
@@ -28136,12 +28190,14 @@ async function formatLf2(text2, options) {
|
|
|
28136
28190
|
}
|
|
28137
28191
|
}
|
|
28138
28192
|
if (passage.header) {
|
|
28139
|
-
const header =
|
|
28193
|
+
const header = PASSAGE_HEADER_REGEX.test(passage.header) ? normalizePassageHeader(passage.header) : passage.header;
|
|
28140
28194
|
resultLines.push(header.replace(/\s+$/, ""));
|
|
28141
28195
|
}
|
|
28142
28196
|
if (passage.body === "") continue;
|
|
28143
|
-
const
|
|
28144
|
-
|
|
28197
|
+
const role = parsePassageHeader(passage.header, passage.startLine);
|
|
28198
|
+
const kind = classifyPassage(passage.header);
|
|
28199
|
+
const body = kind === "normal" && role && !isMarkupPassage(role) ? passage.body : await formatPassage(passage.body, {
|
|
28200
|
+
kind,
|
|
28145
28201
|
prettier: prettier2?.prettier,
|
|
28146
28202
|
prettierOptions: prettier2?.options,
|
|
28147
28203
|
isBlock,
|
|
@@ -28156,7 +28212,7 @@ async function formatRange(text2, _range, options) {
|
|
|
28156
28212
|
return formatDocument(text2, options);
|
|
28157
28213
|
}
|
|
28158
28214
|
function normalizePassageHeader(line) {
|
|
28159
|
-
const headerMatch = line.match(/^::\s
|
|
28215
|
+
const headerMatch = line.match(/^::\s*(.*)/);
|
|
28160
28216
|
if (!headerMatch) return line;
|
|
28161
28217
|
const rest = headerMatch[1];
|
|
28162
28218
|
const unescaped = rest.replace(/\\./g, "ec");
|
|
@@ -28175,14 +28231,15 @@ function normalizePassageHeader(line) {
|
|
|
28175
28231
|
}
|
|
28176
28232
|
return `:: ${name}${suffix}`;
|
|
28177
28233
|
}
|
|
28178
|
-
var
|
|
28234
|
+
var PASSAGE_HEADER_REGEX, DEFAULT_DEDENTING2, BUILTIN_CONTAINERS, formatPlugin;
|
|
28179
28235
|
var init_format = __esm({
|
|
28180
28236
|
"src/plugins/format.ts"() {
|
|
28181
28237
|
"use strict";
|
|
28182
28238
|
init_tooling();
|
|
28239
|
+
init_passage_parser();
|
|
28183
28240
|
init_segment();
|
|
28184
28241
|
init_prettier_bridge();
|
|
28185
|
-
|
|
28242
|
+
PASSAGE_HEADER_REGEX = /^(::)\s*/;
|
|
28186
28243
|
DEFAULT_DEDENTING2 = /* @__PURE__ */ new Set(["else", "elseif", "next", "case", "default"]);
|
|
28187
28244
|
BUILTIN_CONTAINERS = new Set(builtinMacros.filter((m) => m.block).map((m) => m.name.toLowerCase()));
|
|
28188
28245
|
formatPlugin = {
|
|
@@ -28200,7 +28257,7 @@ var init_format = __esm({
|
|
|
28200
28257
|
ctx.connection.onDocumentFormatting(async (params) => {
|
|
28201
28258
|
const text2 = ctx.workspace.documents.getText(params.textDocument.uri);
|
|
28202
28259
|
if (text2 === void 0) return [];
|
|
28203
|
-
const formatted = await formatDocument(text2, formatOpts);
|
|
28260
|
+
const formatted = await formatDocument(text2, { ...formatOpts, filePath: params.textDocument.uri });
|
|
28204
28261
|
if (formatted === text2) return [];
|
|
28205
28262
|
const lines = text2.split("\n");
|
|
28206
28263
|
return [{
|
|
@@ -28218,7 +28275,7 @@ var init_format = __esm({
|
|
|
28218
28275
|
start: { line: params.range.start.line, character: params.range.start.character },
|
|
28219
28276
|
end: { line: params.range.end.line, character: params.range.end.character }
|
|
28220
28277
|
};
|
|
28221
|
-
const formatted = await formatRange(text2, range, formatOpts);
|
|
28278
|
+
const formatted = await formatRange(text2, range, { ...formatOpts, filePath: params.textDocument.uri });
|
|
28222
28279
|
if (formatted === text2) return [];
|
|
28223
28280
|
const lines = text2.split("\n");
|
|
28224
28281
|
return [{
|
|
@@ -28239,7 +28296,7 @@ var format_exports = {};
|
|
|
28239
28296
|
__export(format_exports, {
|
|
28240
28297
|
runFormat: () => runFormat
|
|
28241
28298
|
});
|
|
28242
|
-
import {
|
|
28299
|
+
import { writeFileSync } from "node:fs";
|
|
28243
28300
|
function parseArgs2(args2) {
|
|
28244
28301
|
const options = {
|
|
28245
28302
|
check: false,
|
|
@@ -28275,27 +28332,19 @@ function parseArgs2(args2) {
|
|
|
28275
28332
|
async function runFormat(args2) {
|
|
28276
28333
|
const options = parseArgs2(args2);
|
|
28277
28334
|
const cwd = process.cwd();
|
|
28278
|
-
|
|
28279
|
-
|
|
28280
|
-
|
|
28281
|
-
|
|
28282
|
-
|
|
28283
|
-
|
|
28284
|
-
});
|
|
28285
|
-
|
|
28335
|
+
let uniqueFiles;
|
|
28336
|
+
let texts;
|
|
28337
|
+
try {
|
|
28338
|
+
uniqueFiles = await resolveInputs(options.patterns, cwd);
|
|
28339
|
+
texts = readFileContents(uniqueFiles);
|
|
28340
|
+
} catch (error48) {
|
|
28341
|
+
console.error(`spindle-lsp format: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
28342
|
+
return 2;
|
|
28286
28343
|
}
|
|
28287
|
-
const uniqueFiles = [...new Set(files)];
|
|
28288
28344
|
if (uniqueFiles.length === 0) {
|
|
28289
28345
|
console.log("No files found");
|
|
28290
28346
|
return 0;
|
|
28291
28347
|
}
|
|
28292
|
-
const texts = /* @__PURE__ */ new Map();
|
|
28293
|
-
for (const filePath of uniqueFiles) {
|
|
28294
|
-
try {
|
|
28295
|
-
texts.set(filePath, readFileSync7(filePath, "utf-8"));
|
|
28296
|
-
} catch {
|
|
28297
|
-
}
|
|
28298
|
-
}
|
|
28299
28348
|
const storyFormat = await findStoryFormat(texts.values(), commonDirectory(uniqueFiles));
|
|
28300
28349
|
if (!storyFormat.isSpindle) {
|
|
28301
28350
|
console.error(skippedFormatNote(storyFormat));
|
|
@@ -28308,9 +28357,10 @@ async function runFormat(args2) {
|
|
|
28308
28357
|
formatOpts.maxLineLength = options.maxLineLength;
|
|
28309
28358
|
}
|
|
28310
28359
|
const unformatted = [];
|
|
28360
|
+
let failed = false;
|
|
28311
28361
|
for (const [filePath, text2] of texts) {
|
|
28312
28362
|
try {
|
|
28313
|
-
const formatted = await formatDocument(text2, formatOpts);
|
|
28363
|
+
const formatted = await formatDocument(text2, { ...formatOpts, filePath });
|
|
28314
28364
|
if (formatted !== text2) {
|
|
28315
28365
|
if (options.check) {
|
|
28316
28366
|
const relative2 = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
|
|
@@ -28319,9 +28369,12 @@ async function runFormat(args2) {
|
|
|
28319
28369
|
writeFileSync(filePath, formatted, "utf-8");
|
|
28320
28370
|
}
|
|
28321
28371
|
}
|
|
28322
|
-
} catch {
|
|
28372
|
+
} catch (error48) {
|
|
28373
|
+
failed = true;
|
|
28374
|
+
console.error(`spindle-lsp format: ${filePath}: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
28323
28375
|
}
|
|
28324
28376
|
}
|
|
28377
|
+
if (failed) return 2;
|
|
28325
28378
|
if (options.check) {
|
|
28326
28379
|
if (unformatted.length > 0) {
|
|
28327
28380
|
for (const file2 of unformatted) {
|
|
@@ -28338,7 +28391,7 @@ ${unformatted.length} file${unformatted.length !== 1 ? "s" : ""} would be reform
|
|
|
28338
28391
|
var init_format2 = __esm({
|
|
28339
28392
|
"src/cli/format.ts"() {
|
|
28340
28393
|
"use strict";
|
|
28341
|
-
|
|
28394
|
+
init_file_inputs();
|
|
28342
28395
|
init_format();
|
|
28343
28396
|
init_macro_sources();
|
|
28344
28397
|
init_story_format();
|
|
@@ -50599,7 +50652,7 @@ var init_protocol = __esm({
|
|
|
50599
50652
|
return;
|
|
50600
50653
|
}
|
|
50601
50654
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
50602
|
-
await new Promise((
|
|
50655
|
+
await new Promise((resolve6) => setTimeout(resolve6, pollInterval));
|
|
50603
50656
|
options?.signal?.throwIfAborted();
|
|
50604
50657
|
}
|
|
50605
50658
|
} catch (error48) {
|
|
@@ -50616,7 +50669,7 @@ var init_protocol = __esm({
|
|
|
50616
50669
|
*/
|
|
50617
50670
|
request(request, resultSchema, options) {
|
|
50618
50671
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
50619
|
-
return new Promise((
|
|
50672
|
+
return new Promise((resolve6, reject) => {
|
|
50620
50673
|
const earlyReject = (error48) => {
|
|
50621
50674
|
reject(error48);
|
|
50622
50675
|
};
|
|
@@ -50694,7 +50747,7 @@ var init_protocol = __esm({
|
|
|
50694
50747
|
if (!parseResult.success) {
|
|
50695
50748
|
reject(parseResult.error);
|
|
50696
50749
|
} else {
|
|
50697
|
-
|
|
50750
|
+
resolve6(parseResult.data);
|
|
50698
50751
|
}
|
|
50699
50752
|
} catch (error48) {
|
|
50700
50753
|
reject(error48);
|
|
@@ -50956,12 +51009,12 @@ var init_protocol = __esm({
|
|
|
50956
51009
|
}
|
|
50957
51010
|
} catch {
|
|
50958
51011
|
}
|
|
50959
|
-
return new Promise((
|
|
51012
|
+
return new Promise((resolve6, reject) => {
|
|
50960
51013
|
if (signal.aborted) {
|
|
50961
51014
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
50962
51015
|
return;
|
|
50963
51016
|
}
|
|
50964
|
-
const timeoutId = setTimeout(
|
|
51017
|
+
const timeoutId = setTimeout(resolve6, interval);
|
|
50965
51018
|
signal.addEventListener("abort", () => {
|
|
50966
51019
|
clearTimeout(timeoutId);
|
|
50967
51020
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -53988,7 +54041,7 @@ var require_compile = __commonJS({
|
|
|
53988
54041
|
const schOrFunc = root.refs[ref2];
|
|
53989
54042
|
if (schOrFunc)
|
|
53990
54043
|
return schOrFunc;
|
|
53991
|
-
let _sch =
|
|
54044
|
+
let _sch = resolve6.call(this, root, ref2);
|
|
53992
54045
|
if (_sch === void 0) {
|
|
53993
54046
|
const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref2];
|
|
53994
54047
|
const { schemaId } = this.opts;
|
|
@@ -54015,7 +54068,7 @@ var require_compile = __commonJS({
|
|
|
54015
54068
|
function sameSchemaEnv(s1, s2) {
|
|
54016
54069
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
54017
54070
|
}
|
|
54018
|
-
function
|
|
54071
|
+
function resolve6(root, ref2) {
|
|
54019
54072
|
let sch;
|
|
54020
54073
|
while (typeof (sch = this.refs[ref2]) == "string")
|
|
54021
54074
|
ref2 = sch;
|
|
@@ -54590,7 +54643,7 @@ var require_fast_uri = __commonJS({
|
|
|
54590
54643
|
}
|
|
54591
54644
|
return uri;
|
|
54592
54645
|
}
|
|
54593
|
-
function
|
|
54646
|
+
function resolve6(baseURI, relativeURI, options) {
|
|
54594
54647
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
54595
54648
|
const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
54596
54649
|
schemelessOptions.skipEscape = true;
|
|
@@ -54817,7 +54870,7 @@ var require_fast_uri = __commonJS({
|
|
|
54817
54870
|
var fastUri = {
|
|
54818
54871
|
SCHEMES,
|
|
54819
54872
|
normalize,
|
|
54820
|
-
resolve:
|
|
54873
|
+
resolve: resolve6,
|
|
54821
54874
|
resolveComponent,
|
|
54822
54875
|
equal,
|
|
54823
54876
|
serialize,
|
|
@@ -58975,7 +59028,7 @@ var init_mcp = __esm({
|
|
|
58975
59028
|
let task = createTaskResult.task;
|
|
58976
59029
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
58977
59030
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
58978
|
-
await new Promise((
|
|
59031
|
+
await new Promise((resolve6) => setTimeout(resolve6, pollInterval));
|
|
58979
59032
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
58980
59033
|
if (!updatedTask) {
|
|
58981
59034
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -59584,12 +59637,12 @@ var init_stdio2 = __esm({
|
|
|
59584
59637
|
this.onclose?.();
|
|
59585
59638
|
}
|
|
59586
59639
|
send(message) {
|
|
59587
|
-
return new Promise((
|
|
59640
|
+
return new Promise((resolve6) => {
|
|
59588
59641
|
const json2 = serializeMessage(message);
|
|
59589
59642
|
if (this._stdout.write(json2)) {
|
|
59590
|
-
|
|
59643
|
+
resolve6();
|
|
59591
59644
|
} else {
|
|
59592
|
-
this._stdout.once("drain",
|
|
59645
|
+
this._stdout.once("drain", resolve6);
|
|
59593
59646
|
}
|
|
59594
59647
|
});
|
|
59595
59648
|
}
|
|
@@ -59606,8 +59659,7 @@ __export(server_exports, {
|
|
|
59606
59659
|
formatFiles: () => formatFiles,
|
|
59607
59660
|
startMcpServer: () => startMcpServer
|
|
59608
59661
|
});
|
|
59609
|
-
import {
|
|
59610
|
-
import { resolve as resolve4 } from "node:path";
|
|
59662
|
+
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
59611
59663
|
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
59612
59664
|
function filterBySeverity2(diagnostics, minSeverity) {
|
|
59613
59665
|
const minIdx = SEVERITY_ORDER2.indexOf(minSeverity);
|
|
@@ -59616,37 +59668,8 @@ function filterBySeverity2(diagnostics, minSeverity) {
|
|
|
59616
59668
|
return idx >= minIdx;
|
|
59617
59669
|
});
|
|
59618
59670
|
}
|
|
59619
|
-
async function resolveFiles(pattern, cwd) {
|
|
59620
|
-
let input = pattern;
|
|
59621
|
-
let directory = cwd;
|
|
59622
|
-
try {
|
|
59623
|
-
const literal3 = resolve4(cwd, pattern);
|
|
59624
|
-
const stat = statSync(literal3);
|
|
59625
|
-
if (stat.isFile()) return [literal3];
|
|
59626
|
-
if (stat.isDirectory()) {
|
|
59627
|
-
directory = literal3;
|
|
59628
|
-
input = "**/*.{tw,twee}";
|
|
59629
|
-
}
|
|
59630
|
-
} catch {
|
|
59631
|
-
}
|
|
59632
|
-
const matches = await Ze(input, {
|
|
59633
|
-
cwd: directory,
|
|
59634
|
-
absolute: true,
|
|
59635
|
-
nodir: true
|
|
59636
|
-
});
|
|
59637
|
-
return [...new Set(matches)];
|
|
59638
|
-
}
|
|
59639
59671
|
function readFiles(files) {
|
|
59640
|
-
|
|
59641
|
-
for (const filePath of files) {
|
|
59642
|
-
try {
|
|
59643
|
-
const text2 = readFileSync8(filePath, "utf-8");
|
|
59644
|
-
const uri = pathToFileURL4(filePath).toString();
|
|
59645
|
-
fileContents.set(uri, text2);
|
|
59646
|
-
} catch {
|
|
59647
|
-
}
|
|
59648
|
-
}
|
|
59649
|
-
return fileContents;
|
|
59672
|
+
return new Map([...readFileContents(files)].map(([path, text2]) => [pathToFileURL4(path).toString(), text2]));
|
|
59650
59673
|
}
|
|
59651
59674
|
async function skippedReason(fileContents, files) {
|
|
59652
59675
|
const format = await findStoryFormat(fileContents.values(), commonDirectory(files));
|
|
@@ -59683,7 +59706,6 @@ async function checkProject(pattern, severity, cwd = process.cwd()) {
|
|
|
59683
59706
|
const results = [];
|
|
59684
59707
|
for (const filePath of files) {
|
|
59685
59708
|
const uri = pathToFileURL4(filePath).toString();
|
|
59686
|
-
if (!workspace.documents.has(uri)) continue;
|
|
59687
59709
|
let diags = computeDiagnostics(uri, workspace);
|
|
59688
59710
|
if (severity) {
|
|
59689
59711
|
diags = filterBySeverity2(diags, severity);
|
|
@@ -59721,7 +59743,7 @@ async function formatFiles(pattern, cwd = process.cwd()) {
|
|
|
59721
59743
|
const text2 = contents.get(pathToFileURL4(filePath).toString());
|
|
59722
59744
|
if (text2 === void 0) continue;
|
|
59723
59745
|
try {
|
|
59724
|
-
const result = await formatDocument(text2);
|
|
59746
|
+
const result = await formatDocument(text2, { filePath });
|
|
59725
59747
|
if (result !== text2) {
|
|
59726
59748
|
writeFileSync2(filePath, result, "utf-8");
|
|
59727
59749
|
formatted++;
|
|
@@ -59729,7 +59751,8 @@ async function formatFiles(pattern, cwd = process.cwd()) {
|
|
|
59729
59751
|
} else {
|
|
59730
59752
|
unchanged++;
|
|
59731
59753
|
}
|
|
59732
|
-
} catch {
|
|
59754
|
+
} catch (error48) {
|
|
59755
|
+
throw new Error(`${filePath}: ${error48 instanceof Error ? error48.message : String(error48)}`, { cause: error48 });
|
|
59733
59756
|
}
|
|
59734
59757
|
}
|
|
59735
59758
|
return { formatted, unchanged, files: changedFiles, ...warning && { warning } };
|
|
@@ -59746,9 +59769,10 @@ async function checkFormatting(pattern, cwd = process.cwd()) {
|
|
|
59746
59769
|
const text2 = contents.get(pathToFileURL4(filePath).toString());
|
|
59747
59770
|
if (text2 === void 0) continue;
|
|
59748
59771
|
try {
|
|
59749
|
-
const result = await formatDocument(text2);
|
|
59772
|
+
const result = await formatDocument(text2, { filePath });
|
|
59750
59773
|
(result !== text2 ? needsFormatting : alreadyFormatted).push(relativeTo(cwd, filePath));
|
|
59751
|
-
} catch {
|
|
59774
|
+
} catch (error48) {
|
|
59775
|
+
throw new Error(`${filePath}: ${error48 instanceof Error ? error48.message : String(error48)}`, { cause: error48 });
|
|
59752
59776
|
}
|
|
59753
59777
|
}
|
|
59754
59778
|
return { needsFormatting, alreadyFormatted, ...warning && { warning } };
|
|
@@ -59808,7 +59832,7 @@ var SEVERITY_ORDER2;
|
|
|
59808
59832
|
var init_server3 = __esm({
|
|
59809
59833
|
"src/mcp/server.ts"() {
|
|
59810
59834
|
"use strict";
|
|
59811
|
-
|
|
59835
|
+
init_file_inputs();
|
|
59812
59836
|
init_mcp();
|
|
59813
59837
|
init_stdio2();
|
|
59814
59838
|
init_zod();
|
|
@@ -61083,8 +61107,8 @@ var require_semaphore = __commonJS({
|
|
|
61083
61107
|
this._waiting = [];
|
|
61084
61108
|
}
|
|
61085
61109
|
lock(thunk) {
|
|
61086
|
-
return new Promise((
|
|
61087
|
-
this._waiting.push({ thunk, resolve:
|
|
61110
|
+
return new Promise((resolve6, reject) => {
|
|
61111
|
+
this._waiting.push({ thunk, resolve: resolve6, reject });
|
|
61088
61112
|
this.runNext();
|
|
61089
61113
|
});
|
|
61090
61114
|
}
|
|
@@ -62710,9 +62734,9 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
62710
62734
|
if (typeof cancellationStrategy.sender.enableCancellation === "function") {
|
|
62711
62735
|
cancellationStrategy.sender.enableCancellation(requestMessage);
|
|
62712
62736
|
}
|
|
62713
|
-
return new Promise(async (
|
|
62737
|
+
return new Promise(async (resolve6, reject) => {
|
|
62714
62738
|
const resolveWithCleanup = (r) => {
|
|
62715
|
-
|
|
62739
|
+
resolve6(r);
|
|
62716
62740
|
cancellationStrategy.sender.cleanup(id);
|
|
62717
62741
|
disposable?.dispose();
|
|
62718
62742
|
};
|
|
@@ -68354,8 +68378,8 @@ var require_server = __commonJS({
|
|
|
68354
68378
|
if (value instanceof Promise) {
|
|
68355
68379
|
return value;
|
|
68356
68380
|
} else if (Is3.thenable(value)) {
|
|
68357
|
-
return new Promise((
|
|
68358
|
-
value.then((resolved) =>
|
|
68381
|
+
return new Promise((resolve6, reject) => {
|
|
68382
|
+
value.then((resolved) => resolve6(resolved), (error48) => reject(error48));
|
|
68359
68383
|
});
|
|
68360
68384
|
} else {
|
|
68361
68385
|
return Promise.resolve(value);
|
|
@@ -68639,7 +68663,7 @@ var require_files = __commonJS({
|
|
|
68639
68663
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
68640
68664
|
exports.FileSystem = void 0;
|
|
68641
68665
|
exports.uriToFilePath = uriToFilePath;
|
|
68642
|
-
exports.resolve =
|
|
68666
|
+
exports.resolve = resolve6;
|
|
68643
68667
|
exports.resolveGlobalNodePath = resolveGlobalNodePath;
|
|
68644
68668
|
exports.resolveGlobalYarnPath = resolveGlobalYarnPath;
|
|
68645
68669
|
exports.resolveModulePath = resolveModulePath;
|
|
@@ -68668,7 +68692,7 @@ var require_files = __commonJS({
|
|
|
68668
68692
|
function isWindows() {
|
|
68669
68693
|
return process.platform === "win32";
|
|
68670
68694
|
}
|
|
68671
|
-
function
|
|
68695
|
+
function resolve6(moduleName, nodePath, cwd, tracer) {
|
|
68672
68696
|
const nodePathKey = "NODE_PATH";
|
|
68673
68697
|
const app = [
|
|
68674
68698
|
"var p = process;",
|
|
@@ -68687,7 +68711,7 @@ var require_files = __commonJS({
|
|
|
68687
68711
|
"}",
|
|
68688
68712
|
"});"
|
|
68689
68713
|
].join("");
|
|
68690
|
-
return new Promise((
|
|
68714
|
+
return new Promise((resolve7, reject) => {
|
|
68691
68715
|
const env = process.env;
|
|
68692
68716
|
const newEnv = /* @__PURE__ */ Object.create(null);
|
|
68693
68717
|
Object.keys(env).forEach((key) => newEnv[key] = env[key]);
|
|
@@ -68719,7 +68743,7 @@ var require_files = __commonJS({
|
|
|
68719
68743
|
if (message2.c === "r") {
|
|
68720
68744
|
cp.send({ c: "e" });
|
|
68721
68745
|
if (message2.s) {
|
|
68722
|
-
|
|
68746
|
+
resolve7(message2.r);
|
|
68723
68747
|
} else {
|
|
68724
68748
|
reject(new Error(`Failed to resolve module: ${moduleName}`));
|
|
68725
68749
|
}
|
|
@@ -68847,17 +68871,17 @@ var require_files = __commonJS({
|
|
|
68847
68871
|
if (!path.isAbsolute(nodePath)) {
|
|
68848
68872
|
nodePath = path.join(workspaceRoot, nodePath);
|
|
68849
68873
|
}
|
|
68850
|
-
return
|
|
68874
|
+
return resolve6(moduleName, nodePath, nodePath, tracer).then((value) => {
|
|
68851
68875
|
if (FileSystem.isParent(nodePath, value)) {
|
|
68852
68876
|
return value;
|
|
68853
68877
|
} else {
|
|
68854
68878
|
return Promise.reject(new Error(`Failed to load ${moduleName} from node path location.`));
|
|
68855
68879
|
}
|
|
68856
68880
|
}).then(void 0, (_error) => {
|
|
68857
|
-
return
|
|
68881
|
+
return resolve6(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
|
|
68858
68882
|
});
|
|
68859
68883
|
} else {
|
|
68860
|
-
return
|
|
68884
|
+
return resolve6(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
|
|
68861
68885
|
}
|
|
68862
68886
|
}
|
|
68863
68887
|
}
|
|
@@ -68939,10 +68963,10 @@ var require_ril = __commonJS({
|
|
|
68939
68963
|
return api_1.Disposable.create(() => this.stream.off("end", listener));
|
|
68940
68964
|
}
|
|
68941
68965
|
write(data2, encoding) {
|
|
68942
|
-
return new Promise((
|
|
68966
|
+
return new Promise((resolve6, reject) => {
|
|
68943
68967
|
const callback = (error48) => {
|
|
68944
68968
|
if (error48 === void 0 || error48 === null) {
|
|
68945
|
-
|
|
68969
|
+
resolve6();
|
|
68946
68970
|
} else {
|
|
68947
68971
|
reject(error48);
|
|
68948
68972
|
}
|
|
@@ -69234,10 +69258,10 @@ var require_main = __commonJS({
|
|
|
69234
69258
|
}
|
|
69235
69259
|
function createClientPipeTransport(pipeName, encoding = "utf-8") {
|
|
69236
69260
|
let connectResolve;
|
|
69237
|
-
const connected = new Promise((
|
|
69238
|
-
connectResolve =
|
|
69261
|
+
const connected = new Promise((resolve6, _reject) => {
|
|
69262
|
+
connectResolve = resolve6;
|
|
69239
69263
|
});
|
|
69240
|
-
return new Promise((
|
|
69264
|
+
return new Promise((resolve6, reject) => {
|
|
69241
69265
|
const server = (0, net_1.createServer)((socket) => {
|
|
69242
69266
|
server.close();
|
|
69243
69267
|
connectResolve([
|
|
@@ -69248,7 +69272,7 @@ var require_main = __commonJS({
|
|
|
69248
69272
|
server.on("error", reject);
|
|
69249
69273
|
server.listen(pipeName, () => {
|
|
69250
69274
|
server.removeListener("error", reject);
|
|
69251
|
-
|
|
69275
|
+
resolve6({
|
|
69252
69276
|
onConnected: () => {
|
|
69253
69277
|
return connected;
|
|
69254
69278
|
}
|
|
@@ -69265,10 +69289,10 @@ var require_main = __commonJS({
|
|
|
69265
69289
|
}
|
|
69266
69290
|
function createClientSocketTransport(port, encoding = "utf-8") {
|
|
69267
69291
|
let connectResolve;
|
|
69268
|
-
const connected = new Promise((
|
|
69269
|
-
connectResolve =
|
|
69292
|
+
const connected = new Promise((resolve6, _reject) => {
|
|
69293
|
+
connectResolve = resolve6;
|
|
69270
69294
|
});
|
|
69271
|
-
return new Promise((
|
|
69295
|
+
return new Promise((resolve6, reject) => {
|
|
69272
69296
|
const server = (0, net_1.createServer)((socket) => {
|
|
69273
69297
|
server.close();
|
|
69274
69298
|
connectResolve([
|
|
@@ -69285,7 +69309,7 @@ var require_main = __commonJS({
|
|
|
69285
69309
|
return;
|
|
69286
69310
|
}
|
|
69287
69311
|
const boundPort = address.port;
|
|
69288
|
-
|
|
69312
|
+
resolve6({
|
|
69289
69313
|
port: () => boundPort,
|
|
69290
69314
|
onConnected: () => {
|
|
69291
69315
|
return connected;
|
|
@@ -70079,6 +70103,7 @@ var init_markup_cursor = __esm({
|
|
|
70079
70103
|
init_tooling();
|
|
70080
70104
|
init_passage_markup();
|
|
70081
70105
|
init_tree();
|
|
70106
|
+
init_source_view();
|
|
70082
70107
|
init_text();
|
|
70083
70108
|
MarkupCursor = class {
|
|
70084
70109
|
constructor(passage, at3, workspace) {
|
|
@@ -70104,6 +70129,7 @@ var init_markup_cursor = __esm({
|
|
|
70104
70129
|
start: 0,
|
|
70105
70130
|
end: content.length,
|
|
70106
70131
|
text: false,
|
|
70132
|
+
view: { offset: 0, text: content },
|
|
70107
70133
|
tokens: passage.tokens,
|
|
70108
70134
|
errors: passage.tokenization.errors,
|
|
70109
70135
|
nodes: () => passage.pairing.nodes
|
|
@@ -70116,6 +70142,7 @@ var init_markup_cursor = __esm({
|
|
|
70116
70142
|
start: piece.offset,
|
|
70117
70143
|
end,
|
|
70118
70144
|
text: true,
|
|
70145
|
+
view: piece,
|
|
70119
70146
|
tokens: piece.tokens,
|
|
70120
70147
|
errors: piece.errors,
|
|
70121
70148
|
nodes: () => pairMarkup(piece.tokens, { isBlock: (name) => this.workspace.isContainer(name), source: content }).nodes
|
|
@@ -70130,17 +70157,19 @@ var init_markup_cursor = __esm({
|
|
|
70130
70157
|
* of its name.
|
|
70131
70158
|
*/
|
|
70132
70159
|
enclosingMacro(known) {
|
|
70133
|
-
const {
|
|
70160
|
+
const { at: at3 } = this;
|
|
70134
70161
|
for (const region of this.regions) {
|
|
70135
70162
|
const found = [];
|
|
70136
70163
|
for (const token of region.tokens) {
|
|
70137
70164
|
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 ?
|
|
70165
|
+
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
70166
|
}
|
|
70140
70167
|
for (const error48 of region.errors) {
|
|
70141
|
-
|
|
70142
|
-
const
|
|
70143
|
-
if (
|
|
70168
|
+
const source = region.view.text;
|
|
70169
|
+
const end = viewIndex(region.view, error48.end);
|
|
70170
|
+
if (error48.code !== "unclosed-macro" || error48.offset >= at3 || error48.end >= at3 || !/\s/.test(source[end] ?? "")) continue;
|
|
70171
|
+
const name = source.slice(parseSelectors(source, viewIndex(region.view, error48.offset) + 1).end, end);
|
|
70172
|
+
if (name && name[0] !== "/") found.push({ start: error48.offset, name, argsBefore: source.slice(end, viewIndex(region.view, at3)).trimStart() });
|
|
70144
70173
|
}
|
|
70145
70174
|
const innermost = found.filter((macro) => known(macro.name)).sort((a, b) => b.start - a.start)[0];
|
|
70146
70175
|
if (innermost) return { name: innermost.name, argsBefore: innermost.argsBefore };
|
|
@@ -70229,10 +70258,9 @@ function variableUses(passage) {
|
|
|
70229
70258
|
for (const piece of passage.pieces) {
|
|
70230
70259
|
if (piece.kind !== "code") continue;
|
|
70231
70260
|
lexJs(piece.code, {
|
|
70232
|
-
variable(sigil, name, index) {
|
|
70233
|
-
const nameEnd = index + 1 + name.length;
|
|
70261
|
+
variable(sigil, name, index, _nesting, nameEnd) {
|
|
70234
70262
|
const pathEnd = nameEnd + pathLength(piece.code, nameEnd);
|
|
70235
|
-
uses.push({ sigil, name, start: pieceOffset(piece, index), end: pieceOffset(piece, pathEnd
|
|
70263
|
+
uses.push({ sigil, name, start: pieceOffset(piece, index), end: pieceOffset(piece, pathEnd) });
|
|
70236
70264
|
}
|
|
70237
70265
|
}, piece.goal);
|
|
70238
70266
|
}
|
|
@@ -70824,27 +70852,7 @@ function findReferences(uri, position, workspace, includeDeclaration) {
|
|
|
70824
70852
|
return [];
|
|
70825
70853
|
}
|
|
70826
70854
|
function variableAt(uri, position, workspace) {
|
|
70827
|
-
|
|
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;
|
|
70855
|
+
return workspace.variables.referenceAt(uri, position);
|
|
70848
70856
|
}
|
|
70849
70857
|
function findPassageReferences(passageName, workspace, includeDeclaration) {
|
|
70850
70858
|
const locations = [];
|
|
@@ -70927,15 +70935,13 @@ function toLspRange3(r) {
|
|
|
70927
70935
|
end: { line: r.end.line, character: r.end.character }
|
|
70928
70936
|
};
|
|
70929
70937
|
}
|
|
70930
|
-
var
|
|
70938
|
+
var referencesPlugin;
|
|
70931
70939
|
var init_references = __esm({
|
|
70932
70940
|
"src/plugins/references.ts"() {
|
|
70933
70941
|
"use strict";
|
|
70934
70942
|
init_macro_heads();
|
|
70935
70943
|
init_passage_refs();
|
|
70936
70944
|
init_passage_parser();
|
|
70937
|
-
VARIABLE_CANDIDATE = /(?:\$|(?<!\w)%)(?=\w)/g;
|
|
70938
|
-
VARIABLE_PATH = /^([$%])(\w+(?:\.[A-Za-z_$][\w$]*)*)/;
|
|
70939
70945
|
referencesPlugin = {
|
|
70940
70946
|
id: "references",
|
|
70941
70947
|
capabilities: {
|
|
@@ -71039,17 +71045,32 @@ function computeRename(uri, position, newName, workspace) {
|
|
|
71039
71045
|
`Cannot rename to ${JSON.stringify(newName)}: a transient name cannot start with a digit, \`%5\` is the modulo operator in code.`
|
|
71040
71046
|
).at(uri, symbol2.range);
|
|
71041
71047
|
}
|
|
71048
|
+
const declaration = parseDeclarations(`${symbol2.sigil}${bareName} = 0`, symbol2.sigil);
|
|
71049
|
+
if (declaration.errors.length || declaration.declarations[0]?.name !== bareName) {
|
|
71050
|
+
throw new RenameError(`Cannot rename to ${JSON.stringify(newName)}: ${declaration.errors[0]?.message ?? "invalid variable name"}.`).at(uri, symbol2.range);
|
|
71051
|
+
}
|
|
71042
71052
|
if (bareName === symbol2.name) return /* @__PURE__ */ new Map();
|
|
71043
71053
|
if (workspace.variables.getDeclared().has(bareName) || workspace.variables.getDeclaredTransient().has(bareName)) {
|
|
71044
71054
|
throw new RenameError(`Cannot rename to ${JSON.stringify(newName)}: a variable with that name already exists.`).at(uri, symbol2.range);
|
|
71045
71055
|
}
|
|
71046
71056
|
const refs = symbol2.sigil === "%" ? findTransientReferences(symbol2.name, workspace, true) : findVariableReferences(symbol2.name, workspace, true);
|
|
71047
71057
|
for (const ref2 of refs) {
|
|
71048
|
-
const
|
|
71049
|
-
|
|
71050
|
-
|
|
71051
|
-
|
|
71052
|
-
|
|
71058
|
+
const doc = workspace.markup.get(ref2.uri);
|
|
71059
|
+
const passage = doc.passageAt(ref2.range.start);
|
|
71060
|
+
const start = passage.contentOffset(positionToOffset(ref2.range.start, doc.lineStarts));
|
|
71061
|
+
const end = passage.contentOffset(positionToOffset(ref2.range.end, doc.lineStarts));
|
|
71062
|
+
const view = sourceView(passage, start, end);
|
|
71063
|
+
const index = viewIndex(view, start);
|
|
71064
|
+
let base;
|
|
71065
|
+
lexJs(view.text.slice(index, viewIndex(view, end)), {
|
|
71066
|
+
variable(sigil, name, at3, _nesting, nameEnd) {
|
|
71067
|
+
if (at3 === 0 && sigil === symbol2.sigil && name === symbol2.name) {
|
|
71068
|
+
base = [pieceOffset(view, index + 1), pieceOffset(view, index + nameEnd)];
|
|
71069
|
+
}
|
|
71070
|
+
}
|
|
71071
|
+
});
|
|
71072
|
+
if (!base) throw new RenameError("Cannot locate the variable name safely.").at(ref2.uri, ref2.range);
|
|
71073
|
+
addEdit(ref2.uri, passage.range(...base), bareName);
|
|
71053
71074
|
}
|
|
71054
71075
|
break;
|
|
71055
71076
|
}
|
|
@@ -71204,6 +71225,8 @@ var init_rename = __esm({
|
|
|
71204
71225
|
"use strict";
|
|
71205
71226
|
import_vscode_languageserver2 = __toESM(require_api3(), 1);
|
|
71206
71227
|
init_tooling();
|
|
71228
|
+
init_source_view();
|
|
71229
|
+
init_text();
|
|
71207
71230
|
init_link_runtime();
|
|
71208
71231
|
init_passage_refs();
|
|
71209
71232
|
init_js_string_literal();
|
|
@@ -71358,7 +71381,8 @@ var init_code_lens = __esm({
|
|
|
71358
71381
|
range: toLspRange5(l.range),
|
|
71359
71382
|
command: {
|
|
71360
71383
|
title: l.command.title,
|
|
71361
|
-
|
|
71384
|
+
// Informational counts: no editor-specific navigation command is registered.
|
|
71385
|
+
command: ""
|
|
71362
71386
|
}
|
|
71363
71387
|
}));
|
|
71364
71388
|
});
|
|
@@ -71387,13 +71411,15 @@ function addWidgetParamHints(passages, inRange, workspace, hints) {
|
|
|
71387
71411
|
const widget = workspace.widgets.getWidget(token.name);
|
|
71388
71412
|
if (!widget || widget.params.length === 0) continue;
|
|
71389
71413
|
const args2 = splitArgs(token.rawArgs);
|
|
71414
|
+
const view = textAt(passage, token.start, token.end) ?? { offset: 0 };
|
|
71415
|
+
const argsStart = viewIndex(view, token.argsStart);
|
|
71390
71416
|
let from = 0;
|
|
71391
71417
|
for (let i2 = 0; i2 < Math.min(args2.length, widget.params.length); i2++) {
|
|
71392
71418
|
const at3 = token.rawArgs.indexOf(args2[i2], from);
|
|
71393
71419
|
if (at3 === -1) break;
|
|
71394
71420
|
from = at3 + args2[i2].length;
|
|
71395
71421
|
hints.push({
|
|
71396
|
-
position: passage.position(
|
|
71422
|
+
position: passage.position(pieceOffset(view, argsStart + at3)),
|
|
71397
71423
|
label: `${widget.params[i2]}:`,
|
|
71398
71424
|
kind: "parameter"
|
|
71399
71425
|
});
|
|
@@ -71416,6 +71442,7 @@ var init_inlay_hints = __esm({
|
|
|
71416
71442
|
"src/plugins/inlay-hints.ts"() {
|
|
71417
71443
|
"use strict";
|
|
71418
71444
|
init_tooling();
|
|
71445
|
+
init_source_view();
|
|
71419
71446
|
init_tokens();
|
|
71420
71447
|
inlayHintsPlugin = {
|
|
71421
71448
|
id: "inlay-hints",
|
|
@@ -71580,9 +71607,9 @@ var init_semantic_tokens = __esm({
|
|
|
71580
71607
|
});
|
|
71581
71608
|
|
|
71582
71609
|
// src/plugins/code-actions.ts
|
|
71583
|
-
import { readFileSync as
|
|
71610
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
71584
71611
|
import { basename, dirname as dirname3, join as join4 } from "node:path";
|
|
71585
|
-
import { fileURLToPath as
|
|
71612
|
+
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL5 } from "node:url";
|
|
71586
71613
|
function computeCodeActions(uri, diagnostics, workspace, options = {}) {
|
|
71587
71614
|
const actions = [];
|
|
71588
71615
|
for (const diag of diagnostics) {
|
|
@@ -71654,7 +71681,7 @@ function addMacroToConfig(uri, macroName, workspace, options) {
|
|
|
71654
71681
|
let text2 = workspace.documents.getText(configUri);
|
|
71655
71682
|
if (text2 === void 0) {
|
|
71656
71683
|
try {
|
|
71657
|
-
text2 =
|
|
71684
|
+
text2 = readFileSync7(existingPath, "utf-8");
|
|
71658
71685
|
} catch {
|
|
71659
71686
|
return null;
|
|
71660
71687
|
}
|
|
@@ -71665,10 +71692,10 @@ function addMacroToConfig(uri, macroName, workspace, options) {
|
|
|
71665
71692
|
}
|
|
71666
71693
|
function resolveConfigRoot(uri, workspaceRoot) {
|
|
71667
71694
|
if (workspaceRoot) {
|
|
71668
|
-
return workspaceRoot.startsWith("file:") ?
|
|
71695
|
+
return workspaceRoot.startsWith("file:") ? fileURLToPath3(workspaceRoot) : workspaceRoot;
|
|
71669
71696
|
}
|
|
71670
71697
|
if (!uri.startsWith("file:")) return null;
|
|
71671
|
-
const docDir = dirname3(
|
|
71698
|
+
const docDir = dirname3(fileURLToPath3(uri));
|
|
71672
71699
|
let search = docDir;
|
|
71673
71700
|
for (let i2 = 0; i2 < 10; i2++) {
|
|
71674
71701
|
if (findConfigFile(search)) return search;
|
|
@@ -71785,18 +71812,6 @@ function lineEndingFor(workspace, uri) {
|
|
|
71785
71812
|
}
|
|
71786
71813
|
return "\n";
|
|
71787
71814
|
}
|
|
71788
|
-
function declarationInsertEdit(text2, headerLine, declaration, eol) {
|
|
71789
|
-
const lines = text2.split("\n");
|
|
71790
|
-
let contentEnd = lines.length;
|
|
71791
|
-
for (let i2 = headerLine + 1; i2 < lines.length; i2++) {
|
|
71792
|
-
if (/^\uFEFF?::\s+/.test(lines[i2])) {
|
|
71793
|
-
contentEnd = i2;
|
|
71794
|
-
break;
|
|
71795
|
-
}
|
|
71796
|
-
}
|
|
71797
|
-
if (contentEnd === lines.length && text2.endsWith("\n")) contentEnd = lines.length;
|
|
71798
|
-
return insertLinesAt(text2, contentEnd, declaration, eol);
|
|
71799
|
-
}
|
|
71800
71815
|
function declareVariable(diag, workspace, sigil) {
|
|
71801
71816
|
if (diag.data?.kind !== "undeclared-variable" || diag.data.sigil !== sigil) return [];
|
|
71802
71817
|
const { name } = diag.data;
|
|
@@ -71804,7 +71819,10 @@ function declareVariable(diag, workspace, sigil) {
|
|
|
71804
71819
|
if (!passage) return [];
|
|
71805
71820
|
const text2 = workspace.documents.getText(passage.uri);
|
|
71806
71821
|
if (text2 === void 0) return [];
|
|
71807
|
-
const
|
|
71822
|
+
const markup = workspace.markup.get(passage.uri)?.passages.find((p) => p.passage === passage);
|
|
71823
|
+
if (!markup) return [];
|
|
71824
|
+
const boundary = markup.bodyEnd === text2.length ? text2.split("\n").length : markup.position(markup.content.length).line;
|
|
71825
|
+
const edit = insertLinesAt(text2, boundary, `${sigil}${name} = 0
|
|
71808
71826
|
`, lineEndingFor(workspace, passage.uri));
|
|
71809
71827
|
return [{
|
|
71810
71828
|
title: `Declare '${sigil}${name}' in ${sigil === "$" ? "StoryVariables" : "StoryTransients"}`,
|
|
@@ -72298,12 +72316,12 @@ var server_exports2 = {};
|
|
|
72298
72316
|
__export(server_exports2, {
|
|
72299
72317
|
startServer: () => startServer
|
|
72300
72318
|
});
|
|
72301
|
-
import { fileURLToPath as
|
|
72302
|
-
import { readFileSync as
|
|
72319
|
+
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
72320
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
72303
72321
|
import { basename as basename2 } from "node:path";
|
|
72304
72322
|
function uriToFsPath(uri) {
|
|
72305
72323
|
try {
|
|
72306
|
-
return
|
|
72324
|
+
return fileURLToPath4(uri);
|
|
72307
72325
|
} catch {
|
|
72308
72326
|
return uri;
|
|
72309
72327
|
}
|
|
@@ -72437,7 +72455,7 @@ function startServer(args2) {
|
|
|
72437
72455
|
if (workspace) {
|
|
72438
72456
|
try {
|
|
72439
72457
|
const fsPath = uriToFsPath(textDocument.uri);
|
|
72440
|
-
const text2 =
|
|
72458
|
+
const text2 = readFileSync8(fsPath, "utf-8");
|
|
72441
72459
|
workspace.documents.update(textDocument.uri, text2);
|
|
72442
72460
|
} catch {
|
|
72443
72461
|
workspace.documents.close(textDocument.uri);
|
|
@@ -72473,7 +72491,7 @@ function startServer(args2) {
|
|
|
72473
72491
|
} else {
|
|
72474
72492
|
try {
|
|
72475
72493
|
const fsPath = uriToFsPath(change.uri);
|
|
72476
|
-
const text2 =
|
|
72494
|
+
const text2 = readFileSync8(fsPath, "utf-8");
|
|
72477
72495
|
if (workspace.documents.has(change.uri)) {
|
|
72478
72496
|
workspace.documents.update(change.uri, text2);
|
|
72479
72497
|
} else {
|
|
@@ -72509,7 +72527,7 @@ async function scanWorkspaceFiles(root) {
|
|
|
72509
72527
|
];
|
|
72510
72528
|
for (const filePath of files) {
|
|
72511
72529
|
try {
|
|
72512
|
-
const text2 =
|
|
72530
|
+
const text2 = readFileSync8(filePath, "utf-8");
|
|
72513
72531
|
const uri = fsPathToUri(filePath);
|
|
72514
72532
|
contents.set(uri, text2);
|
|
72515
72533
|
} catch {
|
|
@@ -72539,7 +72557,7 @@ var init_server4 = __esm({
|
|
|
72539
72557
|
|
|
72540
72558
|
// src/bin.ts
|
|
72541
72559
|
var args = process.argv.slice(2);
|
|
72542
|
-
var VERSION = "0.14.
|
|
72560
|
+
var VERSION = "0.14.3";
|
|
72543
72561
|
var HELP = `spindle-lsp v${VERSION}
|
|
72544
72562
|
Language Server Protocol server for Spindle story format
|
|
72545
72563
|
|