@rohal12/spindle-lsp 0.15.10 → 0.15.12
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 +60 -38
- package/dist/bin.js.map +3 -3
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -55,7 +55,7 @@ var VERSION;
|
|
|
55
55
|
var init_version = __esm({
|
|
56
56
|
"src/version.ts"() {
|
|
57
57
|
"use strict";
|
|
58
|
-
VERSION = false ? pkg.version : "0.15.
|
|
58
|
+
VERSION = false ? pkg.version : "0.15.12";
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
|
|
@@ -31258,7 +31258,7 @@ function parsePassageHeader(rawLine, lineNumber) {
|
|
|
31258
31258
|
const first = delimiter.exec(escaped);
|
|
31259
31259
|
const boundary = first?.index ?? line.length;
|
|
31260
31260
|
const nameEnd = escaped.slice(0, boundary).trimEnd().length;
|
|
31261
|
-
const name = line.slice(nameStart, nameEnd).replace(/\\(
|
|
31261
|
+
const name = line.slice(nameStart, nameEnd).replace(/\\(.|$)/g, "$1").trim();
|
|
31262
31262
|
if (!name) return null;
|
|
31263
31263
|
let rest = boundary;
|
|
31264
31264
|
let tags = [];
|
|
@@ -31306,7 +31306,7 @@ function isScriptOrStylesheetPassage(passage) {
|
|
|
31306
31306
|
return passage.tags?.some((t) => CODE_PASSAGE_TAGS.has(t)) ?? false;
|
|
31307
31307
|
}
|
|
31308
31308
|
function isRuntimePassage(passage) {
|
|
31309
|
-
return passage.name !== "StoryTitle" && passage.name !== "StoryData" && !isScriptOrStylesheetPassage(passage) && !passage.tags?.includes("Twine.private");
|
|
31309
|
+
return !passage.runtimeOmitted && passage.name !== "StoryTitle" && passage.name !== "StoryData" && !isScriptOrStylesheetPassage(passage) && !passage.tags?.includes("Twine.private");
|
|
31310
31310
|
}
|
|
31311
31311
|
function isMarkupPassage(passage) {
|
|
31312
31312
|
return isRuntimePassage(passage) && !(passage.name !== void 0 && NON_MARKUP_PASSAGES.has(passage.name));
|
|
@@ -31355,6 +31355,16 @@ var init_passage_parser = __esm({
|
|
|
31355
31355
|
});
|
|
31356
31356
|
|
|
31357
31357
|
// src/core/workspace/passage-index.ts
|
|
31358
|
+
import { createRequire as createSettingsRequire } from "node:module";
|
|
31359
|
+
function compareSourceUris(left, right) {
|
|
31360
|
+
const a = left.split("/").map(decodeURIComponent);
|
|
31361
|
+
const b = right.split("/").map(decodeURIComponent);
|
|
31362
|
+
for (let i2 = 0; i2 < Math.min(a.length, b.length); i2++) {
|
|
31363
|
+
const order = Buffer.compare(Buffer.from(a[i2], "utf8"), Buffer.from(b[i2], "utf8"));
|
|
31364
|
+
if (order !== 0) return order;
|
|
31365
|
+
}
|
|
31366
|
+
return a.length - b.length;
|
|
31367
|
+
}
|
|
31358
31368
|
var PassageIndex;
|
|
31359
31369
|
var init_passage_index = __esm({
|
|
31360
31370
|
"src/core/workspace/passage-index.ts"() {
|
|
@@ -31402,6 +31412,12 @@ var init_passage_index = __esm({
|
|
|
31402
31412
|
start: passages[i2].range.start,
|
|
31403
31413
|
end: { line: nextStart, character: lines[nextStart]?.length ?? 0 }
|
|
31404
31414
|
};
|
|
31415
|
+
if (passages[i2].name === "StorySettings") {
|
|
31416
|
+
const { StoryBuilder } = createSettingsRequire(import.meta.url)("@rohal12/twee-ts");
|
|
31417
|
+
const builder = new StoryBuilder();
|
|
31418
|
+
builder.add({ name: "StorySettings", tags: [], text: lines.slice(passages[i2].headerEnd.end.line + 1, nextStart + 1).join("\n") }, []);
|
|
31419
|
+
passages[i2].runtimeOmitted = builder.build().twine1.settings.size === 0;
|
|
31420
|
+
}
|
|
31405
31421
|
}
|
|
31406
31422
|
if (passages.length > 0) {
|
|
31407
31423
|
this.byUri.set(uri, passages);
|
|
@@ -31436,6 +31452,10 @@ var init_passage_index = __esm({
|
|
|
31436
31452
|
}
|
|
31437
31453
|
return found;
|
|
31438
31454
|
}
|
|
31455
|
+
/** The compiler replaces duplicate passages with the later source declaration. */
|
|
31456
|
+
getEffectivePassage(name) {
|
|
31457
|
+
return this.getPassages(name).sort((a, b) => compareSourceUris(a.uri, b.uri)).at(-1);
|
|
31458
|
+
}
|
|
31439
31459
|
/** Get the passage containing a specific line in a document. */
|
|
31440
31460
|
getPassageAt(uri, line) {
|
|
31441
31461
|
const passages = this.byUri.get(uri);
|
|
@@ -31468,11 +31488,11 @@ var init_passage_index = __esm({
|
|
|
31468
31488
|
}
|
|
31469
31489
|
/** Get the StoryVariables passage, if any. */
|
|
31470
31490
|
getStoryVariables() {
|
|
31471
|
-
return this.
|
|
31491
|
+
return this.getEffectivePassage("StoryVariables");
|
|
31472
31492
|
}
|
|
31473
31493
|
/** Get the StoryTransients passage, if any. */
|
|
31474
31494
|
getStoryTransients() {
|
|
31475
|
-
return this.
|
|
31495
|
+
return this.getEffectivePassage("StoryTransients");
|
|
31476
31496
|
}
|
|
31477
31497
|
/** Get the StoryInit passage, if any. */
|
|
31478
31498
|
getStoryInit() {
|
|
@@ -32297,6 +32317,10 @@ var init_macro_registry2 = __esm({
|
|
|
32297
32317
|
hasConfiguredParameters(name) {
|
|
32298
32318
|
return this.configEntries.get(name.toLowerCase())?.parameters !== void 0;
|
|
32299
32319
|
}
|
|
32320
|
+
/** Whether a project definition replaces the original runtime macro. */
|
|
32321
|
+
hasDiscoveredMacro(name) {
|
|
32322
|
+
return this.discovered.has(name.toLowerCase());
|
|
32323
|
+
}
|
|
32300
32324
|
/** Check if a macro is a block (container) macro. */
|
|
32301
32325
|
isBlock(name) {
|
|
32302
32326
|
return this.getMacro(name)?.block ?? false;
|
|
@@ -33363,11 +33387,10 @@ var init_macro_supplements = __esm({
|
|
|
33363
33387
|
button: {
|
|
33364
33388
|
name: "button",
|
|
33365
33389
|
container: true,
|
|
33366
|
-
description: 'Creates a button that executes its contents when clicked.\n\nUsage:\n\n```\n{button "
|
|
33367
|
-
parameters: ["text
|
|
33390
|
+
description: 'Creates a button that executes its contents when clicked. Navigate by placing {goto} in its body.\n\nUsage:\n\n```\n{button "Go"}\n {goto "Hall"}\n{/button}\n```',
|
|
33391
|
+
parameters: ["text"],
|
|
33368
33392
|
parameterDocs: [
|
|
33369
|
-
{ name: "label", documentation: "Text of the button." }
|
|
33370
|
-
{ name: "passage", documentation: "Passage to go to when clicked; omit to run the contents." }
|
|
33393
|
+
{ name: "label", documentation: "Text of the button; its body runs when clicked." }
|
|
33371
33394
|
]
|
|
33372
33395
|
},
|
|
33373
33396
|
timed: {
|
|
@@ -33448,7 +33471,7 @@ var init_macro_supplements = __esm({
|
|
|
33448
33471
|
},
|
|
33449
33472
|
meter: {
|
|
33450
33473
|
name: "meter",
|
|
33451
|
-
description:
|
|
33474
|
+
description: 'Displays the current value relative to a maximum, with an optional quoted label.\n\nUsage: `{meter 5 10 "%"}`',
|
|
33452
33475
|
parameters: ["...text"],
|
|
33453
33476
|
parameterDocs: [
|
|
33454
33477
|
{ name: "current", documentation: 'Current value expression; a maximum expression and an optional label mode (`"%"`, `"none"` or a unit) follow.' }
|
|
@@ -33595,27 +33618,19 @@ var init_macro_supplements = __esm({
|
|
|
33595
33618
|
},
|
|
33596
33619
|
watch: {
|
|
33597
33620
|
name: "watch",
|
|
33598
|
-
description:
|
|
33621
|
+
description: 'Watches a quoted condition and runs an action when it changes from false to true. Use name to allow removal with {unwatch}.\n\nUsage: `{watch "$x >= 2" run "$x = 0" name "reset-x"}`',
|
|
33599
33622
|
parameters: ["...text"],
|
|
33600
33623
|
parameterDocs: [
|
|
33601
|
-
{ name: "
|
|
33624
|
+
{ name: "condition", documentation: "Quoted expression checked when variables change or the story navigates." },
|
|
33625
|
+
{ name: "options", documentation: "Action (goto, dialog or run), optional name, priority and once flag." }
|
|
33602
33626
|
]
|
|
33603
33627
|
},
|
|
33604
33628
|
unwatch: {
|
|
33605
33629
|
name: "unwatch",
|
|
33606
|
-
description:
|
|
33630
|
+
description: 'Removes a watcher by its registered name.\n\nUsage: `{unwatch "reset-x"}`',
|
|
33607
33631
|
parameters: ["...text"],
|
|
33608
33632
|
parameterDocs: [
|
|
33609
|
-
{ name: "
|
|
33610
|
-
]
|
|
33611
|
-
},
|
|
33612
|
-
unless: {
|
|
33613
|
-
name: "unless",
|
|
33614
|
-
container: true,
|
|
33615
|
-
description: "Conditionally displays its contents when the expression is falsy. The inverse of `{if}`.\n\nUsage:\n\n```\n{unless condition}\n ...\n{/unless}\n```",
|
|
33616
|
-
parameters: ["...text"],
|
|
33617
|
-
parameterDocs: [
|
|
33618
|
-
{ name: "condition", documentation: "Expression; the contents show when it is falsy." }
|
|
33633
|
+
{ name: "name", documentation: "Name supplied to the watch macro." }
|
|
33619
33634
|
]
|
|
33620
33635
|
}
|
|
33621
33636
|
};
|
|
@@ -33641,6 +33656,7 @@ var init_workspace_model = __esm({
|
|
|
33641
33656
|
init_macro_sources();
|
|
33642
33657
|
init_story_format();
|
|
33643
33658
|
init_spindle_version();
|
|
33659
|
+
init_passage_parser();
|
|
33644
33660
|
init_macro_supplements();
|
|
33645
33661
|
WorkspaceModel = class extends EventEmitter2 {
|
|
33646
33662
|
documents;
|
|
@@ -33869,7 +33885,8 @@ var init_workspace_model = __esm({
|
|
|
33869
33885
|
}
|
|
33870
33886
|
let lines;
|
|
33871
33887
|
for (const passage of this.passages.getPassagesInDocument(uri)) {
|
|
33872
|
-
|
|
33888
|
+
if (passage.tags?.includes("Twine.private")) continue;
|
|
33889
|
+
const isStoryInit = passage.name === "StoryInit" && isRuntimePassage(passage);
|
|
33873
33890
|
const isScript = passage.tags?.includes("script") ?? false;
|
|
33874
33891
|
if (!isStoryInit && !isScript) continue;
|
|
33875
33892
|
lines ??= text3.split("\n");
|
|
@@ -33894,8 +33911,8 @@ var init_workspace_model = __esm({
|
|
|
33894
33911
|
this.declaredVersion = storyDataFormatVersion(this.passages.getAllPassages(), (uri) => this.documents.getText(uri));
|
|
33895
33912
|
this._target = resolveSpindleTarget(this.installedVersion, this.declaredVersion);
|
|
33896
33913
|
const declarations = (name) => {
|
|
33897
|
-
const passage = this.passages.
|
|
33898
|
-
return passage ? this.markup.get(passage.uri)?.passages.find((p) => p.passage === passage) : void 0;
|
|
33914
|
+
const passage = this.passages.getEffectivePassage(name);
|
|
33915
|
+
return passage && isRuntimePassage(passage) ? this.markup.get(passage.uri)?.passages.find((p) => p.passage === passage) : void 0;
|
|
33899
33916
|
};
|
|
33900
33917
|
const variables = declarations("StoryVariables");
|
|
33901
33918
|
if (variables) this.variables.parseStoryVariables(variables.content, variables.passage.headerEnd.end.line + 1, variables.doc.uri);
|
|
@@ -34201,6 +34218,7 @@ var init_passage_refs = __esm({
|
|
|
34201
34218
|
|
|
34202
34219
|
// src/core/parsing/link-parser.ts
|
|
34203
34220
|
function markupOfText(text3) {
|
|
34221
|
+
if (typeof text3 !== "string") return text3;
|
|
34204
34222
|
if (lastMarkup?.text === text3) return lastMarkup;
|
|
34205
34223
|
const markup = readText2(text3);
|
|
34206
34224
|
lastMarkup = markup;
|
|
@@ -34224,7 +34242,7 @@ function readText2(text3) {
|
|
|
34224
34242
|
return new DocumentMarkup(TEXT_URI, text3, passages, TEXT_CONTEXT);
|
|
34225
34243
|
}
|
|
34226
34244
|
function findLinkRuntimeMismatches(text3) {
|
|
34227
|
-
if (!text3.includes("[[")) return [];
|
|
34245
|
+
if (!(typeof text3 === "string" ? text3 : text3.text).includes("[[")) return [];
|
|
34228
34246
|
const found = [];
|
|
34229
34247
|
for (const ref2 of documentPassageRefs(markupOfText(text3))) {
|
|
34230
34248
|
if (ref2.form !== "bracket") continue;
|
|
@@ -34384,7 +34402,7 @@ function buildReport(documents, workspace) {
|
|
|
34384
34402
|
}
|
|
34385
34403
|
function declarationsOf(workspace, name) {
|
|
34386
34404
|
const passage = name === "StoryVariables" ? workspace.passages.getStoryVariables() : workspace.passages.getStoryTransients();
|
|
34387
|
-
if (!passage) return void 0;
|
|
34405
|
+
if (!passage || !isRuntimePassage(passage)) return void 0;
|
|
34388
34406
|
const markup = workspace.markup.get(passage.uri)?.passages.find((candidate) => candidate.passage === passage);
|
|
34389
34407
|
if (!markup) return void 0;
|
|
34390
34408
|
return new Map(markup.declarations.declarations.map((declaration) => [declaration.name, declaration.schema]));
|
|
@@ -34517,7 +34535,7 @@ function structureDiagnostics(passage, workspace) {
|
|
|
34517
34535
|
if (token.type === "macro" && !token.isClose) {
|
|
34518
34536
|
diagnostics.push(...parentDiagnostics(passage, token, ancestors, workspace));
|
|
34519
34537
|
diagnostics.push(...childDiagnostics(passage, node, token, workspace));
|
|
34520
|
-
diagnostics.push(...loopDiagnostics(passage, token, ancestors));
|
|
34538
|
+
diagnostics.push(...loopDiagnostics(passage, token, ancestors, workspace));
|
|
34521
34539
|
}
|
|
34522
34540
|
if (!node.body) continue;
|
|
34523
34541
|
const inside = [...ancestors, {
|
|
@@ -34643,13 +34661,13 @@ function statementEnd(code, from) {
|
|
|
34643
34661
|
}
|
|
34644
34662
|
return code.length;
|
|
34645
34663
|
}
|
|
34646
|
-
function loopDiagnostics(passage, token, ancestors) {
|
|
34664
|
+
function loopDiagnostics(passage, token, ancestors, workspace) {
|
|
34647
34665
|
const macro = token.name.toLowerCase();
|
|
34648
|
-
if (macro !== "computed" && macro !== "set" || !token.rawArgs) return [];
|
|
34666
|
+
if (macro !== "computed" && macro !== "set" || !token.rawArgs || workspace.macros.getMacro(macro)?.source !== "builtin") return [];
|
|
34649
34667
|
let loop;
|
|
34650
34668
|
for (let i2 = ancestors.length - 1; i2 >= 0; i2--) {
|
|
34651
34669
|
const ancestor = ancestors[i2];
|
|
34652
|
-
if (ancestor.element) continue;
|
|
34670
|
+
if (ancestor.element || workspace.macros.getMacro(ancestor.name)?.source !== "builtin") continue;
|
|
34653
34671
|
if (DEFERRED_CONTAINERS.has(ancestor.name)) return [];
|
|
34654
34672
|
if (ancestor.name === "for") {
|
|
34655
34673
|
loop = ancestor;
|
|
@@ -34694,7 +34712,8 @@ function argumentDiagnostics(passage, workspace) {
|
|
|
34694
34712
|
for (const token of passage.isMarkup ? macroTokens(passage) : []) {
|
|
34695
34713
|
if (token.type !== "macro" || token.isClose) continue;
|
|
34696
34714
|
const info = workspace.macros.getMacro(token.name);
|
|
34697
|
-
if (!info?.parameters || info.skipArgs ||
|
|
34715
|
+
if (!info?.parameters || info.skipArgs || info.parameterDefs?.length) continue;
|
|
34716
|
+
if (SPINDLE_MACROS.has(token.name.toLowerCase()) && !workspace.macros.hasDiscoveredMacro(token.name)) continue;
|
|
34698
34717
|
let params;
|
|
34699
34718
|
try {
|
|
34700
34719
|
params = new Parameters(info.parameters);
|
|
@@ -34777,14 +34796,14 @@ function describeNavigation(passage) {
|
|
|
34777
34796
|
}
|
|
34778
34797
|
function linkDiagnostics(doc) {
|
|
34779
34798
|
const diagnostics = [];
|
|
34780
|
-
for (const link of findLinkRuntimeMismatches(doc
|
|
34799
|
+
for (const link of findLinkRuntimeMismatches(doc)) {
|
|
34781
34800
|
diagnostics.push(makeDiag(
|
|
34782
34801
|
link.range,
|
|
34783
34802
|
DiagnosticCode.LinkRuntimeMismatch,
|
|
34784
34803
|
`Spindle reads this link differently from how it is written: the link macro reads the label as ${JSON.stringify(link.runtime.display)} and a click ${describeNavigation(link.runtime.passage)}, not to ${JSON.stringify(link.target)}.`
|
|
34785
34804
|
));
|
|
34786
34805
|
}
|
|
34787
|
-
for (const found of findLiteralLinkInterpolations(doc
|
|
34806
|
+
for (const found of findLiteralLinkInterpolations(doc)) {
|
|
34788
34807
|
diagnostics.push(makeDiag(
|
|
34789
34808
|
found.range,
|
|
34790
34809
|
DiagnosticCode.LiteralLinkInterpolation,
|
|
@@ -79927,7 +79946,7 @@ function linkable(name) {
|
|
|
79927
79946
|
return tokens2.length === 1 && link.type === "link" && link.target === name && !bracketLinkMismatch("label", name);
|
|
79928
79947
|
}
|
|
79929
79948
|
function getPassageNameCompletions(workspace) {
|
|
79930
|
-
return workspace.passages.getAllPassages().filter((p) => linkable(p.name)).map((p) => ({
|
|
79949
|
+
return workspace.passages.getAllPassages().filter((p) => isRuntimePassage(p) && linkable(p.name)).map((p) => ({
|
|
79931
79950
|
label: p.name,
|
|
79932
79951
|
kind: 18,
|
|
79933
79952
|
// CompletionItemKind.Reference
|
|
@@ -79942,6 +79961,7 @@ var init_completions = __esm({
|
|
|
79942
79961
|
init_widgets();
|
|
79943
79962
|
init_passage_refs();
|
|
79944
79963
|
init_link_runtime();
|
|
79964
|
+
init_passage_parser();
|
|
79945
79965
|
init_markup_cursor();
|
|
79946
79966
|
init_markup_symbols();
|
|
79947
79967
|
VARIABLE_DETAIL = { $: "story variable", "%": "transient variable", _: "temporary variable", "@": "local/parameter variable" };
|
|
@@ -81388,7 +81408,7 @@ function declareVariable(diag, workspace, sigil) {
|
|
|
81388
81408
|
if (diag.data?.kind !== "undeclared-variable" || diag.data.sigil !== sigil) return [];
|
|
81389
81409
|
const { name } = diag.data;
|
|
81390
81410
|
const passage = sigil === "$" ? workspace.passages.getStoryVariables() : workspace.passages.getStoryTransients();
|
|
81391
|
-
if (!passage) return [];
|
|
81411
|
+
if (!passage || !isRuntimePassage(passage)) return [];
|
|
81392
81412
|
const text3 = workspace.documents.getText(passage.uri);
|
|
81393
81413
|
if (text3 === void 0) return [];
|
|
81394
81414
|
const markup = workspace.markup.get(passage.uri)?.passages.find((p) => p.passage === passage);
|
|
@@ -81404,6 +81424,7 @@ function declareVariable(diag, workspace, sigil) {
|
|
|
81404
81424
|
}];
|
|
81405
81425
|
}
|
|
81406
81426
|
function fixNoStoryVariables(workspace) {
|
|
81427
|
+
if (workspace.passages.getStoryVariables()) return null;
|
|
81407
81428
|
const targetUri = missingStoryVariablesOwner(workspace);
|
|
81408
81429
|
if (targetUri === void 0) return null;
|
|
81409
81430
|
const text3 = workspace.documents.getText(targetUri);
|
|
@@ -81454,7 +81475,7 @@ function fixBrokenLink(uri, diag, workspace) {
|
|
|
81454
81475
|
});
|
|
81455
81476
|
}
|
|
81456
81477
|
const header = `:: ${name.replace(/[\\[\]{}]/g, "\\$&")}`;
|
|
81457
|
-
if (name.trim() === name && name !== "" && !/[\r\n]/.test(name)) {
|
|
81478
|
+
if (!workspace.passages.getPassage(name) && name.trim() === name && name !== "" && !/[\r\n]/.test(name)) {
|
|
81458
81479
|
const edit = insertLinesAt(text3, text3.split("\n").length, `
|
|
81459
81480
|
${header}
|
|
81460
81481
|
`, lineEndingFor(workspace, uri));
|
|
@@ -81523,6 +81544,7 @@ var init_code_actions = __esm({
|
|
|
81523
81544
|
init_rename();
|
|
81524
81545
|
init_js_string_literal();
|
|
81525
81546
|
init_text();
|
|
81547
|
+
init_passage_parser();
|
|
81526
81548
|
DEFAULT_CONFIG_FILENAME = "spindle.config.yaml";
|
|
81527
81549
|
NEW_MACRO_ENTRY = { description: "" };
|
|
81528
81550
|
fixUndeclaredVariable = (diag, workspace) => declareVariable(diag, workspace, "$");
|