@rohal12/spindle-lsp 0.13.2 → 0.14.0
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 +1551 -767
- package/dist/bin.js.map +4 -4
- package/package.json +3 -3
package/dist/bin.js
CHANGED
|
@@ -6174,7 +6174,7 @@ function isRawMacro(name) {
|
|
|
6174
6174
|
return RAW_BODY_MACROS.has(name);
|
|
6175
6175
|
}
|
|
6176
6176
|
function isBlockMacro(name) {
|
|
6177
|
-
return BLOCK_MACROS.has(name);
|
|
6177
|
+
return BLOCK_MACROS.has(name) || BLOCK_WIDGETS.has(name);
|
|
6178
6178
|
}
|
|
6179
6179
|
function buildAst(nodes) {
|
|
6180
6180
|
return nodes.map(astNode);
|
|
@@ -6445,7 +6445,7 @@ function getLineInfo(input, offset2) {
|
|
|
6445
6445
|
}
|
|
6446
6446
|
function getOptions(opts) {
|
|
6447
6447
|
var options = {};
|
|
6448
|
-
for (var opt in defaultOptions) options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt];
|
|
6448
|
+
for (var opt in defaultOptions) options[opt] = opts && hasOwn$1(opts, opt) ? opts[opt] : defaultOptions[opt];
|
|
6449
6449
|
if (options.ecmaVersion === "latest") options.ecmaVersion = 1e8;
|
|
6450
6450
|
else if (options.ecmaVersion == null) {
|
|
6451
6451
|
if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) {
|
|
@@ -6617,7 +6617,7 @@ function transientAssignment(p, end) {
|
|
|
6617
6617
|
if (t === types$1.eof) return false;
|
|
6618
6618
|
if (depth > 0) {
|
|
6619
6619
|
if (OPENERS.has(t)) depth++;
|
|
6620
|
-
else if (CLOSERS.has(t)) depth--;
|
|
6620
|
+
else if (CLOSERS$1.has(t)) depth--;
|
|
6621
6621
|
} else if (t === types$1.bracketL) depth = 1;
|
|
6622
6622
|
else if (t === types$1.dot) {
|
|
6623
6623
|
q2.nextToken();
|
|
@@ -6628,6 +6628,9 @@ function transientAssignment(p, end) {
|
|
|
6628
6628
|
return false;
|
|
6629
6629
|
}
|
|
6630
6630
|
}
|
|
6631
|
+
function isMemberDot(type) {
|
|
6632
|
+
return type === types$1.dot || type === types$1.questionDot;
|
|
6633
|
+
}
|
|
6631
6634
|
function tokenizerAt(src, start, goal, { onComment, afterOperand = false } = {}) {
|
|
6632
6635
|
const p = new SigilParser(onComment ? {
|
|
6633
6636
|
...OPTIONS,
|
|
@@ -6699,6 +6702,9 @@ function bracketsBefore(src, pos) {
|
|
|
6699
6702
|
};
|
|
6700
6703
|
}
|
|
6701
6704
|
function parseCode(src, goal = "expression") {
|
|
6705
|
+
return parseWithAst(src, goal).out;
|
|
6706
|
+
}
|
|
6707
|
+
function parseWithAst(src, goal) {
|
|
6702
6708
|
const percentAt = /* @__PURE__ */ new Map();
|
|
6703
6709
|
for (; ; ) {
|
|
6704
6710
|
const transientsRead = /* @__PURE__ */ new Set();
|
|
@@ -6710,7 +6716,10 @@ function parseCode(src, goal = "expression") {
|
|
|
6710
6716
|
};
|
|
6711
6717
|
walk(ast, src, out, false, false);
|
|
6712
6718
|
out.refs.sort((a, b) => a.start - b.start);
|
|
6713
|
-
return
|
|
6719
|
+
return {
|
|
6720
|
+
out,
|
|
6721
|
+
ast
|
|
6722
|
+
};
|
|
6714
6723
|
} catch (error48) {
|
|
6715
6724
|
const pos = error48.pos ?? -1;
|
|
6716
6725
|
if (!(error48 instanceof SyntaxError) || percentAt.has(pos)) throw error48;
|
|
@@ -6846,8 +6855,8 @@ function walk(node, src, out, binding, shorthand) {
|
|
|
6846
6855
|
}
|
|
6847
6856
|
}
|
|
6848
6857
|
}
|
|
6849
|
-
function findCodeEnd(src, start, { goal = "expression", stop } = {}) {
|
|
6850
|
-
const end = scanCodeEnd(src, start, goal, stop);
|
|
6858
|
+
function findCodeEnd(src, start, { goal = "expression", stop, onRunOut } = {}) {
|
|
6859
|
+
const end = scanCodeEnd(src, start, goal, stop, onRunOut);
|
|
6851
6860
|
return end < 0 && !stop ? parsedCodeEnd(src, start, goal) : end;
|
|
6852
6861
|
}
|
|
6853
6862
|
function parsedCodeEnd(src, start, goal) {
|
|
@@ -6865,7 +6874,11 @@ function parsedCodeEnd(src, start, goal) {
|
|
|
6865
6874
|
}
|
|
6866
6875
|
return -1;
|
|
6867
6876
|
}
|
|
6868
|
-
function scanCodeEnd(src, start, goal, stop) {
|
|
6877
|
+
function scanCodeEnd(src, start, goal, stop, onRunOut) {
|
|
6878
|
+
const ranOut = () => {
|
|
6879
|
+
onRunOut?.();
|
|
6880
|
+
return -1;
|
|
6881
|
+
};
|
|
6869
6882
|
const stack = [];
|
|
6870
6883
|
let prevEnd = -1;
|
|
6871
6884
|
let prevWord = false;
|
|
@@ -6881,11 +6894,12 @@ function scanCodeEnd(src, start, goal, stop) {
|
|
|
6881
6894
|
if (!/^Unterminated/.test(message) && !inTemplate) {
|
|
6882
6895
|
resumeAt = Math.max(tok.pos, from) + 1;
|
|
6883
6896
|
afterOperand = false;
|
|
6884
|
-
if (resumeAt >= src.length) return
|
|
6897
|
+
if (resumeAt >= src.length) return ranOut();
|
|
6885
6898
|
break;
|
|
6886
6899
|
}
|
|
6887
6900
|
const k2 = stack.lastIndexOf("${");
|
|
6888
|
-
if (!/^Unterminated template/.test(message) || k2 < 0 || templateSlip || stop) return -1;
|
|
6901
|
+
if (!/^Unterminated template/.test(message) || k2 < 0 || templateSlip || stop) return /^Unterminated/.test(message) && !/^Unterminated regular/.test(message) && !(/^Unterminated string/.test(message) && prevWord && tok.pos === prevEnd) ? ranOut() : -1;
|
|
6902
|
+
onRunOut?.();
|
|
6889
6903
|
templateSlip = true;
|
|
6890
6904
|
stack.length = k2;
|
|
6891
6905
|
resumeAt = tok.pos;
|
|
@@ -6894,7 +6908,7 @@ function scanCodeEnd(src, start, goal, stop) {
|
|
|
6894
6908
|
}
|
|
6895
6909
|
if (tok.restarted && stack.includes("${")) return -1;
|
|
6896
6910
|
const t = tok.type;
|
|
6897
|
-
if (t === types$1.eof) return
|
|
6911
|
+
if (t === types$1.eof) return ranOut();
|
|
6898
6912
|
if (t === types$1.string && prevWord && tok.start === prevEnd) return -1;
|
|
6899
6913
|
prevWord = t === types$1.name && !WORDS_BEFORE_STRING.has(tok.value) || t === types$1.num;
|
|
6900
6914
|
prevEnd = tok.end;
|
|
@@ -7035,7 +7049,7 @@ function walkTokens(src, from, handlers, nesting, goal, oneTemplate) {
|
|
|
7035
7049
|
if (t === types$1.name) {
|
|
7036
7050
|
const sigil = sigilAt(src, tok.start, tok.value);
|
|
7037
7051
|
const property = prev === types$1.dot || prev === types$1.questionDot || (sigil === "$" || sigil === "_") && keyPosition(src, tok.end, prev);
|
|
7038
|
-
if (sigil && !property) handlers.variable?.(sigil,
|
|
7052
|
+
if (sigil && !property) handlers.variable?.(sigil, tok.value.slice(1), tok.start, nesting, tok.end);
|
|
7039
7053
|
else code(tok.start, tok.end);
|
|
7040
7054
|
} else if (t === types$1.string || t === types$1.regexp || t === types$1.template || t === types$1.invalidTemplate) literal3(tok.start, tok.end);
|
|
7041
7055
|
else if (t === types$1.backQuote) {
|
|
@@ -7122,48 +7136,107 @@ function scanStringLiteral(src, start) {
|
|
|
7122
7136
|
function skipLiteral(input, i2) {
|
|
7123
7137
|
const quote = input[i2];
|
|
7124
7138
|
const template = quote === "`";
|
|
7139
|
+
let ranOut = false;
|
|
7125
7140
|
for (let j2 = i2 + 1; j2 < input.length; ) {
|
|
7126
7141
|
const c = input[j2];
|
|
7127
7142
|
if (c === "\\") j2 += 2;
|
|
7128
|
-
else if (c === quote) return
|
|
7129
|
-
|
|
7143
|
+
else if (c === quote) return {
|
|
7144
|
+
end: j2 + 1,
|
|
7145
|
+
ranOut
|
|
7146
|
+
};
|
|
7147
|
+
else if (!template && c === "\n") return {
|
|
7148
|
+
end: -1,
|
|
7149
|
+
ranOut
|
|
7150
|
+
};
|
|
7130
7151
|
else if (template && c === "$" && input[j2 + 1] === "{") {
|
|
7131
|
-
const close =
|
|
7132
|
-
|
|
7133
|
-
|
|
7152
|
+
const close = lenientRead(input, j2 + 2);
|
|
7153
|
+
ranOut || (ranOut = close.ranOut);
|
|
7154
|
+
if (close.end === -1) return {
|
|
7155
|
+
end: -1,
|
|
7156
|
+
ranOut
|
|
7157
|
+
};
|
|
7158
|
+
j2 = close.end + 1;
|
|
7134
7159
|
} else j2++;
|
|
7135
7160
|
}
|
|
7136
|
-
return
|
|
7161
|
+
return {
|
|
7162
|
+
end: -1,
|
|
7163
|
+
ranOut: ranOut || template
|
|
7164
|
+
};
|
|
7165
|
+
}
|
|
7166
|
+
function lenientClose(input, i2, onRunOut) {
|
|
7167
|
+
const { end, ranOut } = lenientRead(input, i2);
|
|
7168
|
+
if (ranOut) onRunOut?.();
|
|
7169
|
+
return end;
|
|
7137
7170
|
}
|
|
7138
|
-
function
|
|
7171
|
+
function lenientRead(input, i2) {
|
|
7139
7172
|
if (memoInput !== input) {
|
|
7140
7173
|
memoInput = input;
|
|
7141
7174
|
memo.clear();
|
|
7142
7175
|
}
|
|
7143
|
-
let
|
|
7144
|
-
if (
|
|
7145
|
-
|
|
7146
|
-
memo.set(i2,
|
|
7176
|
+
let read = memo.get(i2);
|
|
7177
|
+
if (read === void 0) {
|
|
7178
|
+
read = scanLenient(input, i2);
|
|
7179
|
+
memo.set(i2, read);
|
|
7147
7180
|
}
|
|
7148
|
-
return
|
|
7181
|
+
return read;
|
|
7149
7182
|
}
|
|
7150
7183
|
function scanLenient(input, i2) {
|
|
7151
7184
|
let depth = 0;
|
|
7185
|
+
let ranOut = false;
|
|
7152
7186
|
while (i2 < input.length) {
|
|
7153
7187
|
const c = input[i2];
|
|
7154
7188
|
if (c === "{") {
|
|
7155
7189
|
depth++;
|
|
7156
7190
|
i2++;
|
|
7157
7191
|
} else if (c === "}") {
|
|
7158
|
-
if (depth === 0) return
|
|
7192
|
+
if (depth === 0) return {
|
|
7193
|
+
end: i2,
|
|
7194
|
+
ranOut
|
|
7195
|
+
};
|
|
7159
7196
|
depth--;
|
|
7160
7197
|
i2++;
|
|
7161
7198
|
} else if (c === "`" || (c === '"' || c === "'") && !(i2 > 0 && NON_STRING_QUOTE_PREFIX.test(input[i2 - 1]))) {
|
|
7162
7199
|
const close = skipLiteral(input, i2);
|
|
7163
|
-
|
|
7200
|
+
ranOut || (ranOut = close.ranOut);
|
|
7201
|
+
i2 = close.end === -1 ? i2 + 1 : close.end;
|
|
7164
7202
|
} else i2++;
|
|
7165
7203
|
}
|
|
7166
|
-
return
|
|
7204
|
+
return {
|
|
7205
|
+
end: -1,
|
|
7206
|
+
ranOut: true
|
|
7207
|
+
};
|
|
7208
|
+
}
|
|
7209
|
+
function jsCodeEnd(onOpenEnd) {
|
|
7210
|
+
return {
|
|
7211
|
+
closeBrace(input, codeStart, lenientStart) {
|
|
7212
|
+
let ranOut = false;
|
|
7213
|
+
const onRunOut = () => ranOut = true;
|
|
7214
|
+
const strict = findCodeEnd(input, codeStart, { onRunOut });
|
|
7215
|
+
const end = strict !== -1 ? strict : lenientClose(input, lenientStart, onRunOut);
|
|
7216
|
+
if (ranOut) onOpenEnd?.(input, codeStart);
|
|
7217
|
+
return end;
|
|
7218
|
+
},
|
|
7219
|
+
rawBodyEnd(input, bodyStart, name) {
|
|
7220
|
+
const closer = `\\{/${name}\\s*\\}`;
|
|
7221
|
+
const first = new RegExp(closer, "gi");
|
|
7222
|
+
first.lastIndex = bodyStart;
|
|
7223
|
+
const firstAt = first.exec(input)?.index ?? -1;
|
|
7224
|
+
if (firstAt === -1) return -1;
|
|
7225
|
+
const at3 = new RegExp(closer, "iy");
|
|
7226
|
+
let ranOut = false;
|
|
7227
|
+
const end = findCodeEnd(input, bodyStart, {
|
|
7228
|
+
goal: "statements",
|
|
7229
|
+
stop: (k2) => {
|
|
7230
|
+
at3.lastIndex = k2;
|
|
7231
|
+
return at3.test(input);
|
|
7232
|
+
},
|
|
7233
|
+
onRunOut: () => ranOut = true
|
|
7234
|
+
});
|
|
7235
|
+
if (end !== -1) return end;
|
|
7236
|
+
if (onOpenEnd && (ranOut || new RegExp(`\\{/${name}\\s*$`, "i").test(input))) onOpenEnd(input, bodyStart);
|
|
7237
|
+
return firstAt;
|
|
7238
|
+
}
|
|
7239
|
+
};
|
|
7167
7240
|
}
|
|
7168
7241
|
function isCodeAttribute(name) {
|
|
7169
7242
|
const lower = name.toLowerCase();
|
|
@@ -7195,7 +7268,7 @@ function splitSigilTemplate(template) {
|
|
|
7195
7268
|
if (text2) parts.push({ text: text2 });
|
|
7196
7269
|
return parts;
|
|
7197
7270
|
}
|
|
7198
|
-
function run(source, startRule, options) {
|
|
7271
|
+
function run$1(source, startRule, options) {
|
|
7199
7272
|
const hooks = options.hooks ? {
|
|
7200
7273
|
...defaultHooks,
|
|
7201
7274
|
...options.hooks
|
|
@@ -7217,7 +7290,7 @@ function run(source, startRule, options) {
|
|
|
7217
7290
|
}
|
|
7218
7291
|
}
|
|
7219
7292
|
function analyzeMarkup(source, options = {}) {
|
|
7220
|
-
const { tokens: tokens2, errors, damage } =
|
|
7293
|
+
const { tokens: tokens2, errors, damage } = scanMarkupTolerant(source, options);
|
|
7221
7294
|
const hooks = {
|
|
7222
7295
|
...defaultHooks,
|
|
7223
7296
|
...options.hooks
|
|
@@ -7252,23 +7325,23 @@ function pairingError(source, error48) {
|
|
|
7252
7325
|
return new MarkupError(error48.message, error48.start, line, column, error48.code, error48.end, error48.data);
|
|
7253
7326
|
}
|
|
7254
7327
|
function tokenizeMarkup(source, options = {}) {
|
|
7255
|
-
return run(source, "Tokens", options);
|
|
7328
|
+
return run$1(source, "Tokens", options);
|
|
7256
7329
|
}
|
|
7257
7330
|
function parseSelectors(source, at3 = 0) {
|
|
7258
|
-
const found = run(source.slice(at3), "SelectorsPrefix", {});
|
|
7331
|
+
const found = run$1(source.slice(at3), "SelectorsPrefix", {});
|
|
7259
7332
|
return {
|
|
7260
7333
|
...found,
|
|
7261
7334
|
end: at3 + found.end
|
|
7262
7335
|
};
|
|
7263
7336
|
}
|
|
7264
7337
|
function tokenizeMarkupTolerant(source, options = {}) {
|
|
7265
|
-
const { tokens: tokens2, errors } =
|
|
7338
|
+
const { tokens: tokens2, errors } = scanMarkupTolerant(source, options);
|
|
7266
7339
|
return {
|
|
7267
7340
|
tokens: tokens2,
|
|
7268
7341
|
errors
|
|
7269
7342
|
};
|
|
7270
7343
|
}
|
|
7271
|
-
function
|
|
7344
|
+
function scanMarkupTolerant(source, options = {}) {
|
|
7272
7345
|
const tokens2 = [];
|
|
7273
7346
|
const errors = [];
|
|
7274
7347
|
const damage = [];
|
|
@@ -7416,15 +7489,15 @@ function topLevelIndices(src, isSeparator) {
|
|
|
7416
7489
|
} });
|
|
7417
7490
|
return indices;
|
|
7418
7491
|
}
|
|
7419
|
-
function
|
|
7420
|
-
const
|
|
7492
|
+
function topLevelSpans(src, isSeparator) {
|
|
7493
|
+
const spans = [];
|
|
7421
7494
|
let from = 0;
|
|
7422
7495
|
for (const i2 of topLevelIndices(src, isSeparator)) {
|
|
7423
|
-
|
|
7496
|
+
spans.push([from, i2]);
|
|
7424
7497
|
from = i2 + 1;
|
|
7425
7498
|
}
|
|
7426
|
-
|
|
7427
|
-
return
|
|
7499
|
+
spans.push([from, src.length]);
|
|
7500
|
+
return spans;
|
|
7428
7501
|
}
|
|
7429
7502
|
function isStandaloneValue(token) {
|
|
7430
7503
|
return startsLikeValue(token) && !endsWithOperator(token);
|
|
@@ -7441,21 +7514,31 @@ function startsLikeValue(token) {
|
|
|
7441
7514
|
return false;
|
|
7442
7515
|
}
|
|
7443
7516
|
function trySplitOnWhitespace(raw) {
|
|
7444
|
-
const args2 =
|
|
7517
|
+
const args2 = topLevelSpans(raw, isWhitespace).filter(([a, b]) => b > a);
|
|
7445
7518
|
if (args2.length < 2) return null;
|
|
7446
|
-
for (const
|
|
7519
|
+
for (const [a, b] of args2) if (!isStandaloneValue(raw.slice(a, b))) return null;
|
|
7447
7520
|
return args2;
|
|
7448
7521
|
}
|
|
7449
|
-
function
|
|
7450
|
-
const
|
|
7522
|
+
function trimmed$1(src, [start, end]) {
|
|
7523
|
+
const text2 = src.slice(start, end);
|
|
7524
|
+
const lead = text2.length - text2.trimStart().length;
|
|
7525
|
+
return [start + lead, Math.max(start + lead, end - (text2.length - text2.trimEnd().length))];
|
|
7526
|
+
}
|
|
7527
|
+
function splitArgSpans(raw) {
|
|
7528
|
+
const args2 = topLevelSpans(raw, (ch) => ch === ",").map((span) => trimmed$1(raw, span));
|
|
7451
7529
|
const hasComma = args2.length > 1;
|
|
7452
|
-
|
|
7530
|
+
const last2 = args2[args2.length - 1];
|
|
7531
|
+
if (last2[0] === last2[1]) args2.pop();
|
|
7453
7532
|
if (!hasComma && args2.length === 1) {
|
|
7454
|
-
const
|
|
7455
|
-
|
|
7533
|
+
const [start, end] = args2[0];
|
|
7534
|
+
const split = trySplitOnWhitespace(raw.slice(start, end));
|
|
7535
|
+
if (split) return split.map(([a, b]) => [start + a, start + b]);
|
|
7456
7536
|
}
|
|
7457
7537
|
return args2;
|
|
7458
7538
|
}
|
|
7539
|
+
function splitArgs(raw) {
|
|
7540
|
+
return splitArgSpans(raw).map(([a, b]) => raw.slice(a, b));
|
|
7541
|
+
}
|
|
7459
7542
|
function terms(src) {
|
|
7460
7543
|
const spans = [];
|
|
7461
7544
|
let start = 0;
|
|
@@ -7529,8 +7612,9 @@ function readOptions(params, src, { at: at3, spans }) {
|
|
|
7529
7612
|
}
|
|
7530
7613
|
return options;
|
|
7531
7614
|
}
|
|
7532
|
-
function takeFlag(src, word) {
|
|
7615
|
+
function takeFlag(src, word, alone) {
|
|
7533
7616
|
const spans = terms(src);
|
|
7617
|
+
if (spans.length === 1) return alone && slice(src, spans[0]) === word ? [src.length, src.length] : null;
|
|
7534
7618
|
if (spans.length < 2) return null;
|
|
7535
7619
|
if (slice(src, spans[spans.length - 1]) === word) {
|
|
7536
7620
|
const rest = [0, spans[spans.length - 2][1]];
|
|
@@ -7565,8 +7649,9 @@ function trimmed(src, at3) {
|
|
|
7565
7649
|
}
|
|
7566
7650
|
function readGroup(params, src, args2, { at: srcAt, spans }) {
|
|
7567
7651
|
let [text2, at3] = trimmed(src ?? "", srcAt);
|
|
7652
|
+
const alone = !params.some((p) => p.type !== "flag" && p.required);
|
|
7568
7653
|
for (const flag of params.filter((p) => p.type === "flag")) {
|
|
7569
|
-
const rest2 = src === null ? null : takeFlag(text2, flag.name);
|
|
7654
|
+
const rest2 = src === null ? null : takeFlag(text2, flag.name, alone);
|
|
7570
7655
|
args2[flag.name] = rest2 !== null;
|
|
7571
7656
|
if (rest2) [text2, at3] = trimmed(slice(text2, rest2), at3 + rest2[0]);
|
|
7572
7657
|
}
|
|
@@ -7637,9 +7722,40 @@ function passageTarget(arg) {
|
|
|
7637
7722
|
name
|
|
7638
7723
|
};
|
|
7639
7724
|
}
|
|
7725
|
+
function checkParameterTypes(macro, parameters) {
|
|
7726
|
+
const holdsFix = `Give a \`string\` or \`text\` parameter one of ${STRING_HOLDS.join(", ")} to hold (see docs/custom-macros.md#what-a-string-holds).`;
|
|
7727
|
+
for (const param of parameters) {
|
|
7728
|
+
const type = param.type;
|
|
7729
|
+
if (!PARAMETER_TYPES.includes(type)) throw parameterError(macro, param, type === void 0 ? "has no type" : `has the unknown type ${JSON.stringify(type)}`, `Give it one of the types ${PARAMETER_TYPES.join(", ")} (see docs/custom-macros.md#parameter-types), or declare no parameters and read props.rawArgs.`);
|
|
7730
|
+
const holds = param.holds;
|
|
7731
|
+
if (holds !== void 0 && type !== "string" && type !== "text") throw parameterError(macro, param, `is of the type ${type}, which holds what it is`, holdsFix);
|
|
7732
|
+
if (holds !== void 0 && !STRING_HOLDS.includes(holds)) throw parameterError(macro, param, `holds the unknown ${JSON.stringify(holds)}`, holdsFix);
|
|
7733
|
+
if (param.parameters) checkParameterTypes(macro, param.parameters);
|
|
7734
|
+
}
|
|
7735
|
+
}
|
|
7736
|
+
function parameterError(macro, param, problem, fix) {
|
|
7737
|
+
return /* @__PURE__ */ new Error(`spindle: The parameter "${param.name}" of the macro {${macro}} ${problem}. ${fix}`);
|
|
7738
|
+
}
|
|
7739
|
+
function getMacroRegistry() {
|
|
7740
|
+
return Array.from(metadataRegistry.values());
|
|
7741
|
+
}
|
|
7640
7742
|
function subMacroParameters(name) {
|
|
7641
7743
|
return SUB_MACRO_PARAMETERS.get(name.toLowerCase());
|
|
7642
7744
|
}
|
|
7745
|
+
function variableNameError(name, label2 = name) {
|
|
7746
|
+
return name === "__proto__" ? `"${label2}" cannot be used as a variable name (${RESERVED_NAME} is reserved)` : void 0;
|
|
7747
|
+
}
|
|
7748
|
+
function ownEntries(sources, keep = () => true) {
|
|
7749
|
+
const record2 = /* @__PURE__ */ Object.create(null);
|
|
7750
|
+
for (const source of sources) {
|
|
7751
|
+
if (!source) continue;
|
|
7752
|
+
for (const key of Object.keys(source)) {
|
|
7753
|
+
const value = source[key];
|
|
7754
|
+
if (keep(value)) record2[key] = value;
|
|
7755
|
+
}
|
|
7756
|
+
}
|
|
7757
|
+
return record2;
|
|
7758
|
+
}
|
|
7643
7759
|
function withParseCache(fn) {
|
|
7644
7760
|
const outer = parses;
|
|
7645
7761
|
parses = /* @__PURE__ */ new Map();
|
|
@@ -7668,6 +7784,13 @@ function pieceOffset(piece, index) {
|
|
|
7668
7784
|
function extentOf(piece) {
|
|
7669
7785
|
return piece.kind === "code" ? piece.code.length : piece.kind === "text" ? piece.text.length : piece.length;
|
|
7670
7786
|
}
|
|
7787
|
+
function widgetParameters(params, holds = {}) {
|
|
7788
|
+
if (!params.some((param) => hasOwn(holds, param))) return void 0;
|
|
7789
|
+
return params.map((name) => ({
|
|
7790
|
+
name,
|
|
7791
|
+
...hasOwn(holds, name) ? { holds: holds[name] } : {}
|
|
7792
|
+
}));
|
|
7793
|
+
}
|
|
7671
7794
|
function withHolds(params, holds) {
|
|
7672
7795
|
return params.map((param) => {
|
|
7673
7796
|
if (param.parameters) return {
|
|
@@ -7682,8 +7805,13 @@ function withHolds(params, holds) {
|
|
|
7682
7805
|
}
|
|
7683
7806
|
function parameterLookup(macros) {
|
|
7684
7807
|
const parameters = new NameMap();
|
|
7685
|
-
|
|
7686
|
-
|
|
7808
|
+
const widgets = new NameMap();
|
|
7809
|
+
for (const { name, parameters: params, interpolate, widget } of macros) {
|
|
7810
|
+
if (params) parameters.set(name, withHolds(params, holdsByDefault(interpolate)));
|
|
7811
|
+
const declared = widget && widgetParameters(widget.params, widget.holds);
|
|
7812
|
+
if (declared) widgets.set(name, declared);
|
|
7813
|
+
}
|
|
7814
|
+
const lookup = (name) => {
|
|
7687
7815
|
let params = parameters.get(name);
|
|
7688
7816
|
if (!params) {
|
|
7689
7817
|
const sub = subMacroParameters(name);
|
|
@@ -7691,6 +7819,8 @@ function parameterLookup(macros) {
|
|
|
7691
7819
|
}
|
|
7692
7820
|
return params;
|
|
7693
7821
|
};
|
|
7822
|
+
if (widgets.size > 0) lookup.widget = (name) => widgets.get(name);
|
|
7823
|
+
return lookup;
|
|
7694
7824
|
}
|
|
7695
7825
|
function codeGoal(param) {
|
|
7696
7826
|
if (param.type === "expression" || param.type === "passage") return "expression";
|
|
@@ -7781,6 +7911,8 @@ function* codeAndText(src, tokens2, parametersOf2) {
|
|
|
7781
7911
|
}
|
|
7782
7912
|
const params = parametersOf2(name);
|
|
7783
7913
|
if (params) yield* argPieces(args2, argsAt, params, token.name, label2);
|
|
7914
|
+
const widget = parametersOf2.widget?.(name);
|
|
7915
|
+
if (widget) yield* widgetPieces(args2, argsAt, widget, token.name, label2);
|
|
7784
7916
|
}
|
|
7785
7917
|
}
|
|
7786
7918
|
}
|
|
@@ -7836,23 +7968,42 @@ function nestedPiece(piece, toRoot, where2) {
|
|
|
7836
7968
|
...nested
|
|
7837
7969
|
};
|
|
7838
7970
|
}
|
|
7839
|
-
function
|
|
7971
|
+
function escapeAt(raw, i2, escapes) {
|
|
7972
|
+
if (escapes === "quotes") {
|
|
7973
|
+
const next = raw.charAt(i2 + 1);
|
|
7974
|
+
return /["'\\]/.test(next) ? {
|
|
7975
|
+
length: 2,
|
|
7976
|
+
text: next
|
|
7977
|
+
} : void 0;
|
|
7978
|
+
}
|
|
7979
|
+
JS_ESCAPE_RE.lastIndex = i2;
|
|
7980
|
+
const written2 = JS_ESCAPE_RE.exec(raw)?.[0];
|
|
7981
|
+
const text2 = written2 && stringLiteralValue(`"${written2}"`);
|
|
7982
|
+
return typeof text2 === "string" ? {
|
|
7983
|
+
length: written2.length,
|
|
7984
|
+
text: text2
|
|
7985
|
+
} : void 0;
|
|
7986
|
+
}
|
|
7987
|
+
function escapeOffsets(raw, at3, value, escapes) {
|
|
7840
7988
|
const offsets = [];
|
|
7841
7989
|
let escaped = false;
|
|
7842
7990
|
let i2 = 0;
|
|
7843
7991
|
while (offsets.length < value.length) {
|
|
7844
7992
|
if (i2 >= raw.length) return void 0;
|
|
7845
|
-
|
|
7846
|
-
if (
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
}
|
|
7993
|
+
const escape2 = raw[i2] === "\\" ? escapeAt(raw, i2, escapes) : void 0;
|
|
7994
|
+
if (!escape2) {
|
|
7995
|
+
offsets.push(at3 + i2++);
|
|
7996
|
+
continue;
|
|
7997
|
+
}
|
|
7998
|
+
if (!value.startsWith(escape2.text, offsets.length)) return void 0;
|
|
7999
|
+
for (let k2 = 0; k2 < escape2.text.length; k2++) offsets.push(at3 + i2);
|
|
8000
|
+
escaped = true;
|
|
8001
|
+
i2 += escape2.length;
|
|
7850
8002
|
}
|
|
7851
8003
|
offsets.push(at3 + i2);
|
|
7852
8004
|
return escaped ? offsets : void 0;
|
|
7853
8005
|
}
|
|
7854
8006
|
function* argPieces(args2, offset2, params, macro, label2) {
|
|
7855
|
-
const name = macro.toLowerCase();
|
|
7856
8007
|
let values;
|
|
7857
8008
|
const spans = /* @__PURE__ */ new Map();
|
|
7858
8009
|
try {
|
|
@@ -7865,10 +8016,34 @@ function* argPieces(args2, offset2, params, macro, label2) {
|
|
|
7865
8016
|
offset: offset2,
|
|
7866
8017
|
length: args2.length,
|
|
7867
8018
|
label: label2,
|
|
7868
|
-
macro:
|
|
8019
|
+
macro: macro.toLowerCase()
|
|
7869
8020
|
};
|
|
7870
8021
|
return;
|
|
7871
8022
|
}
|
|
8023
|
+
yield* valuePieces(args2, offset2, params, values, spans, macro, label2, "quotes");
|
|
8024
|
+
}
|
|
8025
|
+
function* widgetPieces(args2, offset2, params, macro, label2) {
|
|
8026
|
+
const written2 = splitArgSpans(args2);
|
|
8027
|
+
const declared = [];
|
|
8028
|
+
const values = {};
|
|
8029
|
+
const spans = /* @__PURE__ */ new Map();
|
|
8030
|
+
params.forEach(({ name, holds }, i2) => {
|
|
8031
|
+
const span = written2[i2];
|
|
8032
|
+
const value = span && stringLiteralValue(args2.slice(...span));
|
|
8033
|
+
if (!holds || value == null) return;
|
|
8034
|
+
const param = {
|
|
8035
|
+
name,
|
|
8036
|
+
type: "string",
|
|
8037
|
+
holds
|
|
8038
|
+
};
|
|
8039
|
+
declared.push(param);
|
|
8040
|
+
values[name] = value;
|
|
8041
|
+
spans.set(param, span);
|
|
8042
|
+
});
|
|
8043
|
+
yield* valuePieces(args2, offset2, declared, values, spans, macro, label2, "javascript");
|
|
8044
|
+
}
|
|
8045
|
+
function* valuePieces(args2, offset2, params, values, spans, macro, label2, escapes) {
|
|
8046
|
+
const name = macro.toLowerCase();
|
|
7872
8047
|
function* visit(list3, from) {
|
|
7873
8048
|
for (const param of list3) {
|
|
7874
8049
|
const value = from[param.name];
|
|
@@ -7913,7 +8088,7 @@ function* argPieces(args2, offset2, params, macro, label2) {
|
|
|
7913
8088
|
}
|
|
7914
8089
|
const at3 = offset2 + start + (value !== written2 && /^["']/.test(written2) ? 1 : 0);
|
|
7915
8090
|
const holds = stringHolds(param);
|
|
7916
|
-
const sourceOffsets = escapeOffsets(args2.slice(at3 - offset2), at3, value);
|
|
8091
|
+
const sourceOffsets = escapeOffsets(args2.slice(at3 - offset2), at3, value, escapes);
|
|
7917
8092
|
if (holds === "expression" || holds === "statements") {
|
|
7918
8093
|
const piece = {
|
|
7919
8094
|
kind: "code",
|
|
@@ -7966,15 +8141,13 @@ function attributeValues(src, token) {
|
|
|
7966
8141
|
function sigilExpressions(value) {
|
|
7967
8142
|
const found = [];
|
|
7968
8143
|
let from = 0;
|
|
7969
|
-
for (const part of splitSigilTemplate(value)) {
|
|
7970
|
-
if (!("expr" in part)) continue;
|
|
7971
|
-
const at3 = locate(value, part.expr, from);
|
|
7972
|
-
from = at3 + part.expr.length;
|
|
8144
|
+
for (const part of splitSigilTemplate(value)) if ("expr" in part) {
|
|
7973
8145
|
found.push({
|
|
7974
8146
|
expr: part.expr,
|
|
7975
|
-
at:
|
|
8147
|
+
at: from + 1
|
|
7976
8148
|
});
|
|
7977
|
-
|
|
8149
|
+
from += part.expr.length + 2;
|
|
8150
|
+
} else from += ("text" in part ? part.text : part.verbatim).length;
|
|
7978
8151
|
return found;
|
|
7979
8152
|
}
|
|
7980
8153
|
function locate(text2, part, from) {
|
|
@@ -7983,23 +8156,6 @@ function locate(text2, part, from) {
|
|
|
7983
8156
|
const anywhere = text2.indexOf(part);
|
|
7984
8157
|
return anywhere >= 0 ? anywhere : from;
|
|
7985
8158
|
}
|
|
7986
|
-
function checkParameterTypes(macro, parameters) {
|
|
7987
|
-
const holdsFix = `Give a \`string\` or \`text\` parameter one of ${STRING_HOLDS.join(", ")} to hold (see docs/custom-macros.md#what-a-string-holds).`;
|
|
7988
|
-
for (const param of parameters) {
|
|
7989
|
-
const type = param.type;
|
|
7990
|
-
if (!PARAMETER_TYPES.includes(type)) throw parameterError(macro, param, type === void 0 ? "has no type" : `has the unknown type ${JSON.stringify(type)}`, `Give it one of the types ${PARAMETER_TYPES.join(", ")} (see docs/custom-macros.md#parameter-types), or declare no parameters and read props.rawArgs.`);
|
|
7991
|
-
const holds = param.holds;
|
|
7992
|
-
if (holds !== void 0 && type !== "string" && type !== "text") throw parameterError(macro, param, `is of the type ${type}, which holds what it is`, holdsFix);
|
|
7993
|
-
if (holds !== void 0 && !STRING_HOLDS.includes(holds)) throw parameterError(macro, param, `holds the unknown ${JSON.stringify(holds)}`, holdsFix);
|
|
7994
|
-
if (param.parameters) checkParameterTypes(macro, param.parameters);
|
|
7995
|
-
}
|
|
7996
|
-
}
|
|
7997
|
-
function parameterError(macro, param, problem, fix) {
|
|
7998
|
-
return /* @__PURE__ */ new Error(`spindle: The parameter "${param.name}" of the macro {${macro}} ${problem}. ${fix}`);
|
|
7999
|
-
}
|
|
8000
|
-
function getMacroRegistry() {
|
|
8001
|
-
return Array.from(metadataRegistry.values());
|
|
8002
|
-
}
|
|
8003
8159
|
function textContainsChildren(text2, parametersOf2) {
|
|
8004
8160
|
if (!text2.includes("{")) return false;
|
|
8005
8161
|
let nodes;
|
|
@@ -8030,6 +8186,7 @@ function astContainsChildren(nodes, parametersOf2 = registeredParameters) {
|
|
|
8030
8186
|
}, parametersOf2) || astContainsChildren(node.children, parametersOf2)) return true;
|
|
8031
8187
|
}
|
|
8032
8188
|
if (node.type === "macro") {
|
|
8189
|
+
if (node.name.toLowerCase() === "widget") continue;
|
|
8033
8190
|
if (tokenTextContainsChildren({
|
|
8034
8191
|
isClose: false,
|
|
8035
8192
|
nameStart: 0,
|
|
@@ -8048,9 +8205,25 @@ function astContainsChildren(nodes, parametersOf2 = registeredParameters) {
|
|
|
8048
8205
|
return false;
|
|
8049
8206
|
}
|
|
8050
8207
|
function widgetDef({ name = "", parameters = "" }) {
|
|
8208
|
+
const params = [];
|
|
8209
|
+
const holds = {};
|
|
8210
|
+
const badHolds = [];
|
|
8211
|
+
for (const word of parameters.split(/[\s,]+/)) {
|
|
8212
|
+
if (!word.startsWith("@")) continue;
|
|
8213
|
+
const [param = word, written2] = word.split(/:(.*)/s);
|
|
8214
|
+
params.push(param);
|
|
8215
|
+
if (written2 === void 0) continue;
|
|
8216
|
+
if (STRING_HOLDS.includes(written2)) holds[param] = written2;
|
|
8217
|
+
else badHolds.push({
|
|
8218
|
+
param,
|
|
8219
|
+
written: written2
|
|
8220
|
+
});
|
|
8221
|
+
}
|
|
8051
8222
|
return {
|
|
8052
8223
|
name,
|
|
8053
|
-
params
|
|
8224
|
+
params,
|
|
8225
|
+
...Object.keys(holds).length > 0 ? { holds } : {},
|
|
8226
|
+
...badHolds.length > 0 ? { badHolds } : {}
|
|
8054
8227
|
};
|
|
8055
8228
|
}
|
|
8056
8229
|
function parseWidgetDef(rawArgs) {
|
|
@@ -8102,8 +8275,11 @@ function widgetDefinitions$1(passages, parametersOf2 = registeredParameters) {
|
|
|
8102
8275
|
}
|
|
8103
8276
|
return found;
|
|
8104
8277
|
}
|
|
8105
|
-
function
|
|
8106
|
-
|
|
8278
|
+
function effectiveWidgetDefinitions(definitions) {
|
|
8279
|
+
const inInit = (def) => def.passage === "StoryInit";
|
|
8280
|
+
const effective = new NameMap();
|
|
8281
|
+
for (const def of [...definitions.filter((def2) => !inInit(def2)), ...definitions.filter(inInit)]) if (def.closeStart !== void 0) effective.set(def.name, def);
|
|
8282
|
+
return [...effective.values()];
|
|
8107
8283
|
}
|
|
8108
8284
|
function distance(a, b) {
|
|
8109
8285
|
let prev = Array.from({ length: b.length + 1 }, (_2, j2) => j2);
|
|
@@ -8257,20 +8433,6 @@ function validateMarkup(passages, options) {
|
|
|
8257
8433
|
for (const [passage, tokens2] of parsed) withParseCache(() => checkPassage(passage, tokens2));
|
|
8258
8434
|
return diagnostics;
|
|
8259
8435
|
}
|
|
8260
|
-
function variableNameError(name, label2 = name) {
|
|
8261
|
-
return name === "__proto__" ? `"${label2}" cannot be used as a variable name (${RESERVED_NAME} is reserved)` : void 0;
|
|
8262
|
-
}
|
|
8263
|
-
function ownEntries(sources, keep = () => true) {
|
|
8264
|
-
const record2 = /* @__PURE__ */ Object.create(null);
|
|
8265
|
-
for (const source of sources) {
|
|
8266
|
-
if (!source) continue;
|
|
8267
|
-
for (const key of Object.keys(source)) {
|
|
8268
|
-
const value = source[key];
|
|
8269
|
-
if (keep(value)) record2[key] = value;
|
|
8270
|
-
}
|
|
8271
|
-
}
|
|
8272
|
-
return record2;
|
|
8273
|
-
}
|
|
8274
8436
|
function staticLiteral(src) {
|
|
8275
8437
|
const reader = new Reader(src);
|
|
8276
8438
|
const value = reader.value();
|
|
@@ -8281,6 +8443,17 @@ function entryOrder(keys) {
|
|
|
8281
8443
|
const all = [...keys];
|
|
8282
8444
|
return [...all.filter((key) => ARRAY_INDEX_RE.test(key)).sort((a, b) => Number(a) - Number(b)), ...all.filter((key) => !ARRAY_INDEX_RE.test(key))];
|
|
8283
8445
|
}
|
|
8446
|
+
function regexLiterals(src, goal = "expression", handlers = {}) {
|
|
8447
|
+
const ends = /* @__PURE__ */ new Map();
|
|
8448
|
+
lexJs(src, {
|
|
8449
|
+
...handlers,
|
|
8450
|
+
literal(text2, index, nesting) {
|
|
8451
|
+
if (text2.charAt(0) === "/" && !/^\/[/*]/.test(text2)) ends.set(index, index + text2.length);
|
|
8452
|
+
handlers.literal?.(text2, index, nesting);
|
|
8453
|
+
}
|
|
8454
|
+
}, goal);
|
|
8455
|
+
return ends;
|
|
8456
|
+
}
|
|
8284
8457
|
function bigintValue(digits) {
|
|
8285
8458
|
try {
|
|
8286
8459
|
return BigInt(digits.replace(/_/g, "")).toString();
|
|
@@ -8406,6 +8579,7 @@ function checkReference(ref2, declared) {
|
|
|
8406
8579
|
const part = ref2.path[i2];
|
|
8407
8580
|
if (current2.type === "array") return null;
|
|
8408
8581
|
if (current2.type === "null") return null;
|
|
8582
|
+
if (current2.type === "string" && isArrayIndex(part)) continue;
|
|
8409
8583
|
const sample = PRIMITIVE_SAMPLES[current2.type];
|
|
8410
8584
|
if (sample && part in sample) {
|
|
8411
8585
|
const memberType = typeof sample[part];
|
|
@@ -8421,9 +8595,20 @@ function checkReference(ref2, declared) {
|
|
|
8421
8595
|
}
|
|
8422
8596
|
return null;
|
|
8423
8597
|
}
|
|
8424
|
-
function referenceAt(code,
|
|
8598
|
+
function referenceAt(code, sigil, name, start, end, at3) {
|
|
8599
|
+
FIELD_PATH_RE.lastIndex = end;
|
|
8600
|
+
const fields = FIELD_PATH_RE.exec(code)[0];
|
|
8601
|
+
return {
|
|
8602
|
+
sigil,
|
|
8603
|
+
name,
|
|
8604
|
+
path: fields ? fields.slice(1).split(".") : [],
|
|
8605
|
+
start: at3(start),
|
|
8606
|
+
end: at3(end + fields.length)
|
|
8607
|
+
};
|
|
8608
|
+
}
|
|
8609
|
+
function termReferenceAt(term, index, at3) {
|
|
8425
8610
|
VAR_PATH_RE.lastIndex = index;
|
|
8426
|
-
const match = VAR_PATH_RE.exec(
|
|
8611
|
+
const match = VAR_PATH_RE.exec(term);
|
|
8427
8612
|
if (!match) return void 0;
|
|
8428
8613
|
const [name, ...path] = match[2].split(".");
|
|
8429
8614
|
return {
|
|
@@ -8449,39 +8634,42 @@ function scanCode(code, at3, emit, goal = "expression") {
|
|
|
8449
8634
|
}
|
|
8450
8635
|
for (const ref2 of parsed.refs) {
|
|
8451
8636
|
if (ref2.sigil !== "$" && ref2.sigil !== "%") continue;
|
|
8452
|
-
|
|
8453
|
-
if (found) emit(found);
|
|
8637
|
+
emit(referenceAt(code, ref2.sigil, ref2.name, ref2.start, ref2.end, at3));
|
|
8454
8638
|
}
|
|
8455
8639
|
}
|
|
8456
8640
|
function scanCodeLeniently(code, at3, emit, goal) {
|
|
8457
8641
|
lexJs(code, {
|
|
8458
|
-
variable(sigil,
|
|
8642
|
+
variable(sigil, name, index, _nesting, end) {
|
|
8459
8643
|
if (sigil !== "$" && sigil !== "%") return;
|
|
8460
|
-
|
|
8461
|
-
if (found) emit(found);
|
|
8644
|
+
emit(referenceAt(code, sigil, name, index, end, at3));
|
|
8462
8645
|
},
|
|
8463
8646
|
literal() {
|
|
8464
8647
|
}
|
|
8465
8648
|
}, goal);
|
|
8466
8649
|
}
|
|
8467
|
-
function
|
|
8650
|
+
function scanPieces(pieces, at3, emit, options) {
|
|
8651
|
+
for (const piece of pieces) {
|
|
8652
|
+
const pieceAt = (i2) => at3(pieceOffset(piece, i2));
|
|
8653
|
+
if (piece.kind === "code") scanCode(piece.code, pieceAt, emit, piece.goal);
|
|
8654
|
+
else if (piece.kind === "text") scanInterpolations(piece.text, pieceAt, emit, {
|
|
8655
|
+
...options,
|
|
8656
|
+
storeVarMacros: NO_STORE_VAR_MACROS
|
|
8657
|
+
});
|
|
8658
|
+
}
|
|
8659
|
+
}
|
|
8660
|
+
function scanArgs(token, parametersOf2, at3, emit, options) {
|
|
8468
8661
|
if (!token.rawArgs) return;
|
|
8662
|
+
const params = parametersOf2(token.name);
|
|
8663
|
+
let byParameters = false;
|
|
8469
8664
|
if (params) {
|
|
8470
8665
|
if (options.all && !options.storeVarMacros.has(token.name.toLowerCase())) scanVariableParameters(token, params, at3, emit);
|
|
8471
8666
|
const pieces = [...argPieces(token.rawArgs, token.argsStart, params, token.name, "")];
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
const pieceAt = (i2) => at3(pieceOffset(piece, i2));
|
|
8475
|
-
if (piece.kind === "code") scanCode(piece.code, pieceAt, emit, piece.goal);
|
|
8476
|
-
else if (piece.kind === "text") scanInterpolations(piece.text, pieceAt, emit, {
|
|
8477
|
-
...options,
|
|
8478
|
-
storeVarMacros: NO_STORE_VAR_MACROS
|
|
8479
|
-
});
|
|
8480
|
-
}
|
|
8481
|
-
return;
|
|
8482
|
-
}
|
|
8667
|
+
byParameters = !pieces.some((piece) => piece.kind === "argument-error");
|
|
8668
|
+
if (byParameters) scanPieces(pieces, at3, emit, options);
|
|
8483
8669
|
}
|
|
8484
|
-
scanCode(token.rawArgs, (i2) => at3(token.argsStart + i2), emit);
|
|
8670
|
+
if (!byParameters) scanCode(token.rawArgs, (i2) => at3(token.argsStart + i2), emit);
|
|
8671
|
+
const widget = parametersOf2.widget?.(token.name);
|
|
8672
|
+
if (widget) scanPieces(widgetPieces(token.rawArgs, token.argsStart, widget, token.name, ""), at3, emit, options);
|
|
8485
8673
|
}
|
|
8486
8674
|
function scanVariableParameters(token, params, at3, emit) {
|
|
8487
8675
|
const spans = /* @__PURE__ */ new Map();
|
|
@@ -8494,7 +8682,7 @@ function scanVariableParameters(token, params, at3, emit) {
|
|
|
8494
8682
|
for (const param of params) {
|
|
8495
8683
|
const span = spans.get(param);
|
|
8496
8684
|
if (param.type !== "variable" || !span) continue;
|
|
8497
|
-
const ref2 =
|
|
8685
|
+
const ref2 = termReferenceAt(token.rawArgs.slice(span[0], span[1]), 0, (i2) => at3(token.argsStart + span[0] + i2));
|
|
8498
8686
|
if (ref2) emit(ref2);
|
|
8499
8687
|
}
|
|
8500
8688
|
}
|
|
@@ -8533,7 +8721,7 @@ function collectTokenRefs(content, tokens2, at3, emit, options) {
|
|
|
8533
8721
|
else scanInterpolations(value, valueIn, emit, options);
|
|
8534
8722
|
}
|
|
8535
8723
|
else if (token.type === "macro" && !token.isClose) {
|
|
8536
|
-
scanArgs(token, parametersOf2
|
|
8724
|
+
scanArgs(token, parametersOf2, at3, emit, options);
|
|
8537
8725
|
scanSelectors(content, token, at3, emit, options);
|
|
8538
8726
|
if (storeVarMacros.has(token.name.toLowerCase())) {
|
|
8539
8727
|
const lead = token.rawArgs.length - token.rawArgs.trimStart().length;
|
|
@@ -8569,7 +8757,7 @@ function collectTokenRefs(content, tokens2, at3, emit, options) {
|
|
|
8569
8757
|
function collectVariableReferences(content, options) {
|
|
8570
8758
|
const found = [];
|
|
8571
8759
|
withParseCache(() => collectTokenRefs(content, tokensOf(content, false, options), (i2) => i2, (ref2) => found.push(ref2), options));
|
|
8572
|
-
return found;
|
|
8760
|
+
return found.sort((a, b) => a.start - b.start);
|
|
8573
8761
|
}
|
|
8574
8762
|
function checkVariableReferences(passages, declared, options) {
|
|
8575
8763
|
const diagnostics = [];
|
|
@@ -8593,10 +8781,13 @@ function checkVariableReferences(passages, declared, options) {
|
|
|
8593
8781
|
}
|
|
8594
8782
|
function codeOnly(source) {
|
|
8595
8783
|
const chars = Array.from({ length: source.length }, () => " ");
|
|
8596
|
-
|
|
8784
|
+
const regexes = regexLiterals(source, "statements", { code(ch, index) {
|
|
8597
8785
|
for (let k2 = 0; k2 < ch.length; k2++) chars[index + k2] = ch[k2];
|
|
8598
|
-
} }
|
|
8599
|
-
return
|
|
8786
|
+
} });
|
|
8787
|
+
return {
|
|
8788
|
+
code: chars.join(""),
|
|
8789
|
+
regexes
|
|
8790
|
+
};
|
|
8600
8791
|
}
|
|
8601
8792
|
function written(props, key, read) {
|
|
8602
8793
|
const value = read(props.get(key));
|
|
@@ -8659,18 +8850,23 @@ function macroOf(config2) {
|
|
|
8659
8850
|
return macro;
|
|
8660
8851
|
}
|
|
8661
8852
|
function discoverMacros(source) {
|
|
8662
|
-
const code = codeOnly(source);
|
|
8853
|
+
const { code, regexes } = codeOnly(source);
|
|
8663
8854
|
const found = [];
|
|
8855
|
+
let bindings;
|
|
8664
8856
|
for (const call of code.matchAll(CALL_RE)) {
|
|
8665
8857
|
let at3 = call.index + call[0].length;
|
|
8666
8858
|
if (code.charAt(at3) !== "{") {
|
|
8667
8859
|
const variable = IDENTIFIER_ARGUMENT_RE.exec(code.slice(at3))?.[1];
|
|
8668
8860
|
if (!variable) continue;
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8861
|
+
bindings ?? (bindings = new Bindings(code));
|
|
8862
|
+
const object3 = bindings.objectOf(variable, call.index, CONFIG_KEYS);
|
|
8863
|
+
if (object3 === void 0) continue;
|
|
8864
|
+
at3 = object3;
|
|
8865
|
+
}
|
|
8866
|
+
const reader = new ConfigReader(source, {
|
|
8867
|
+
goal: "statements",
|
|
8868
|
+
regexes
|
|
8869
|
+
});
|
|
8674
8870
|
reader.i = at3;
|
|
8675
8871
|
const config2 = reader.datum();
|
|
8676
8872
|
const macro = config2 && macroOf(config2);
|
|
@@ -8678,12 +8874,561 @@ function discoverMacros(source) {
|
|
|
8678
8874
|
}
|
|
8679
8875
|
return found;
|
|
8680
8876
|
}
|
|
8877
|
+
function segmentRegions(body) {
|
|
8878
|
+
const lines = body.split("\n");
|
|
8879
|
+
if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
8880
|
+
if (lines.length === 0) return [];
|
|
8881
|
+
const regions = [];
|
|
8882
|
+
let i2 = 0;
|
|
8883
|
+
while (i2 < lines.length) {
|
|
8884
|
+
const line = lines[i2];
|
|
8885
|
+
const trimmed2 = line.trim();
|
|
8886
|
+
if (/^<script(\s|>)/i.test(trimmed2)) {
|
|
8887
|
+
const block = blockLines(lines, i2, /<\/script\s*>/i);
|
|
8888
|
+
regions.push({
|
|
8889
|
+
type: "script",
|
|
8890
|
+
lines: block
|
|
8891
|
+
});
|
|
8892
|
+
i2 += block.length;
|
|
8893
|
+
continue;
|
|
8894
|
+
}
|
|
8895
|
+
if (/^<svg(\s|>)/i.test(trimmed2)) {
|
|
8896
|
+
const block = blockLines(lines, i2, /<\/svg\s*>/i);
|
|
8897
|
+
regions.push({
|
|
8898
|
+
type: "svg",
|
|
8899
|
+
lines: block
|
|
8900
|
+
});
|
|
8901
|
+
i2 += block.length;
|
|
8902
|
+
continue;
|
|
8903
|
+
}
|
|
8904
|
+
if (/^<([a-zA-Z][\w-]*)/.test(trimmed2)) {
|
|
8905
|
+
const tagName = trimmed2.match(/^<([a-zA-Z][\w-]*)/)[1].toLowerCase();
|
|
8906
|
+
if (VOID_ELEMENTS.has(tagName) && !lines[i2 + 1]?.trim().startsWith("<")) {
|
|
8907
|
+
pushSpindleLine(regions, line);
|
|
8908
|
+
i2++;
|
|
8909
|
+
continue;
|
|
8910
|
+
}
|
|
8911
|
+
if (new RegExp(`</${tagName}\\s*>`, "i").test(trimmed2)) {
|
|
8912
|
+
pushSpindleLine(regions, line);
|
|
8913
|
+
i2++;
|
|
8914
|
+
continue;
|
|
8915
|
+
}
|
|
8916
|
+
const htmlLines = [line];
|
|
8917
|
+
let depth = 1;
|
|
8918
|
+
i2++;
|
|
8919
|
+
while (i2 < lines.length && depth > 0) {
|
|
8920
|
+
htmlLines.push(lines[i2]);
|
|
8921
|
+
const opens = (lines[i2].match(new RegExp(`<${tagName}(?:[\\s>]|$)`, "gi")) ?? []).length;
|
|
8922
|
+
const closes2 = (lines[i2].match(new RegExp(`</${tagName}\\s*>`, "gi")) ?? []).length;
|
|
8923
|
+
depth += opens - closes2;
|
|
8924
|
+
i2++;
|
|
8925
|
+
}
|
|
8926
|
+
regions.push({
|
|
8927
|
+
type: "html",
|
|
8928
|
+
lines: htmlLines
|
|
8929
|
+
});
|
|
8930
|
+
continue;
|
|
8931
|
+
}
|
|
8932
|
+
pushSpindleLine(regions, line);
|
|
8933
|
+
i2++;
|
|
8934
|
+
}
|
|
8935
|
+
return regions;
|
|
8936
|
+
}
|
|
8937
|
+
function blockLines(lines, start, close) {
|
|
8938
|
+
let end = start;
|
|
8939
|
+
while (end < lines.length - 1 && !close.test(lines[end])) end++;
|
|
8940
|
+
return lines.slice(start, end + 1);
|
|
8941
|
+
}
|
|
8942
|
+
function pushSpindleLine(regions, line) {
|
|
8943
|
+
const last2 = regions[regions.length - 1];
|
|
8944
|
+
if (last2?.type === "spindle") last2.lines.push(line);
|
|
8945
|
+
else regions.push({
|
|
8946
|
+
type: "spindle",
|
|
8947
|
+
lines: [line]
|
|
8948
|
+
});
|
|
8949
|
+
}
|
|
8950
|
+
async function run(code, prettier2, options, overrides) {
|
|
8951
|
+
if (!prettier2) return void 0;
|
|
8952
|
+
try {
|
|
8953
|
+
return await prettier2.format(code, {
|
|
8954
|
+
...options ?? DEFAULT_PRETTIER_OPTIONS,
|
|
8955
|
+
...overrides
|
|
8956
|
+
});
|
|
8957
|
+
} catch {
|
|
8958
|
+
return;
|
|
8959
|
+
}
|
|
8960
|
+
}
|
|
8961
|
+
function formatJS(code, prettier2, options) {
|
|
8962
|
+
return run(code, prettier2, options, { parser: "babel" });
|
|
8963
|
+
}
|
|
8964
|
+
function formatCSS(code, prettier2, options) {
|
|
8965
|
+
return run(code, prettier2, options, { parser: "css" });
|
|
8966
|
+
}
|
|
8967
|
+
function formatHTML(code, prettier2, options) {
|
|
8968
|
+
return run(code, prettier2, options, {
|
|
8969
|
+
parser: "html",
|
|
8970
|
+
htmlWhitespaceSensitivity: "css"
|
|
8971
|
+
});
|
|
8972
|
+
}
|
|
8973
|
+
function scanSpindleMarkup(text2) {
|
|
8974
|
+
const tokens2 = [];
|
|
8975
|
+
const tags = [];
|
|
8976
|
+
const doBlocks = [];
|
|
8977
|
+
let open;
|
|
8978
|
+
const push = (t, inAttribute) => {
|
|
8979
|
+
const match = {
|
|
8980
|
+
start: t.start,
|
|
8981
|
+
end: t.end,
|
|
8982
|
+
token: text2.slice(t.start, t.end)
|
|
8983
|
+
};
|
|
8984
|
+
if (inAttribute) match.inAttribute = true;
|
|
8985
|
+
tokens2.push(match);
|
|
8986
|
+
};
|
|
8987
|
+
for (const t of tokenizeMarkupTolerant(text2).tokens) if (t.type === "html") {
|
|
8988
|
+
tags.push({
|
|
8989
|
+
start: t.start,
|
|
8990
|
+
end: t.end
|
|
8991
|
+
});
|
|
8992
|
+
for (const attribute of t.attributeSpans) {
|
|
8993
|
+
if (attribute.valueStart === void 0 || attribute.valueEnd === void 0) continue;
|
|
8994
|
+
const value = text2.slice(attribute.valueStart, attribute.valueEnd);
|
|
8995
|
+
if (!value.includes("{")) continue;
|
|
8996
|
+
for (const inner of tokenizeMarkupTolerant(value, { text: true }).tokens) if (inner.type === "macro" || inner.type === "variable" || inner.type === "expression") push({
|
|
8997
|
+
start: attribute.valueStart + inner.start,
|
|
8998
|
+
end: attribute.valueStart + inner.end
|
|
8999
|
+
}, true);
|
|
9000
|
+
}
|
|
9001
|
+
} else if (t.type !== "text") {
|
|
9002
|
+
if (t.type === "macro" && t.name === "do") {
|
|
9003
|
+
if (!t.isClose) open = t;
|
|
9004
|
+
else if (open) {
|
|
9005
|
+
doBlocks.push({
|
|
9006
|
+
start: open.start,
|
|
9007
|
+
end: t.end,
|
|
9008
|
+
bodyStart: open.end,
|
|
9009
|
+
bodyEnd: t.start
|
|
9010
|
+
});
|
|
9011
|
+
open = void 0;
|
|
9012
|
+
}
|
|
9013
|
+
}
|
|
9014
|
+
push(t);
|
|
9015
|
+
}
|
|
9016
|
+
return {
|
|
9017
|
+
tokens: tokens2,
|
|
9018
|
+
tags,
|
|
9019
|
+
doBlocks
|
|
9020
|
+
};
|
|
9021
|
+
}
|
|
9022
|
+
function multilineJsLiterals(code) {
|
|
9023
|
+
const spans = [];
|
|
9024
|
+
let skipUntil = 0;
|
|
9025
|
+
lexJs(code, { literal(text2, index, nesting) {
|
|
9026
|
+
if (nesting > 0 || index < skipUntil) return;
|
|
9027
|
+
const quote = text2[0];
|
|
9028
|
+
if (quote === "`") {
|
|
9029
|
+
skipUntil = lexTemplate(code, index);
|
|
9030
|
+
if (code.slice(index, skipUntil).includes("\n")) spans.push([index, skipUntil]);
|
|
9031
|
+
} else if ((quote === '"' || quote === "'") && text2.includes("\n")) spans.push([index, index + text2.length]);
|
|
9032
|
+
} }, "statements");
|
|
9033
|
+
return spans;
|
|
9034
|
+
}
|
|
9035
|
+
function lineHasTag(tags, start, end) {
|
|
9036
|
+
return tags.some((tag) => tag.start < end && tag.end > start);
|
|
9037
|
+
}
|
|
9038
|
+
function replaceSvgBlocks(html) {
|
|
9039
|
+
const tokens2 = [];
|
|
9040
|
+
return {
|
|
9041
|
+
text: html.replace(/<svg[\s>][\s\S]*?<\/svg>/gi, (match) => {
|
|
9042
|
+
const idx = tokens2.length;
|
|
9043
|
+
tokens2.push(match);
|
|
9044
|
+
return `<!--SVG:${idx}-->`;
|
|
9045
|
+
}),
|
|
9046
|
+
tokens: tokens2
|
|
9047
|
+
};
|
|
9048
|
+
}
|
|
9049
|
+
function placeholdersIntact(text2, tokens2, placeholdersOf) {
|
|
9050
|
+
return tokens2.every((_2, index) => placeholdersOf(index).reduce((count, placeholder) => count + text2.split(placeholder).length - 1, 0) === 1);
|
|
9051
|
+
}
|
|
9052
|
+
function sameSpindleTokens(before, after) {
|
|
9053
|
+
const tokensOf2 = (text2) => scanSpindleMarkup(text2).tokens.map((m) => m.token);
|
|
9054
|
+
const expected = tokensOf2(before);
|
|
9055
|
+
const found = tokensOf2(after);
|
|
9056
|
+
return expected.length === found.length && expected.every((t, i2) => t === found[i2]);
|
|
9057
|
+
}
|
|
9058
|
+
function restorePlaceholders(text2, tokens2, placeholdersOf) {
|
|
9059
|
+
let result = text2;
|
|
9060
|
+
tokens2.forEach((token, index) => {
|
|
9061
|
+
for (const placeholder of placeholdersOf(index)) result = result.replace(placeholder, () => token);
|
|
9062
|
+
});
|
|
9063
|
+
return result;
|
|
9064
|
+
}
|
|
9065
|
+
function restoreSvgBlocks(text2, tokens2) {
|
|
9066
|
+
return restorePlaceholders(text2, tokens2, SVG_PLACEHOLDERS);
|
|
9067
|
+
}
|
|
9068
|
+
function replaceSpindleTokens(html) {
|
|
9069
|
+
const { tokens: found, tags, doBlocks } = scanSpindleMarkup(html);
|
|
9070
|
+
const units = [];
|
|
9071
|
+
const pushDoBlock = (block) => units.push({
|
|
9072
|
+
start: block.start,
|
|
9073
|
+
end: block.end,
|
|
9074
|
+
token: html.slice(block.start, block.end)
|
|
9075
|
+
});
|
|
9076
|
+
let doIndex = 0;
|
|
9077
|
+
for (const m of found) {
|
|
9078
|
+
for (let block = doBlocks[doIndex]; block && block.end <= m.start; ) {
|
|
9079
|
+
pushDoBlock(block);
|
|
9080
|
+
block = doBlocks[++doIndex];
|
|
9081
|
+
}
|
|
9082
|
+
const open = doBlocks[doIndex];
|
|
9083
|
+
if (open && m.start >= open.start) continue;
|
|
9084
|
+
units.push(m);
|
|
9085
|
+
}
|
|
9086
|
+
for (; doIndex < doBlocks.length; doIndex++) pushDoBlock(doBlocks[doIndex]);
|
|
9087
|
+
units.sort((a, b) => a.start - b.start);
|
|
9088
|
+
const tokens2 = [];
|
|
9089
|
+
const resultLines = [];
|
|
9090
|
+
let unit = 0;
|
|
9091
|
+
let lineStart = 0;
|
|
9092
|
+
while (lineStart <= html.length) {
|
|
9093
|
+
let lineEnd = lineStart;
|
|
9094
|
+
const lineUnits = [];
|
|
9095
|
+
for (; ; ) {
|
|
9096
|
+
while (unit < units.length && units[unit].end <= lineEnd) unit++;
|
|
9097
|
+
const next = units[unit];
|
|
9098
|
+
const inside = next && next.start <= lineEnd ? next : void 0;
|
|
9099
|
+
if (inside) {
|
|
9100
|
+
lineUnits.push(inside);
|
|
9101
|
+
lineEnd = inside.end;
|
|
9102
|
+
unit++;
|
|
9103
|
+
continue;
|
|
9104
|
+
}
|
|
9105
|
+
if (lineEnd >= html.length || html[lineEnd] === "\n") break;
|
|
9106
|
+
lineEnd++;
|
|
9107
|
+
}
|
|
9108
|
+
const line = html.slice(lineStart, lineEnd);
|
|
9109
|
+
const indent = line.match(/^(\s*)/)?.[1] ?? "";
|
|
9110
|
+
if (lineUnits.length === 0) resultLines.push(line);
|
|
9111
|
+
else if (!lineHasTag(tags, lineStart, lineEnd)) {
|
|
9112
|
+
const idx = tokens2.length;
|
|
9113
|
+
tokens2.push(line.trim());
|
|
9114
|
+
resultLines.push(`${indent}<!--SP:${idx}-->`);
|
|
9115
|
+
} else {
|
|
9116
|
+
let replaced = "";
|
|
9117
|
+
let last2 = lineStart;
|
|
9118
|
+
for (const u of lineUnits) {
|
|
9119
|
+
const idx = tokens2.length;
|
|
9120
|
+
tokens2.push(u.token);
|
|
9121
|
+
replaced += html.slice(last2, u.start) + (u.inAttribute ? `__SP${idx}__` : `<!--SP:${idx}-->`);
|
|
9122
|
+
last2 = u.end;
|
|
9123
|
+
}
|
|
9124
|
+
resultLines.push(replaced + html.slice(last2, lineEnd));
|
|
9125
|
+
}
|
|
9126
|
+
lineStart = lineEnd + 1;
|
|
9127
|
+
}
|
|
9128
|
+
return {
|
|
9129
|
+
text: resultLines.join("\n"),
|
|
9130
|
+
tokens: tokens2
|
|
9131
|
+
};
|
|
9132
|
+
}
|
|
9133
|
+
function restoreSpindleTokens(text2, tokens2) {
|
|
9134
|
+
return restorePlaceholders(text2, tokens2, SPINDLE_PLACEHOLDERS);
|
|
9135
|
+
}
|
|
9136
|
+
function closedMacroNames(text2) {
|
|
9137
|
+
const found = /* @__PURE__ */ new Set();
|
|
9138
|
+
for (const t of tokenizeMarkupTolerant(text2).tokens) if (t.type === "macro" && t.isClose) found.add(t.name.toLowerCase());
|
|
9139
|
+
return found;
|
|
9140
|
+
}
|
|
9141
|
+
function defaultIsBlock(text2, extra = []) {
|
|
9142
|
+
const closed = closedMacroNames(text2);
|
|
9143
|
+
for (const name of extra) closed.add(name.toLowerCase());
|
|
9144
|
+
return (name) => isBlockMacro(name) || closed.has(name.toLowerCase());
|
|
9145
|
+
}
|
|
9146
|
+
async function formatPassage(body, options = {}) {
|
|
9147
|
+
if (body.charCodeAt(0) === 65279) return "\uFEFF" + await formatPassage(body.slice(1), options);
|
|
9148
|
+
const eol = dominantEol(body);
|
|
9149
|
+
const output = await formatLf(body.replace(/\r\n/g, "\n"), options);
|
|
9150
|
+
return eol === "\r\n" ? output.replace(/\n/g, "\r\n") : output;
|
|
9151
|
+
}
|
|
9152
|
+
function dominantEol(text2) {
|
|
9153
|
+
const crlf = (text2.match(/\r\n/g) ?? []).length;
|
|
9154
|
+
const lf = (text2.match(/\n/g) ?? []).length - crlf;
|
|
9155
|
+
if (crlf !== lf) return crlf > lf ? "\r\n" : "\n";
|
|
9156
|
+
return text2.indexOf("\r\n") !== -1 && text2.indexOf("\r\n") < text2.indexOf("\n") ? "\r\n" : "\n";
|
|
9157
|
+
}
|
|
9158
|
+
function replaceAll(text2, from, to) {
|
|
9159
|
+
return text2.split(from).join(to);
|
|
9160
|
+
}
|
|
9161
|
+
function newlineSentinel(text2) {
|
|
9162
|
+
for (let code = 57344; code <= 63743; code++) {
|
|
9163
|
+
const ch = String.fromCharCode(code);
|
|
9164
|
+
if (!text2.includes(ch)) return ch;
|
|
9165
|
+
}
|
|
9166
|
+
throw new Error("no free private-use character for the newline stand-in");
|
|
9167
|
+
}
|
|
9168
|
+
function protectMultilineTokens(body, sentinel) {
|
|
9169
|
+
const { tokens: tokens2, doBlocks } = scanSpindleMarkup(body);
|
|
9170
|
+
const spans = [];
|
|
9171
|
+
for (const m of tokens2) if (m.token.includes("\n")) spans.push([m.start, m.end]);
|
|
9172
|
+
for (const block of doBlocks) for (const [a, b] of multilineJsLiterals(body.slice(block.bodyStart, block.bodyEnd))) spans.push([block.bodyStart + a, block.bodyStart + b]);
|
|
9173
|
+
return joinSpans(body, spans, sentinel);
|
|
9174
|
+
}
|
|
9175
|
+
function joinJsLiterals(code, sentinel) {
|
|
9176
|
+
return joinSpans(code, multilineJsLiterals(code), sentinel);
|
|
9177
|
+
}
|
|
9178
|
+
function joinSpans(text2, spans, sentinel) {
|
|
9179
|
+
let out = "";
|
|
9180
|
+
let last2 = 0;
|
|
9181
|
+
for (const [a, b] of [...spans].sort((x2, y) => x2[0] - y[0])) {
|
|
9182
|
+
out += text2.slice(last2, a) + replaceAll(text2.slice(a, b), "\n", sentinel);
|
|
9183
|
+
last2 = b;
|
|
9184
|
+
}
|
|
9185
|
+
return out + text2.slice(last2);
|
|
9186
|
+
}
|
|
9187
|
+
async function formatLf(text2, options) {
|
|
9188
|
+
const { prettier: prettier2, prettierOptions } = options;
|
|
9189
|
+
const body = text2.replace(/(?:[ \t]*\n)+[ \t]*$/, "\n");
|
|
9190
|
+
if (options.kind === "script" || options.kind === "stylesheet") {
|
|
9191
|
+
const format = options.kind === "script" ? formatJS : formatCSS;
|
|
9192
|
+
const code = body.trim();
|
|
9193
|
+
return (await format(code, prettier2, prettierOptions) ?? code).trim().replace(/\n*$/, "\n");
|
|
9194
|
+
}
|
|
9195
|
+
const isBlock = options.isBlock ?? defaultIsBlock(body, options.blockMacros);
|
|
9196
|
+
const isDedenting = options.isDedentingSubMacro ?? ((name) => DEFAULT_DEDENTING.has(name.toLowerCase()));
|
|
9197
|
+
const sentinel = newlineSentinel(body);
|
|
9198
|
+
const lines = [];
|
|
9199
|
+
const hardBreakLines = /* @__PURE__ */ new Set();
|
|
9200
|
+
const regions = segmentRegions(protectMultilineTokens(body, sentinel));
|
|
9201
|
+
for (const region of regions) {
|
|
9202
|
+
if (region.type !== "spindle") region.lines = region.lines.map((l) => replaceAll(l, sentinel, "\n"));
|
|
9203
|
+
if (region.type === "script") {
|
|
9204
|
+
if (region.lines.length === 1) {
|
|
9205
|
+
lines.push(...region.lines);
|
|
9206
|
+
continue;
|
|
9207
|
+
}
|
|
9208
|
+
const innerCode = region.lines.slice(1, -1).join("\n");
|
|
9209
|
+
const formatted = await formatJS(innerCode.trim(), prettier2, prettierOptions);
|
|
9210
|
+
if (formatted === void 0 || !sameSpindleTokens(innerCode, formatted)) {
|
|
9211
|
+
lines.push(...region.lines);
|
|
9212
|
+
continue;
|
|
9213
|
+
}
|
|
9214
|
+
lines.push(region.lines[0]);
|
|
9215
|
+
if (formatted.trim()) for (const fLine of joinJsLiterals(formatted.trim(), sentinel).split("\n")) lines.push(" " + fLine);
|
|
9216
|
+
lines.push(region.lines[region.lines.length - 1]);
|
|
9217
|
+
continue;
|
|
9218
|
+
}
|
|
9219
|
+
if (region.type === "svg") {
|
|
9220
|
+
lines.push(...region.lines);
|
|
9221
|
+
continue;
|
|
9222
|
+
}
|
|
9223
|
+
if (region.type === "html") {
|
|
9224
|
+
const htmlText = region.lines.join("\n");
|
|
9225
|
+
if (WHITESPACE_AS_WRITTEN.test(htmlText)) {
|
|
9226
|
+
lines.push(...region.lines);
|
|
9227
|
+
continue;
|
|
9228
|
+
}
|
|
9229
|
+
const { text: svgPlaceholdered, tokens: svgTokens } = replaceSvgBlocks(htmlText);
|
|
9230
|
+
const { text: placeholdered, tokens: tokens2 } = replaceSpindleTokens(svgPlaceholdered);
|
|
9231
|
+
const formatted = await formatHTML(placeholdered, prettier2, prettierOptions);
|
|
9232
|
+
if (formatted === void 0 || !placeholdersIntact(formatted, tokens2, SPINDLE_PLACEHOLDERS) || !placeholdersIntact(formatted, svgTokens, SVG_PLACEHOLDERS)) {
|
|
9233
|
+
lines.push(...region.lines);
|
|
9234
|
+
continue;
|
|
9235
|
+
}
|
|
9236
|
+
const restored = restoreSvgBlocks(restoreSpindleTokens(formatted.trim(), tokens2.map((t) => replaceAll(t, "\n", sentinel))), svgTokens);
|
|
9237
|
+
for (const fLine of restored.split("\n")) lines.push(fLine);
|
|
9238
|
+
continue;
|
|
9239
|
+
}
|
|
9240
|
+
let indented = indentMacros(region.lines, isBlock, isDedenting);
|
|
9241
|
+
if (options.maxLineLength) indented = wrapLines(indented, options.maxLineLength);
|
|
9242
|
+
for (const line of indented) {
|
|
9243
|
+
if (line.endsWith(" ")) hardBreakLines.add(lines.length);
|
|
9244
|
+
lines.push(line);
|
|
9245
|
+
}
|
|
9246
|
+
}
|
|
9247
|
+
let output = lines.map((l, i2) => hardBreakLines.has(i2) ? l : l.replace(/\s+$/, "")).join("\n");
|
|
9248
|
+
output = output.replace(/\n*$/, "\n");
|
|
9249
|
+
return replaceAll(output, sentinel, "\n");
|
|
9250
|
+
}
|
|
9251
|
+
function indentMacros(lines, isBlock, isDedenting) {
|
|
9252
|
+
const macrosOnLine = macroTokensByLine(lines);
|
|
9253
|
+
const bodies = [{
|
|
9254
|
+
openLine: -1,
|
|
9255
|
+
minCol: Infinity,
|
|
9256
|
+
keepRelative: false
|
|
9257
|
+
}];
|
|
9258
|
+
const stack = [0];
|
|
9259
|
+
const info = [];
|
|
9260
|
+
const openBody = (line) => {
|
|
9261
|
+
bodies.push({
|
|
9262
|
+
openLine: line,
|
|
9263
|
+
minCol: Infinity,
|
|
9264
|
+
keepRelative: false
|
|
9265
|
+
});
|
|
9266
|
+
stack.push(bodies.length - 1);
|
|
9267
|
+
};
|
|
9268
|
+
const currentBody = () => stack[stack.length - 1];
|
|
9269
|
+
const closeBody = () => stack.length > 1 ? stack.pop() : void 0;
|
|
9270
|
+
const addLine = (col, text2) => {
|
|
9271
|
+
const body = bodies[currentBody()];
|
|
9272
|
+
body.minCol = Math.min(body.minCol, col);
|
|
9273
|
+
if (LIST_ITEM_REGEX.test(text2) || CODE_FENCE_REGEX.test(text2)) body.keepRelative = true;
|
|
9274
|
+
info.push({
|
|
9275
|
+
body: currentBody(),
|
|
9276
|
+
col,
|
|
9277
|
+
text: text2
|
|
9278
|
+
});
|
|
9279
|
+
};
|
|
9280
|
+
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
9281
|
+
const lineText = lines[i2];
|
|
9282
|
+
const trimmed2 = lineText.trim();
|
|
9283
|
+
if (trimmed2 === "") {
|
|
9284
|
+
info.push(null);
|
|
9285
|
+
continue;
|
|
9286
|
+
}
|
|
9287
|
+
const col = indentColumn(lineText);
|
|
9288
|
+
const lead = lineText.length - lineText.trimStart().length;
|
|
9289
|
+
const macros = macrosOnLine[i2];
|
|
9290
|
+
const [first, ...rest] = macros;
|
|
9291
|
+
const startsWithMacro = first !== void 0 && first.start === lead;
|
|
9292
|
+
if (startsWithMacro && !first.isClose && isDedenting(first.name)) {
|
|
9293
|
+
const closed2 = closeBody();
|
|
9294
|
+
if (closed2 === void 0) addLine(col, trimmed2);
|
|
9295
|
+
else info.push({
|
|
9296
|
+
body: currentBody(),
|
|
9297
|
+
closes: closed2,
|
|
9298
|
+
col,
|
|
9299
|
+
text: trimmed2
|
|
9300
|
+
});
|
|
9301
|
+
openBody(i2);
|
|
9302
|
+
continue;
|
|
9303
|
+
}
|
|
9304
|
+
const closed = startsWithMacro && first.isClose ? closeBody() : void 0;
|
|
9305
|
+
if (closed === void 0) addLine(col, trimmed2);
|
|
9306
|
+
else info.push({
|
|
9307
|
+
body: currentBody(),
|
|
9308
|
+
closes: closed,
|
|
9309
|
+
col,
|
|
9310
|
+
text: trimmed2
|
|
9311
|
+
});
|
|
9312
|
+
if (startsWithMacro && !first.isClose && isBlock(first.name)) openBody(i2);
|
|
9313
|
+
for (const macro of startsWithMacro ? rest : macros) if (macro.isClose && macro.start > lead) closeBody();
|
|
9314
|
+
}
|
|
9315
|
+
const outCol = [];
|
|
9316
|
+
const result = [];
|
|
9317
|
+
for (let i2 = 0; i2 < info.length; i2++) {
|
|
9318
|
+
const line = info[i2];
|
|
9319
|
+
if (!line) {
|
|
9320
|
+
outCol.push(0);
|
|
9321
|
+
result.push("");
|
|
9322
|
+
continue;
|
|
9323
|
+
}
|
|
9324
|
+
let col;
|
|
9325
|
+
if (line.closes !== void 0) col = outCol[bodies[line.closes].openLine];
|
|
9326
|
+
else {
|
|
9327
|
+
const body = bodies[line.body];
|
|
9328
|
+
const isRoot = body.openLine === -1;
|
|
9329
|
+
col = (isRoot ? 0 : outCol[body.openLine] + 2) + (body.keepRelative ? line.col - (isRoot ? 0 : body.minCol) : 0);
|
|
9330
|
+
}
|
|
9331
|
+
outCol.push(col);
|
|
9332
|
+
const hardBreak = / {2,}$/.test(lines[i2]) && info[i2 + 1] ? " " : "";
|
|
9333
|
+
result.push(" ".repeat(col) + line.text + hardBreak);
|
|
9334
|
+
}
|
|
9335
|
+
return result;
|
|
9336
|
+
}
|
|
9337
|
+
function macroTokensByLine(lines) {
|
|
9338
|
+
const byLine = lines.map(() => []);
|
|
9339
|
+
const starts = [];
|
|
9340
|
+
let offset2 = 0;
|
|
9341
|
+
for (const line2 of lines) {
|
|
9342
|
+
starts.push(offset2);
|
|
9343
|
+
offset2 += line2.length + 1;
|
|
9344
|
+
}
|
|
9345
|
+
let line = 0;
|
|
9346
|
+
for (const token of tokenizeMarkupTolerant(lines.join("\n")).tokens) {
|
|
9347
|
+
if (token.type !== "macro") continue;
|
|
9348
|
+
while (line + 1 < lines.length && starts[line + 1] <= token.start) line++;
|
|
9349
|
+
const lineStart = starts[line];
|
|
9350
|
+
byLine[line].push({
|
|
9351
|
+
...token,
|
|
9352
|
+
start: token.start - lineStart,
|
|
9353
|
+
end: token.end - lineStart
|
|
9354
|
+
});
|
|
9355
|
+
}
|
|
9356
|
+
return byLine;
|
|
9357
|
+
}
|
|
9358
|
+
function indentColumn(line) {
|
|
9359
|
+
let col = 0;
|
|
9360
|
+
for (const ch of line) if (ch === " ") col++;
|
|
9361
|
+
else if (ch === " ") col += 4 - col % 4;
|
|
9362
|
+
else break;
|
|
9363
|
+
return col;
|
|
9364
|
+
}
|
|
9365
|
+
function wrapLines(lines, maxLen) {
|
|
9366
|
+
const result = [];
|
|
9367
|
+
const javaScript = doBodyLines(lines);
|
|
9368
|
+
for (const [index, line] of lines.entries()) {
|
|
9369
|
+
if (line.length <= maxLen || javaScript.has(index)) {
|
|
9370
|
+
result.push(line);
|
|
9371
|
+
continue;
|
|
9372
|
+
}
|
|
9373
|
+
const trimmed2 = line.trim();
|
|
9374
|
+
if (trimmed2 === "" || /^\{[\/#.]/.test(trimmed2) || /^\[\[/.test(trimmed2) || /^\{choice\b/.test(trimmed2) || /^\{choices\b/.test(trimmed2)) {
|
|
9375
|
+
result.push(line);
|
|
9376
|
+
continue;
|
|
9377
|
+
}
|
|
9378
|
+
const wrapped = wordWrap(trimmed2, maxLen, line.match(/^(\s*)/)?.[1] ?? "");
|
|
9379
|
+
if (line.endsWith(" ")) wrapped[wrapped.length - 1] += " ";
|
|
9380
|
+
result.push(...wrapped);
|
|
9381
|
+
}
|
|
9382
|
+
return result;
|
|
9383
|
+
}
|
|
9384
|
+
function doBodyLines(lines) {
|
|
9385
|
+
const found = /* @__PURE__ */ new Set();
|
|
9386
|
+
const text2 = lines.join("\n");
|
|
9387
|
+
for (const block of scanSpindleMarkup(text2).doBlocks) {
|
|
9388
|
+
const first = text2.slice(0, block.bodyStart).split("\n").length - 1;
|
|
9389
|
+
const last2 = text2.slice(0, block.bodyEnd).split("\n").length - 1;
|
|
9390
|
+
for (let i2 = first; i2 <= last2; i2++) found.add(i2);
|
|
9391
|
+
}
|
|
9392
|
+
return found;
|
|
9393
|
+
}
|
|
9394
|
+
function wordWrap(text2, maxLen, indent) {
|
|
9395
|
+
const lines = [];
|
|
9396
|
+
const inToken = new Array(text2.length).fill(false);
|
|
9397
|
+
for (const token of tokenizeMarkupTolerant(text2).tokens) {
|
|
9398
|
+
if (token.type === "text" || token.type === "html") continue;
|
|
9399
|
+
inToken.fill(true, token.start, token.end);
|
|
9400
|
+
}
|
|
9401
|
+
const room = maxLen - indent.length;
|
|
9402
|
+
let pos = 0;
|
|
9403
|
+
while (pos < text2.length) {
|
|
9404
|
+
if (text2.length - pos <= room) {
|
|
9405
|
+
lines.push(indent + text2.slice(pos));
|
|
9406
|
+
break;
|
|
9407
|
+
}
|
|
9408
|
+
let breakIdx = -1;
|
|
9409
|
+
for (let i2 = pos + 1; i2 < text2.length && i2 - pos <= room; i2++) if (text2[i2] === " " && !inToken[i2]) breakIdx = i2;
|
|
9410
|
+
if (breakIdx === -1) {
|
|
9411
|
+
for (let i2 = pos + room + 1; i2 < text2.length; i2++) if (text2[i2] === " " && !inToken[i2]) {
|
|
9412
|
+
breakIdx = i2;
|
|
9413
|
+
break;
|
|
9414
|
+
}
|
|
9415
|
+
}
|
|
9416
|
+
if (breakIdx === -1) {
|
|
9417
|
+
lines.push(indent + text2.slice(pos));
|
|
9418
|
+
break;
|
|
9419
|
+
}
|
|
9420
|
+
lines.push(indent + text2.slice(pos, breakIdx));
|
|
9421
|
+
pos = breakIdx + 1;
|
|
9422
|
+
}
|
|
9423
|
+
return lines;
|
|
9424
|
+
}
|
|
8681
9425
|
function validateStoryMarkup(passages, macros, options = {}) {
|
|
8682
9426
|
const list3 = [...passages];
|
|
8683
9427
|
const all = [...macros];
|
|
8684
9428
|
const known = /* @__PURE__ */ new Set();
|
|
8685
|
-
const
|
|
8686
|
-
const blocks = new Set(
|
|
9429
|
+
const widgets = widgetDefinitions$1(list3, parameterLookup(all));
|
|
9430
|
+
const blocks = new Set(effectiveWidgetDefinitions(widgets).filter((def) => def.block).map((def) => def.name.toLowerCase()));
|
|
9431
|
+
const parametersOf2 = parameterLookup([...all, ...definedWidgetMacros(widgets)]);
|
|
8687
9432
|
for (const macro of all) {
|
|
8688
9433
|
const name = macro.name.toLowerCase();
|
|
8689
9434
|
known.add(name);
|
|
@@ -8699,24 +9444,33 @@ function validateStoryMarkup(passages, macros, options = {}) {
|
|
|
8699
9444
|
tolerant: options.tolerant
|
|
8700
9445
|
});
|
|
8701
9446
|
}
|
|
9447
|
+
function definedWidgetMacros(widgets) {
|
|
9448
|
+
return widgets.map((widget) => ({
|
|
9449
|
+
name: widget.name,
|
|
9450
|
+
widget
|
|
9451
|
+
}));
|
|
9452
|
+
}
|
|
8702
9453
|
function blockLookup(macros) {
|
|
8703
9454
|
const blocks = new Set(macros.filter((m) => m.block).map((m) => m.name.toLowerCase()));
|
|
8704
9455
|
return (name) => blocks.has(name.toLowerCase()) || isBlockMacro(name);
|
|
8705
9456
|
}
|
|
8706
9457
|
function passagePieces(source, macros = []) {
|
|
9458
|
+
return passagePiecesOfTokens(source, macros, tokenizeMarkupTolerant(source).tokens);
|
|
9459
|
+
}
|
|
9460
|
+
function passagePiecesOfTokens(source, macros, tokens2) {
|
|
8707
9461
|
const all = [...macros];
|
|
8708
|
-
const { tokens: tokens2 } = tokenizeMarkupTolerant(source);
|
|
8709
9462
|
return [...passagePiecesOf(source, tokens2, parameterLookup(all), { isBlock: blockLookup(all) })];
|
|
8710
9463
|
}
|
|
8711
9464
|
function widgetDefinitions(passages, macros = []) {
|
|
8712
9465
|
return widgetDefinitions$1(passages, parameterLookup([...macros]));
|
|
8713
9466
|
}
|
|
8714
|
-
function referenceOptions(macros, all = false) {
|
|
9467
|
+
function referenceOptions(macros, all = false, passages = []) {
|
|
8715
9468
|
const list3 = [...macros];
|
|
9469
|
+
const widgets = widgetDefinitions$1(passages, parameterLookup(list3));
|
|
8716
9470
|
return {
|
|
8717
9471
|
all,
|
|
8718
9472
|
storeVarMacros: new Set(list3.filter((m) => m.storeVar).map((m) => m.name.toLowerCase())),
|
|
8719
|
-
parametersOf: parameterLookup(list3),
|
|
9473
|
+
parametersOf: parameterLookup([...list3, ...definedWidgetMacros(widgets)]),
|
|
8720
9474
|
tolerant: true
|
|
8721
9475
|
};
|
|
8722
9476
|
}
|
|
@@ -8724,9 +9478,10 @@ function variableReferences(source, macros = [], options = {}) {
|
|
|
8724
9478
|
return collectVariableReferences(source, referenceOptions(macros, options.all));
|
|
8725
9479
|
}
|
|
8726
9480
|
function validateVariableReferences(passages, declarations, macros = []) {
|
|
8727
|
-
|
|
9481
|
+
const list3 = [...passages];
|
|
9482
|
+
return checkVariableReferences(list3.filter((p) => !p.tags?.some((t) => NOT_MARKUP_TAGS.includes(t))), declarations, referenceOptions(macros, false, list3));
|
|
8728
9483
|
}
|
|
8729
|
-
var SIGIL_SCOPES, SIGIL_CHARS, grammar_shared_default, LB, RB, SIGIL_SCOPES$1, withSelectors, VOID_TAGS, BRANCH_PARENT$1, LINK_SEPARATORS, NO_SELECTORS, EMAIL_AUTOLINK, peg$SyntaxError, NameMap, NameSet, BLOCK_MACROS, RAW_BODY_MACROS, BRANCHING, quoteArg, last$1, BRANCH_PARENT, isBranchTag, lowerName, nameOf, closerOf, closes, astralIdentifierCodes, astralIdentifierStartCodes, nonASCIIidentifierChars, nonASCIIidentifierStartChars, reservedWords, ecma5AndLessKeywords, keywords$1, keywordRelationalOperator, nonASCIIidentifierStart, nonASCIIidentifier, TokenType, beforeExpr, startsExpr, keywords, types$1, lineBreak, lineBreakG, nonASCIIwhitespace, skipWhiteSpace, ref, hasOwnProperty, toString, hasOwn, isArray, regexpCache, loneSurrogate, Position, SourceLocation, defaultOptions, warnedAboutEcmaVersion, SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_ARROW, SCOPE_SIMPLE_CATCH, SCOPE_SUPER, SCOPE_DIRECT_SUPER, SCOPE_CLASS_STATIC_BLOCK, SCOPE_CLASS_FIELD_INIT, SCOPE_SWITCH, SCOPE_VAR, BIND_NONE, BIND_VAR, BIND_LEXICAL, BIND_FUNCTION, BIND_SIMPLE_CATCH, BIND_OUTSIDE, Parser, prototypeAccessors, pp$9, literal, DestructuringErrors, pp$8, loopLabel, switchLabel, empty$1, FUNC_STATEMENT, FUNC_HANGING_STATEMENT, FUNC_NULLABLE_ID, pp$7, TokContext, types, pp$6, pp$5, empty, pp$4, pp$3, Scope, Node, pp$2, scriptValuesAddedInUnicode, ecma9BinaryProperties, ecma10BinaryProperties, ecma11BinaryProperties, ecma12BinaryProperties, ecma13BinaryProperties, unicodeBinaryProperties, unicodeBinaryPropertiesOfStrings, unicodeGeneralCategoryValues, ecma9ScriptValues, ecma10ScriptValues, ecma11ScriptValues, ecma12ScriptValues, ecma13ScriptValues, unicodeScriptValues, data, ecmaVersion, i, list, pp$1, BranchID, RegExpValidationState, CharSetNone, CharSetOk, CharSetString, Token, pp, INVALID_TEMPLATE_ESCAPE_ERROR, OPTIONS, AT_NAME_RE, TRANS_NAME_RE, SIGIL_IDENT_RE, LINE_BREAK_RE, NOT_A_BODY_RE, OPERAND_ENDS, SigilParser, OPENERS, CLOSERS, CodeSyntaxError, last, CLOSER, isNode, NAMESPACE_NAME, WORD_RE$2, FLAGS_RE, WORDS_BEFORE_STRING, NON_STRING_QUOTE_PREFIX, memoInput, memo, defaultCodeEnd, defaultHooks, MarkupError, OFFSET_FIELD, listeners, TRAILING_OPERATOR_RE, slice, MacroArgumentError, WORD_RE$1, NUMBER_RE$1, WORD_OR_PUNCT_RE, LEADING_OPERATOR_RE, takesRest, SUB_MACRO_PARAMETERS, parses, CONDITION_MACROS, PASSAGE_BODIES, holdsByDefault,
|
|
9484
|
+
var SIGIL_SCOPES, SIGIL_CHARS, grammar_shared_default, LB, RB, SIGIL_SCOPES$1, withSelectors, VOID_TAGS, BRANCH_PARENT$1, LINK_SEPARATORS, NO_SELECTORS, EMAIL_AUTOLINK, peg$SyntaxError, NameMap, NameSet, BLOCK_MACROS, BLOCK_WIDGETS, RAW_BODY_MACROS, BRANCHING, quoteArg, last$1, BRANCH_PARENT, isBranchTag, lowerName, nameOf, closerOf, closes, astralIdentifierCodes, astralIdentifierStartCodes, nonASCIIidentifierChars, nonASCIIidentifierStartChars, reservedWords, ecma5AndLessKeywords, keywords$1, keywordRelationalOperator, nonASCIIidentifierStart, nonASCIIidentifier, TokenType, beforeExpr, startsExpr, keywords, types$1, lineBreak, lineBreakG, nonASCIIwhitespace, skipWhiteSpace, ref, hasOwnProperty, toString, hasOwn$1, isArray, regexpCache, loneSurrogate, Position, SourceLocation, defaultOptions, warnedAboutEcmaVersion, SCOPE_TOP, SCOPE_FUNCTION, SCOPE_ASYNC, SCOPE_GENERATOR, SCOPE_ARROW, SCOPE_SIMPLE_CATCH, SCOPE_SUPER, SCOPE_DIRECT_SUPER, SCOPE_CLASS_STATIC_BLOCK, SCOPE_CLASS_FIELD_INIT, SCOPE_SWITCH, SCOPE_VAR, BIND_NONE, BIND_VAR, BIND_LEXICAL, BIND_FUNCTION, BIND_SIMPLE_CATCH, BIND_OUTSIDE, Parser, prototypeAccessors, pp$9, literal, DestructuringErrors, pp$8, loopLabel, switchLabel, empty$1, FUNC_STATEMENT, FUNC_HANGING_STATEMENT, FUNC_NULLABLE_ID, pp$7, TokContext, types, pp$6, pp$5, empty, pp$4, pp$3, Scope, Node, pp$2, scriptValuesAddedInUnicode, ecma9BinaryProperties, ecma10BinaryProperties, ecma11BinaryProperties, ecma12BinaryProperties, ecma13BinaryProperties, unicodeBinaryProperties, unicodeBinaryPropertiesOfStrings, unicodeGeneralCategoryValues, ecma9ScriptValues, ecma10ScriptValues, ecma11ScriptValues, ecma12ScriptValues, ecma13ScriptValues, unicodeScriptValues, data, ecmaVersion, i, list, pp$1, BranchID, RegExpValidationState, CharSetNone, CharSetOk, CharSetString, Token, pp, INVALID_TEMPLATE_ESCAPE_ERROR, OPTIONS, AT_NAME_RE, TRANS_NAME_RE, SIGIL_IDENT_RE, LINE_BREAK_RE, NOT_A_BODY_RE, OPERAND_ENDS, SigilParser, OPENERS, CLOSERS$1, CodeSyntaxError, last, CLOSER, isNode, NAMESPACE_NAME, WORD_RE$2, FLAGS_RE, WORDS_BEFORE_STRING, NON_STRING_QUOTE_PREFIX, memoInput, memo, defaultCodeEnd, defaultHooks, MarkupError, OFFSET_FIELD, listeners, TRAILING_OPERATOR_RE, slice, MacroArgumentError, WORD_RE$1, NUMBER_RE$1, WORD_OR_PUNCT_RE, LEADING_OPERATOR_RE, takesRest, PARAMETER_TYPES, STRING_HOLDS, metadataRegistry, SUB_MACRO_PARAMETERS, RESERVED_NAME, isArrayIndex, hasOwn, createNamespace, parses, CONDITION_MACROS, PASSAGE_BODIES, holdsByDefault, JS_ESCAPE_RE, textPiece, registeredParameters, WIDGET_PARAMETERS, NOT_MARKUP, NOT_MARKUP_TAGS$1, BRANCH_MACROS, didYouMean, PASSAGE_ARGUMENT_HINT, BARE_WORD_RE, NUMBER_RE, IDENT_RE, KEY_RE, ARROW_RE, LINE_END_RE, ARRAY_INDEX_RE, UNSUPPORTED_UNDEFINED, Reader, VAR_PATH_RE, QUOTED_VAR_ARG_RE, VALID_VAR_TYPES, PRIMITIVE_SAMPLES, UNSUPPORTED_TYPE, NO_STORE_VAR_MACROS, FIELD_PATH_RE, CLOSERS, BLOCK_WORDS, NOT_PARAMETERS, DECLARATIONS, WRITE_RE, MUTATORS, MUTATING_CALL_RE, BEFORE_BINDING, isWordChar, Bindings, CALL_RE, IDENTIFIER_ARGUMENT_RE, WORD_RE, MODIFIER_RE, KEY_START_RE, CONFIG_KEYS, ConfigReader, stringOf, booleanOf, textOf, stringsOf, VOID_ELEMENTS, DEFAULT_PRETTIER_OPTIONS, SVG_PLACEHOLDERS, SPINDLE_PLACEHOLDERS, DEFAULT_DEDENTING, WHITESPACE_AS_WRITTEN, LIST_ITEM_REGEX, CODE_FENCE_REGEX, NOT_MARKUP_TAGS;
|
|
8730
9485
|
var init_story_variables = __esm({
|
|
8731
9486
|
"node_modules/@rohal12/spindle/dist/pkg/story-variables.js"() {
|
|
8732
9487
|
SIGIL_SCOPES = {
|
|
@@ -8891,6 +9646,9 @@ var init_story_variables = __esm({
|
|
|
8891
9646
|
delete(name) {
|
|
8892
9647
|
this.names.delete(name);
|
|
8893
9648
|
}
|
|
9649
|
+
clear() {
|
|
9650
|
+
this.names.clear();
|
|
9651
|
+
}
|
|
8894
9652
|
};
|
|
8895
9653
|
BLOCK_MACROS = new NameSet([
|
|
8896
9654
|
"if",
|
|
@@ -8908,6 +9666,7 @@ var init_story_variables = __esm({
|
|
|
8908
9666
|
"span",
|
|
8909
9667
|
"nobr"
|
|
8910
9668
|
]);
|
|
9669
|
+
BLOCK_WIDGETS = new NameSet();
|
|
8911
9670
|
RAW_BODY_MACROS = /* @__PURE__ */ new Set(["do"]);
|
|
8912
9671
|
BRANCHING = /* @__PURE__ */ new Set([
|
|
8913
9672
|
"if",
|
|
@@ -10085,7 +10844,7 @@ var init_story_variables = __esm({
|
|
|
10085
10844
|
ref = Object.prototype;
|
|
10086
10845
|
hasOwnProperty = ref.hasOwnProperty;
|
|
10087
10846
|
toString = ref.toString;
|
|
10088
|
-
hasOwn = Object.hasOwn || (function(obj, propName) {
|
|
10847
|
+
hasOwn$1 = Object.hasOwn || (function(obj, propName) {
|
|
10089
10848
|
return hasOwnProperty.call(obj, propName);
|
|
10090
10849
|
});
|
|
10091
10850
|
isArray = Array.isArray || (function(obj) {
|
|
@@ -11015,7 +11774,7 @@ var init_story_variables = __esm({
|
|
|
11015
11774
|
var parent = len === 0 ? null : this.privateNameStack[len - 1];
|
|
11016
11775
|
for (var i2 = 0; i2 < used.length; ++i2) {
|
|
11017
11776
|
var id = used[i2];
|
|
11018
|
-
if (!hasOwn(declared, id.name)) {
|
|
11777
|
+
if (!hasOwn$1(declared, id.name)) {
|
|
11019
11778
|
if (parent) parent.used.push(id);
|
|
11020
11779
|
else this.raiseRecoverable(id.start, "Private field '#" + id.name + "' must be declared in an enclosing class");
|
|
11021
11780
|
}
|
|
@@ -11093,7 +11852,7 @@ var init_story_variables = __esm({
|
|
|
11093
11852
|
pp$8.checkExport = function(exports$1, name, pos) {
|
|
11094
11853
|
if (!exports$1) return;
|
|
11095
11854
|
if (typeof name !== "string") name = name.type === "Identifier" ? name.name : name.value;
|
|
11096
|
-
if (hasOwn(exports$1, name)) this.raiseRecoverable(pos, "Duplicate export '" + name + "'");
|
|
11855
|
+
if (hasOwn$1(exports$1, name)) this.raiseRecoverable(pos, "Duplicate export '" + name + "'");
|
|
11097
11856
|
exports$1[name] = true;
|
|
11098
11857
|
};
|
|
11099
11858
|
pp$8.checkPatternExport = function(exports$1, pat) {
|
|
@@ -11212,7 +11971,7 @@ var init_story_variables = __esm({
|
|
|
11212
11971
|
} else first = false;
|
|
11213
11972
|
var attr = this.parseImportAttribute();
|
|
11214
11973
|
var keyName = attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
|
|
11215
|
-
if (hasOwn(attributeKeys, keyName)) this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'");
|
|
11974
|
+
if (hasOwn$1(attributeKeys, keyName)) this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'");
|
|
11216
11975
|
attributeKeys[keyName] = true;
|
|
11217
11976
|
nodes.push(attr);
|
|
11218
11977
|
}
|
|
@@ -11374,7 +12133,7 @@ var init_story_variables = __esm({
|
|
|
11374
12133
|
if (isBind) {
|
|
11375
12134
|
if (bindingType === BIND_LEXICAL && expr.name === "let") this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name");
|
|
11376
12135
|
if (checkClashes) {
|
|
11377
|
-
if (hasOwn(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash");
|
|
12136
|
+
if (hasOwn$1(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash");
|
|
11378
12137
|
checkClashes[expr.name] = true;
|
|
11379
12138
|
}
|
|
11380
12139
|
if (bindingType !== BIND_OUTSIDE) this.declareName(expr.name, bindingType, expr.start);
|
|
@@ -13034,7 +13793,7 @@ var init_story_variables = __esm({
|
|
|
13034
13793
|
return CharSetNone;
|
|
13035
13794
|
};
|
|
13036
13795
|
pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
|
|
13037
|
-
if (!hasOwn(state.unicodeProperties.nonBinary, name)) state.raise("Invalid property name");
|
|
13796
|
+
if (!hasOwn$1(state.unicodeProperties.nonBinary, name)) state.raise("Invalid property name");
|
|
13038
13797
|
if (!state.unicodeProperties.nonBinary[name].test(value)) state.raise("Invalid property value");
|
|
13039
13798
|
};
|
|
13040
13799
|
pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
|
|
@@ -14026,15 +14785,15 @@ var init_story_variables = __esm({
|
|
|
14026
14785
|
}
|
|
14027
14786
|
const self = this;
|
|
14028
14787
|
const prevType = self.type;
|
|
14029
|
-
this.prevValue = self.value;
|
|
14030
|
-
const property = type.keyword !== void 0 && (prevType
|
|
14788
|
+
this.prevValue = isMemberDot(this.typeBeforeLast) ? void 0 : self.value;
|
|
14789
|
+
const property = type.keyword !== void 0 && isMemberDot(prevType) || (type === types$1._function || type === types$1._class) && notABody(self.input, self.pos);
|
|
14031
14790
|
if (!property && (type === types$1._function || type === types$1._class)) {
|
|
14032
14791
|
const before = type === types$1._function && prevType === types$1.name && this.prevValue === "async" && !this.breakHere ? this.typeBeforeLast : prevType;
|
|
14033
14792
|
self.type = before === types$1.colon && this.colonEndsTernary ? types$1.parenL : before;
|
|
14034
14793
|
}
|
|
14035
14794
|
this.typeBeforeLast = prevType;
|
|
14036
14795
|
super.finishToken(property ? types$1.name : type, value);
|
|
14037
|
-
if (type === types$1.name && value === "of" && (prevType === types$1._const || prevType === types$1._var || this.prevValue === "let")) self.exprAllowed = false;
|
|
14796
|
+
if (type === types$1.name && (isMemberDot(prevType) || value === "of" && (prevType === types$1._const || prevType === types$1._var || this.prevValue === "let"))) self.exprAllowed = false;
|
|
14038
14797
|
}
|
|
14039
14798
|
braceIsBlock(prevType) {
|
|
14040
14799
|
if (prevType === types$1.colon && this.colonEndsTernary) return false;
|
|
@@ -14054,7 +14813,7 @@ var init_story_variables = __esm({
|
|
|
14054
14813
|
types$1.braceL,
|
|
14055
14814
|
types$1.dollarBraceL
|
|
14056
14815
|
]);
|
|
14057
|
-
CLOSERS = /* @__PURE__ */ new Set([
|
|
14816
|
+
CLOSERS$1 = /* @__PURE__ */ new Set([
|
|
14058
14817
|
types$1.parenR,
|
|
14059
14818
|
types$1.bracketR,
|
|
14060
14819
|
types$1.braceR
|
|
@@ -14106,28 +14865,7 @@ var init_story_variables = __esm({
|
|
|
14106
14865
|
NON_STRING_QUOTE_PREFIX = /[\p{L}\p{N}_\\]/u;
|
|
14107
14866
|
memoInput = "";
|
|
14108
14867
|
memo = /* @__PURE__ */ new Map();
|
|
14109
|
-
defaultCodeEnd =
|
|
14110
|
-
closeBrace(input, codeStart, lenientStart) {
|
|
14111
|
-
const end = findCodeEnd(input, codeStart);
|
|
14112
|
-
return end !== -1 ? end : lenientClose(input, lenientStart);
|
|
14113
|
-
},
|
|
14114
|
-
rawBodyEnd(input, bodyStart, name) {
|
|
14115
|
-
const closer = `\\{/${name}\\s*\\}`;
|
|
14116
|
-
const first = new RegExp(closer, "gi");
|
|
14117
|
-
first.lastIndex = bodyStart;
|
|
14118
|
-
const firstAt = first.exec(input)?.index ?? -1;
|
|
14119
|
-
if (firstAt === -1) return -1;
|
|
14120
|
-
const at3 = new RegExp(closer, "iy");
|
|
14121
|
-
const end = findCodeEnd(input, bodyStart, {
|
|
14122
|
-
goal: "statements",
|
|
14123
|
-
stop: (k2) => {
|
|
14124
|
-
at3.lastIndex = k2;
|
|
14125
|
-
return at3.test(input);
|
|
14126
|
-
}
|
|
14127
|
-
});
|
|
14128
|
-
return end === -1 ? firstAt : end;
|
|
14129
|
-
}
|
|
14130
|
-
};
|
|
14868
|
+
defaultCodeEnd = jsCodeEnd();
|
|
14131
14869
|
defaultHooks = {
|
|
14132
14870
|
...defaultCodeEnd,
|
|
14133
14871
|
isBlock: isBlockMacro,
|
|
@@ -14163,28 +14901,6 @@ var init_story_variables = __esm({
|
|
|
14163
14901
|
WORD_OR_PUNCT_RE = /\S+/y;
|
|
14164
14902
|
LEADING_OPERATOR_RE = /^(?:[-+*/&|^=<>?:,.]|%(?![A-Za-z_]))/;
|
|
14165
14903
|
takesRest = (param) => param.type === "expression" || param.type === "statements" || param.type === "passage" || param.type === "text";
|
|
14166
|
-
SUB_MACRO_PARAMETERS = /* @__PURE__ */ new Map([["option", [{
|
|
14167
|
-
name: "value",
|
|
14168
|
-
type: "string",
|
|
14169
|
-
holds: "text",
|
|
14170
|
-
required: true
|
|
14171
|
-
}]]]);
|
|
14172
|
-
parses = null;
|
|
14173
|
-
CONDITION_MACROS = /* @__PURE__ */ new Set([
|
|
14174
|
-
"if",
|
|
14175
|
-
"elseif",
|
|
14176
|
-
"case"
|
|
14177
|
-
]);
|
|
14178
|
-
PASSAGE_BODIES = /* @__PURE__ */ new Set(["dialog"]);
|
|
14179
|
-
holdsByDefault = (interpolate) => interpolate ? "markup" : "text";
|
|
14180
|
-
textPiece = (text2, offset2, where2) => ({
|
|
14181
|
-
kind: "text",
|
|
14182
|
-
text: text2,
|
|
14183
|
-
offset: offset2,
|
|
14184
|
-
where: where2,
|
|
14185
|
-
tokens: [],
|
|
14186
|
-
errors: []
|
|
14187
|
-
});
|
|
14188
14904
|
new NameMap();
|
|
14189
14905
|
new NameMap();
|
|
14190
14906
|
new NameSet();
|
|
@@ -14210,6 +14926,34 @@ var init_story_variables = __esm({
|
|
|
14210
14926
|
"statements"
|
|
14211
14927
|
];
|
|
14212
14928
|
metadataRegistry = new NameMap();
|
|
14929
|
+
SUB_MACRO_PARAMETERS = /* @__PURE__ */ new Map([["option", [{
|
|
14930
|
+
name: "value",
|
|
14931
|
+
type: "string",
|
|
14932
|
+
holds: "text",
|
|
14933
|
+
required: true
|
|
14934
|
+
}]]]);
|
|
14935
|
+
RESERVED_NAME = "__proto__";
|
|
14936
|
+
isArrayIndex = (key) => /^(?:0|[1-9]\d*)$/.test(key);
|
|
14937
|
+
hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
14938
|
+
createNamespace = (...sources) => ownEntries(sources);
|
|
14939
|
+
Object.freeze(createNamespace());
|
|
14940
|
+
parses = null;
|
|
14941
|
+
CONDITION_MACROS = /* @__PURE__ */ new Set([
|
|
14942
|
+
"if",
|
|
14943
|
+
"elseif",
|
|
14944
|
+
"case"
|
|
14945
|
+
]);
|
|
14946
|
+
PASSAGE_BODIES = /* @__PURE__ */ new Set(["dialog"]);
|
|
14947
|
+
holdsByDefault = (interpolate) => interpolate ? "markup" : "text";
|
|
14948
|
+
JS_ESCAPE_RE = /\\(?:u\{[0-9a-fA-F]+\}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|[0-3][0-7]{0,2}|[4-7][0-7]?|\r\n|[^])/y;
|
|
14949
|
+
textPiece = (text2, offset2, where2) => ({
|
|
14950
|
+
kind: "text",
|
|
14951
|
+
text: text2,
|
|
14952
|
+
offset: offset2,
|
|
14953
|
+
where: where2,
|
|
14954
|
+
tokens: [],
|
|
14955
|
+
errors: []
|
|
14956
|
+
});
|
|
14213
14957
|
registeredParameters = (name) => parameterLookup(getMacroRegistry())(name);
|
|
14214
14958
|
WIDGET_PARAMETERS = [{
|
|
14215
14959
|
name: "name",
|
|
@@ -14237,22 +14981,26 @@ var init_story_variables = __esm({
|
|
|
14237
14981
|
didYouMean = (best, quote) => best ? ` Did you mean ${quote(best)}?` : "";
|
|
14238
14982
|
PASSAGE_ARGUMENT_HINT = " (a passage name is a quoted string or an expression)";
|
|
14239
14983
|
BARE_WORD_RE = /^[A-Za-z][\w$]*$/;
|
|
14240
|
-
|
|
14241
|
-
createNamespace = (...sources) => ownEntries(sources);
|
|
14242
|
-
Object.freeze(createNamespace());
|
|
14243
|
-
NUMBER_RE = /(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|(?:\d[\d_]*\.?[\d_]*|\.\d[\d_]*)(?:[eE][+-]?\d+)?)(n?)/y;
|
|
14984
|
+
NUMBER_RE = /(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|(?:\d[\d_]*\.?[\d_]*|\.\d[\d_]*)(?:[eE][+-]?\d[\d_]*)?)(n?)/y;
|
|
14244
14985
|
IDENT_RE = /[A-Za-z_$][\w$]*/y;
|
|
14245
14986
|
KEY_RE = /[\w$]+/y;
|
|
14246
14987
|
ARROW_RE = /(?:async\s+)?(?:\((?:[^()]|\([^()]*\))*\)|[A-Za-z_$][\w$]*)\s*=>/y;
|
|
14988
|
+
LINE_END_RE = /[\n\r\u2028\u2029]/g;
|
|
14247
14989
|
ARRAY_INDEX_RE = /^(?:0|[1-9]\d{0,8})$/;
|
|
14248
14990
|
UNSUPPORTED_UNDEFINED = {
|
|
14249
14991
|
unsupported: "undefined",
|
|
14250
14992
|
value: "undefined"
|
|
14251
14993
|
};
|
|
14252
14994
|
Reader = class {
|
|
14253
|
-
|
|
14995
|
+
/**
|
|
14996
|
+
* `regexes` (see regexLiterals) are read from `src` when they are first
|
|
14997
|
+
* needed, unless the caller has them already.
|
|
14998
|
+
*/
|
|
14999
|
+
constructor(src, options = {}) {
|
|
14254
15000
|
this.src = src;
|
|
14255
15001
|
this.i = 0;
|
|
15002
|
+
this.goal = options.goal ?? "expression";
|
|
15003
|
+
this.regexes = options.regexes;
|
|
14256
15004
|
}
|
|
14257
15005
|
/** Skip whitespace and comments. */
|
|
14258
15006
|
space() {
|
|
@@ -14260,8 +15008,8 @@ var init_story_variables = __esm({
|
|
|
14260
15008
|
for (; ; ) {
|
|
14261
15009
|
while (/\s/.test(src.charAt(this.i))) this.i++;
|
|
14262
15010
|
if (src.startsWith("//", this.i)) {
|
|
14263
|
-
|
|
14264
|
-
this.i =
|
|
15011
|
+
LINE_END_RE.lastIndex = this.i;
|
|
15012
|
+
this.i = LINE_END_RE.test(src) ? LINE_END_RE.lastIndex - 1 : src.length;
|
|
14265
15013
|
} else if (src.startsWith("/*", this.i)) {
|
|
14266
15014
|
const end = src.indexOf("*/", this.i + 2);
|
|
14267
15015
|
this.i = end < 0 ? src.length : end + 2;
|
|
@@ -14320,10 +15068,9 @@ var init_story_variables = __esm({
|
|
|
14320
15068
|
i2++;
|
|
14321
15069
|
while (/\s/.test(src.charAt(i2))) i2++;
|
|
14322
15070
|
}
|
|
14323
|
-
|
|
14324
|
-
const match = NUMBER_RE.exec(src);
|
|
15071
|
+
const match = this.numberAt(i2);
|
|
14325
15072
|
if (match) {
|
|
14326
|
-
this.i =
|
|
15073
|
+
this.i = i2 + match[0].length;
|
|
14327
15074
|
if (!match[1]) return { shape: { type: "number" } };
|
|
14328
15075
|
if (sign === "+") return { throws: "Cannot convert a BigInt value to a number" };
|
|
14329
15076
|
const digits = bigintValue(match[0].slice(0, -1));
|
|
@@ -14333,11 +15080,17 @@ var init_story_variables = __esm({
|
|
|
14333
15080
|
};
|
|
14334
15081
|
}
|
|
14335
15082
|
IDENT_RE.lastIndex = i2;
|
|
14336
|
-
|
|
15083
|
+
const word = IDENT_RE.exec(src)?.[0];
|
|
15084
|
+
if (word === "Infinity" || word === "NaN") {
|
|
14337
15085
|
this.i = IDENT_RE.lastIndex;
|
|
14338
15086
|
return { shape: { type: "number" } };
|
|
14339
15087
|
}
|
|
14340
15088
|
}
|
|
15089
|
+
/** The numeric literal (a BigInt's `n` is `match[1]`) at `at`, if there is one. */
|
|
15090
|
+
numberAt(at3) {
|
|
15091
|
+
NUMBER_RE.lastIndex = at3;
|
|
15092
|
+
return NUMBER_RE.exec(this.src);
|
|
15093
|
+
}
|
|
14341
15094
|
/** A keyword, a function, or a name (which is not static). */
|
|
14342
15095
|
word() {
|
|
14343
15096
|
const { src } = this;
|
|
@@ -14357,6 +15110,7 @@ var init_story_variables = __esm({
|
|
|
14357
15110
|
this.i = end;
|
|
14358
15111
|
return { shape: { type: "null" } };
|
|
14359
15112
|
case "NaN":
|
|
15113
|
+
case "Infinity":
|
|
14360
15114
|
this.i = end;
|
|
14361
15115
|
return { shape: { type: "number" } };
|
|
14362
15116
|
case "undefined":
|
|
@@ -14498,14 +15252,22 @@ var init_story_variables = __esm({
|
|
|
14498
15252
|
const { src } = this;
|
|
14499
15253
|
const c = src.charAt(this.i);
|
|
14500
15254
|
if (c === '"' || c === "'") return this.stringValue();
|
|
15255
|
+
if (/[\d.]/.test(c)) return this.numberKey();
|
|
14501
15256
|
KEY_RE.lastIndex = this.i;
|
|
14502
15257
|
const found = KEY_RE.exec(src)?.[0];
|
|
14503
15258
|
if (found === void 0) return void 0;
|
|
14504
15259
|
this.i = KEY_RE.lastIndex;
|
|
14505
|
-
|
|
14506
|
-
|
|
15260
|
+
return found;
|
|
15261
|
+
}
|
|
15262
|
+
/** A number as a key: the whole literal, named as the runtime names it. */
|
|
15263
|
+
numberKey() {
|
|
15264
|
+
const match = this.numberAt(this.i);
|
|
15265
|
+
if (!match) return void 0;
|
|
15266
|
+
this.i += match[0].length;
|
|
15267
|
+
if (/[\w$]/.test(this.src.charAt(this.i))) return void 0;
|
|
15268
|
+
const digits = match[0].replace(/_/g, "");
|
|
14507
15269
|
if (/^0\d/.test(digits)) return void 0;
|
|
14508
|
-
if (
|
|
15270
|
+
if (match[1]) return bigintValue(digits.slice(0, -1));
|
|
14509
15271
|
const value = Number(digits);
|
|
14510
15272
|
return Number.isNaN(value) ? void 0 : String(value);
|
|
14511
15273
|
}
|
|
@@ -14548,6 +15310,14 @@ var init_story_variables = __esm({
|
|
|
14548
15310
|
this.space();
|
|
14549
15311
|
return true;
|
|
14550
15312
|
}
|
|
15313
|
+
if (c === "/") {
|
|
15314
|
+
this.regexes ?? (this.regexes = regexLiterals(src, this.goal));
|
|
15315
|
+
const end = this.regexes.get(this.i);
|
|
15316
|
+
if (end !== void 0) {
|
|
15317
|
+
this.i = end;
|
|
15318
|
+
return true;
|
|
15319
|
+
}
|
|
15320
|
+
}
|
|
14551
15321
|
if (c === "[" || c === "{" || c === "(") return this.skipBalanced();
|
|
14552
15322
|
if (c === "]" || c === "}" || c === ")") return false;
|
|
14553
15323
|
this.i++;
|
|
@@ -14585,9 +15355,470 @@ var init_story_variables = __esm({
|
|
|
14585
15355
|
};
|
|
14586
15356
|
UNSUPPORTED_TYPE = "Expected number, string, boolean, array, or object.";
|
|
14587
15357
|
NO_STORE_VAR_MACROS = /* @__PURE__ */ new Set();
|
|
15358
|
+
FIELD_PATH_RE = /(?:\.\w+)*/y;
|
|
15359
|
+
CLOSERS = {
|
|
15360
|
+
"}": "{",
|
|
15361
|
+
")": "(",
|
|
15362
|
+
"]": "["
|
|
15363
|
+
};
|
|
15364
|
+
BLOCK_WORDS = /* @__PURE__ */ new Set([
|
|
15365
|
+
"if",
|
|
15366
|
+
"for",
|
|
15367
|
+
"while",
|
|
15368
|
+
"switch",
|
|
15369
|
+
"with",
|
|
15370
|
+
"catch"
|
|
15371
|
+
]);
|
|
15372
|
+
NOT_PARAMETERS = /* @__PURE__ */ new Set([
|
|
15373
|
+
"if",
|
|
15374
|
+
"for",
|
|
15375
|
+
"while",
|
|
15376
|
+
"switch",
|
|
15377
|
+
"with"
|
|
15378
|
+
]);
|
|
15379
|
+
DECLARATIONS = /* @__PURE__ */ new Set([
|
|
15380
|
+
"const",
|
|
15381
|
+
"let",
|
|
15382
|
+
"var"
|
|
15383
|
+
]);
|
|
15384
|
+
WRITE_RE = /(?:(?:\*\*|<<|>>>?|&&|\|\||\?\?|[-+*/%&|^])=(?!=)|=(?![=>])|\+\+|--)/y;
|
|
15385
|
+
MUTATORS = /* @__PURE__ */ new Set([
|
|
15386
|
+
"push",
|
|
15387
|
+
"pop",
|
|
15388
|
+
"shift",
|
|
15389
|
+
"unshift",
|
|
15390
|
+
"splice",
|
|
15391
|
+
"sort",
|
|
15392
|
+
"reverse",
|
|
15393
|
+
"fill",
|
|
15394
|
+
"copyWithin"
|
|
15395
|
+
]);
|
|
15396
|
+
MUTATING_CALL_RE = /(?:Object|Reflect)\s*\.\s*(?:assign|defineProperty|defineProperties|setPrototypeOf|set|deleteProperty)\s*$/;
|
|
15397
|
+
BEFORE_BINDING = {
|
|
15398
|
+
"{": "{,:",
|
|
15399
|
+
"[": "[,",
|
|
15400
|
+
"(": "(,"
|
|
15401
|
+
};
|
|
15402
|
+
isWordChar = (c) => !!c && /[\w$]/.test(c);
|
|
15403
|
+
Bindings = class {
|
|
15404
|
+
constructor(code) {
|
|
15405
|
+
this.code = code;
|
|
15406
|
+
this.groups = [];
|
|
15407
|
+
this.byOpen = /* @__PURE__ */ new Map();
|
|
15408
|
+
this.byClose = /* @__PURE__ */ new Map();
|
|
15409
|
+
this.functions = /* @__PURE__ */ new Map();
|
|
15410
|
+
this.top = {
|
|
15411
|
+
start: -1,
|
|
15412
|
+
end: Infinity
|
|
15413
|
+
};
|
|
15414
|
+
this.readGroups();
|
|
15415
|
+
}
|
|
15416
|
+
/**
|
|
15417
|
+
* The `{` of the object literal that `name`, used at `at`, is declared as
|
|
15418
|
+
* (`const`, `let` or `var`), when that is the declaration it names: the
|
|
15419
|
+
* innermost one in the scope of the use, that comes before it unless the
|
|
15420
|
+
* use is in a function of its own. `undefined` if it names another value,
|
|
15421
|
+
* more than one declaration is the innermost, or the value is written to
|
|
15422
|
+
* (given another, or one of its `properties` set) where the use can follow.
|
|
15423
|
+
*/
|
|
15424
|
+
objectOf(name, at3, properties) {
|
|
15425
|
+
const { code } = this;
|
|
15426
|
+
const escaped = name.replace(/\$/g, "\\$");
|
|
15427
|
+
const bindings = [];
|
|
15428
|
+
for (const m of code.matchAll(new RegExp(`(?<![\\w$])${escaped}(?![\\w$])`, "g"))) {
|
|
15429
|
+
const binding = this.bindingAt(m.index, name.length, properties);
|
|
15430
|
+
if (binding) bindings.push(binding);
|
|
15431
|
+
}
|
|
15432
|
+
const declarations = bindings.filter((b) => !b.write);
|
|
15433
|
+
for (const b of bindings) if (b.write) b.scope = this.innermostVisible(declarations, b.at)[0]?.scope ?? this.top;
|
|
15434
|
+
const found = this.innermostVisible(bindings, at3);
|
|
15435
|
+
return found.length === 1 ? found[0].object : void 0;
|
|
15436
|
+
}
|
|
15437
|
+
/**
|
|
15438
|
+
* Of the `bindings` the use at `at` can see, those in the innermost scope:
|
|
15439
|
+
* the scope is the use's, and a binding comes before it, unless the use is
|
|
15440
|
+
* in a function of its own.
|
|
15441
|
+
*/
|
|
15442
|
+
innermostVisible(bindings, at3) {
|
|
15443
|
+
const useFunction = this.functionStart(at3);
|
|
15444
|
+
const visible = bindings.filter((b) => b.scope.start <= at3 && at3 < b.scope.end && (!b.ordered || b.at < at3 || this.functionStart(b.at) !== useFunction));
|
|
15445
|
+
const innermost = Math.max(...visible.map((b) => b.scope.start));
|
|
15446
|
+
return visible.filter((b) => b.scope.start === innermost);
|
|
15447
|
+
}
|
|
15448
|
+
readGroups() {
|
|
15449
|
+
const { code, groups } = this;
|
|
15450
|
+
const stack = [];
|
|
15451
|
+
for (let i2 = 0; i2 < code.length; i2++) {
|
|
15452
|
+
const c = code.charAt(i2);
|
|
15453
|
+
if (c === "{" || c === "(" || c === "[") {
|
|
15454
|
+
const group = {
|
|
15455
|
+
kind: c,
|
|
15456
|
+
open: i2,
|
|
15457
|
+
close: code.length,
|
|
15458
|
+
parent: stack[stack.length - 1]
|
|
15459
|
+
};
|
|
15460
|
+
groups.push(group);
|
|
15461
|
+
stack.push(group);
|
|
15462
|
+
this.byOpen.set(i2, group);
|
|
15463
|
+
} else if (CLOSERS[c]) {
|
|
15464
|
+
let k2 = stack.length - 1;
|
|
15465
|
+
while (k2 >= 0 && stack[k2].kind !== CLOSERS[c]) k2--;
|
|
15466
|
+
if (k2 >= 0) {
|
|
15467
|
+
stack[k2].close = i2;
|
|
15468
|
+
this.byClose.set(i2, stack[k2]);
|
|
15469
|
+
stack.length = k2;
|
|
15470
|
+
}
|
|
15471
|
+
}
|
|
15472
|
+
}
|
|
15473
|
+
}
|
|
15474
|
+
/** The innermost group that has `index` inside it, of this kind if given. */
|
|
15475
|
+
innermost(index, kind) {
|
|
15476
|
+
const { groups } = this;
|
|
15477
|
+
for (let k2 = groups.length - 1; k2 >= 0; k2--) {
|
|
15478
|
+
const g = groups[k2];
|
|
15479
|
+
if (g.open < index && index < g.close && (!kind || g.kind === kind)) return g;
|
|
15480
|
+
}
|
|
15481
|
+
}
|
|
15482
|
+
/**
|
|
15483
|
+
* The word before a `(` group (`if`, `for`, `catch`, a function's name…);
|
|
15484
|
+
* `for await` is `for`.
|
|
15485
|
+
*/
|
|
15486
|
+
ownerWord(paren) {
|
|
15487
|
+
const word = this.wordBefore(this.backFrom(paren.open) + 1);
|
|
15488
|
+
if (word.text !== "await") return word.text;
|
|
15489
|
+
const before = this.wordBefore(this.backFrom(word.start) + 1).text;
|
|
15490
|
+
return before === "for" ? before : word.text;
|
|
15491
|
+
}
|
|
15492
|
+
/**
|
|
15493
|
+
* Whether the `{` group is the body of a function (or method), or of a
|
|
15494
|
+
* class static block, which has the scope of a `var` of its own.
|
|
15495
|
+
*/
|
|
15496
|
+
isFunctionBody(group) {
|
|
15497
|
+
if (group.kind !== "{") return false;
|
|
15498
|
+
let known = this.functions.get(group);
|
|
15499
|
+
if (known === void 0) {
|
|
15500
|
+
const before = this.backFrom(group.open);
|
|
15501
|
+
const { code } = this;
|
|
15502
|
+
if (code.charAt(before) === ")") {
|
|
15503
|
+
const params = this.byClose.get(before);
|
|
15504
|
+
known = !!params && !BLOCK_WORDS.has(this.ownerWord(params));
|
|
15505
|
+
} else known = code.slice(before - 1, before + 1) === "=>" || this.wordBefore(before + 1).text === "static";
|
|
15506
|
+
this.functions.set(group, known);
|
|
15507
|
+
}
|
|
15508
|
+
return known;
|
|
15509
|
+
}
|
|
15510
|
+
/** The start of the function that has `index` in its body, or -1. */
|
|
15511
|
+
functionStart(index) {
|
|
15512
|
+
for (let g = this.innermost(index, "{"); g; g = g.parent) if (g.kind === "{" && this.isFunctionBody(g)) return g.open;
|
|
15513
|
+
return -1;
|
|
15514
|
+
}
|
|
15515
|
+
scopeOf(group) {
|
|
15516
|
+
return group ? {
|
|
15517
|
+
start: group.open,
|
|
15518
|
+
end: group.close
|
|
15519
|
+
} : this.top;
|
|
15520
|
+
}
|
|
15521
|
+
/** The block `index` is in: what `let` and `const` declare for. */
|
|
15522
|
+
blockAt(index) {
|
|
15523
|
+
return this.scopeOf(this.innermost(index, "{"));
|
|
15524
|
+
}
|
|
15525
|
+
/** The function (or the whole text) `index` is in: what `var` declares for. */
|
|
15526
|
+
functionAt(index) {
|
|
15527
|
+
const start = this.functionStart(index);
|
|
15528
|
+
return start < 0 ? this.top : this.scopeOf(this.byOpen.get(start));
|
|
15529
|
+
}
|
|
15530
|
+
/**
|
|
15531
|
+
* What the declaration keyword `word` (`var`, `let`, `const`) declares for:
|
|
15532
|
+
* the function for `var`, the block for the others, or the `for` statement,
|
|
15533
|
+
* header and body, when the declaration is in its header.
|
|
15534
|
+
*/
|
|
15535
|
+
declaredIn(word) {
|
|
15536
|
+
if (word.text === "var") return this.functionAt(word.start);
|
|
15537
|
+
const group = this.innermost(word.start);
|
|
15538
|
+
if (group?.kind === "(" && this.ownerWord(group) === "for") return {
|
|
15539
|
+
start: group.open,
|
|
15540
|
+
end: this.statementEnd(group.close + 1)
|
|
15541
|
+
};
|
|
15542
|
+
return this.blockAt(word.start);
|
|
15543
|
+
}
|
|
15544
|
+
/**
|
|
15545
|
+
* Where the statement that starts at `from` ends: a block, the body of an
|
|
15546
|
+
* `if`, `for`, `while` or `with` (and the `else` of an `if`), or else up to
|
|
15547
|
+
* a `;`, the closer of the group it is in, or a line break that is followed
|
|
15548
|
+
* by a statement of its own.
|
|
15549
|
+
*/
|
|
15550
|
+
statementEnd(from) {
|
|
15551
|
+
const { code } = this;
|
|
15552
|
+
const start = this.forward(from);
|
|
15553
|
+
const block = this.byOpen.get(start);
|
|
15554
|
+
if (block?.kind === "{") return Math.min(block.close + 1, code.length);
|
|
15555
|
+
const word = this.wordAt(start);
|
|
15556
|
+
if (/^(?:if|for|while|with)$/.test(word)) {
|
|
15557
|
+
let paren = this.forward(start + word.length);
|
|
15558
|
+
if (word === "for" && this.wordAt(paren) === "await") paren = this.forward(paren + 5);
|
|
15559
|
+
const header = this.byOpen.get(paren);
|
|
15560
|
+
if (header) {
|
|
15561
|
+
const end = this.statementEnd(header.close + 1);
|
|
15562
|
+
const next = this.forward(end);
|
|
15563
|
+
return word === "if" && this.wordAt(next) === "else" ? this.statementEnd(next + 4) : end;
|
|
15564
|
+
}
|
|
15565
|
+
}
|
|
15566
|
+
for (let end = start; end < code.length; end++) {
|
|
15567
|
+
const c = code.charAt(end);
|
|
15568
|
+
if (c === ";") return end + 1;
|
|
15569
|
+
if (CLOSERS[c]) return end;
|
|
15570
|
+
const group = this.byOpen.get(end);
|
|
15571
|
+
if (group) end = group.close;
|
|
15572
|
+
else if (c === "\n" && this.startsStatement(end)) return end;
|
|
15573
|
+
}
|
|
15574
|
+
return code.length;
|
|
15575
|
+
}
|
|
15576
|
+
/** Whether the line break at `index` ends a statement, and one follows. */
|
|
15577
|
+
startsStatement(index) {
|
|
15578
|
+
const next = this.forward(index);
|
|
15579
|
+
return /[\w$)\]}]/.test(this.code.charAt(this.backFrom(index))) && isWordChar(this.code.charAt(next)) && !/^(?:in|of|instanceof|else)$/.test(this.wordAt(next));
|
|
15580
|
+
}
|
|
15581
|
+
/** What a parameter list, whose `)` is `close`, is the scope of: the body. */
|
|
15582
|
+
bodyAfter(close) {
|
|
15583
|
+
const next = this.forward(close + 1);
|
|
15584
|
+
if (this.code.charAt(next) === "{") return this.scopeOf(this.byOpen.get(next));
|
|
15585
|
+
return this.code.startsWith("=>", next) ? this.arrowBody(next + 2) : void 0;
|
|
15586
|
+
}
|
|
15587
|
+
/** The body of an arrow function, whose `=>` ends before `from`. */
|
|
15588
|
+
arrowBody(from) {
|
|
15589
|
+
const { code } = this;
|
|
15590
|
+
const start = this.forward(from);
|
|
15591
|
+
if (code.charAt(start) === "{") return this.scopeOf(this.byOpen.get(start));
|
|
15592
|
+
let end = start;
|
|
15593
|
+
while (end < code.length && !",;)]}".includes(code.charAt(end))) {
|
|
15594
|
+
end = this.byOpen.get(end)?.close ?? end;
|
|
15595
|
+
end++;
|
|
15596
|
+
}
|
|
15597
|
+
return {
|
|
15598
|
+
start,
|
|
15599
|
+
end
|
|
15600
|
+
};
|
|
15601
|
+
}
|
|
15602
|
+
/** The index of the last character that is no space before `index`, or -1. */
|
|
15603
|
+
backFrom(index) {
|
|
15604
|
+
let i2 = index - 1;
|
|
15605
|
+
while (i2 >= 0 && /\s/.test(this.code.charAt(i2))) i2--;
|
|
15606
|
+
return i2;
|
|
15607
|
+
}
|
|
15608
|
+
/** The index of the first character that is no space from `index` on. */
|
|
15609
|
+
forward(index) {
|
|
15610
|
+
let i2 = index;
|
|
15611
|
+
while (i2 < this.code.length && /\s/.test(this.code.charAt(i2))) i2++;
|
|
15612
|
+
return i2;
|
|
15613
|
+
}
|
|
15614
|
+
/** The word that starts at `index` (empty if there is none). */
|
|
15615
|
+
wordAt(index) {
|
|
15616
|
+
return this.code.slice(index, this.nameEnd(index));
|
|
15617
|
+
}
|
|
15618
|
+
/** The word that ends before `end`, and where it starts. */
|
|
15619
|
+
wordBefore(end) {
|
|
15620
|
+
let start = end;
|
|
15621
|
+
while (start > 0 && isWordChar(this.code.charAt(start - 1))) start--;
|
|
15622
|
+
return {
|
|
15623
|
+
text: this.code.slice(start, end),
|
|
15624
|
+
start
|
|
15625
|
+
};
|
|
15626
|
+
}
|
|
15627
|
+
/**
|
|
15628
|
+
* What the name of `length` characters at `at` declares, or writes to, if it
|
|
15629
|
+
* does. A write to a `properties` of it counts, one to another does not.
|
|
15630
|
+
*/
|
|
15631
|
+
bindingAt(at3, length, properties) {
|
|
15632
|
+
const { code } = this;
|
|
15633
|
+
let before = this.backFrom(at3);
|
|
15634
|
+
const spread = code.slice(before - 2, before + 1) === "...";
|
|
15635
|
+
if (code.charAt(before) === "." && !spread) return void 0;
|
|
15636
|
+
if (spread) before = this.backFrom(before - 2);
|
|
15637
|
+
const after = this.forward(at3 + length);
|
|
15638
|
+
return this.declarationAt(at3, before, spread) ?? this.patternAt(at3, before, after) ?? this.arrowParameterAt(at3, after) ?? (spread ? void 0 : this.writeAt(at3, before, after, properties));
|
|
15639
|
+
}
|
|
15640
|
+
/** `const x`, `let x`, `var x`, a later `y` of `let x, y`, `function x`, `class x`. */
|
|
15641
|
+
declarationAt(at3, before, spread) {
|
|
15642
|
+
if (spread) return void 0;
|
|
15643
|
+
const word = this.code.charAt(before) === "," ? this.listKeyword(before) : this.wordBefore(before + 1);
|
|
15644
|
+
if (!word || this.code.charAt(word.start - 1) === ".") return void 0;
|
|
15645
|
+
if (DECLARATIONS.has(word.text)) {
|
|
15646
|
+
const scope = this.declaredIn(word);
|
|
15647
|
+
const init = /\s*=\s*(?=\{)/y;
|
|
15648
|
+
init.lastIndex = this.nameEnd(at3);
|
|
15649
|
+
return {
|
|
15650
|
+
scope,
|
|
15651
|
+
at: at3,
|
|
15652
|
+
ordered: true,
|
|
15653
|
+
object: init.test(this.code) ? init.lastIndex : void 0
|
|
15654
|
+
};
|
|
15655
|
+
}
|
|
15656
|
+
if (word.text === "function" || word.text === "class") return {
|
|
15657
|
+
scope: this.blockAt(word.start),
|
|
15658
|
+
at: at3,
|
|
15659
|
+
ordered: word.text === "class"
|
|
15660
|
+
};
|
|
15661
|
+
}
|
|
15662
|
+
/**
|
|
15663
|
+
* The `const`, `let` or `var` of the declaration list that the `,` at
|
|
15664
|
+
* `comma` is in (`let a = 1, b`, also in a `for` header): the nearest one
|
|
15665
|
+
* before it in the same brackets, that no `;` is between.
|
|
15666
|
+
*/
|
|
15667
|
+
listKeyword(comma) {
|
|
15668
|
+
const { code } = this;
|
|
15669
|
+
const floor = this.innermost(comma)?.open ?? -1;
|
|
15670
|
+
for (let i2 = comma - 1; i2 > floor; i2--) {
|
|
15671
|
+
const c = code.charAt(i2);
|
|
15672
|
+
if (c === ";") return void 0;
|
|
15673
|
+
const group = CLOSERS[c] ? this.byClose.get(i2) : void 0;
|
|
15674
|
+
if (group) i2 = group.open;
|
|
15675
|
+
else if (isWordChar(c)) {
|
|
15676
|
+
const word = this.wordBefore(i2 + 1);
|
|
15677
|
+
if (DECLARATIONS.has(word.text) && code.charAt(word.start - 1) !== ".") return word;
|
|
15678
|
+
i2 = word.start;
|
|
15679
|
+
}
|
|
15680
|
+
}
|
|
15681
|
+
}
|
|
15682
|
+
nameEnd(at3) {
|
|
15683
|
+
let end = at3;
|
|
15684
|
+
while (isWordChar(this.code.charAt(end))) end++;
|
|
15685
|
+
return end;
|
|
15686
|
+
}
|
|
15687
|
+
/**
|
|
15688
|
+
* A name in a pattern (`const { x } = …`) or a parameter list; or one a
|
|
15689
|
+
* pattern assigns to (`({ x } = …)`).
|
|
15690
|
+
*/
|
|
15691
|
+
patternAt(at3, before, after) {
|
|
15692
|
+
const { code } = this;
|
|
15693
|
+
const inner = this.innermost(at3);
|
|
15694
|
+
if (!inner || !BEFORE_BINDING[inner.kind].includes(code.charAt(before))) return;
|
|
15695
|
+
if (inner.kind === "{" && code.charAt(after) === ":") return void 0;
|
|
15696
|
+
let pattern;
|
|
15697
|
+
for (let group = inner; group; group = group.parent) {
|
|
15698
|
+
if (group.kind === "(") {
|
|
15699
|
+
const scope = NOT_PARAMETERS.has(this.ownerWord(group)) ? void 0 : this.bodyAfter(group.close);
|
|
15700
|
+
return scope ? {
|
|
15701
|
+
scope,
|
|
15702
|
+
at: at3,
|
|
15703
|
+
ordered: false
|
|
15704
|
+
} : this.patternWriteAt(at3, pattern);
|
|
15705
|
+
}
|
|
15706
|
+
pattern = group;
|
|
15707
|
+
const open = this.backFrom(group.open);
|
|
15708
|
+
const word = code.charAt(open) === "," ? this.listKeyword(open) : this.wordBefore(open + 1);
|
|
15709
|
+
if (word && DECLARATIONS.has(word.text)) return {
|
|
15710
|
+
scope: this.declaredIn(word),
|
|
15711
|
+
at: at3,
|
|
15712
|
+
ordered: true
|
|
15713
|
+
};
|
|
15714
|
+
if (!"({[,:".includes(code.charAt(open))) break;
|
|
15715
|
+
}
|
|
15716
|
+
return this.patternWriteAt(at3, pattern);
|
|
15717
|
+
}
|
|
15718
|
+
/** `[x] = …`, `({ x } = …)`, `for ({ x } of …)`: a name that is assigned to. */
|
|
15719
|
+
patternWriteAt(at3, pattern) {
|
|
15720
|
+
if (!pattern) return void 0;
|
|
15721
|
+
const { code } = this;
|
|
15722
|
+
const open = this.backFrom(pattern.open);
|
|
15723
|
+
if (/[\w$)\]]/.test(code.charAt(open))) return void 0;
|
|
15724
|
+
const next = this.forward(pattern.close + 1);
|
|
15725
|
+
return pattern.parent?.kind === "(" && this.ownerWord(pattern.parent) === "for" && /^(?:of|in)(?![\w$])/.test(code.slice(next)) || this.isWriteOperator(next) ? {
|
|
15726
|
+
scope: this.top,
|
|
15727
|
+
at: at3,
|
|
15728
|
+
ordered: true,
|
|
15729
|
+
write: true
|
|
15730
|
+
} : void 0;
|
|
15731
|
+
}
|
|
15732
|
+
/** `x => …`. */
|
|
15733
|
+
arrowParameterAt(at3, after) {
|
|
15734
|
+
return this.code.startsWith("=>", after) ? {
|
|
15735
|
+
scope: this.arrowBody(after + 2),
|
|
15736
|
+
at: at3,
|
|
15737
|
+
ordered: false
|
|
15738
|
+
} : void 0;
|
|
15739
|
+
}
|
|
15740
|
+
/** Whether an assignment, `++` or `--` operator is at `index`. */
|
|
15741
|
+
isWriteOperator(index) {
|
|
15742
|
+
WRITE_RE.lastIndex = index;
|
|
15743
|
+
return WRITE_RE.test(this.code);
|
|
15744
|
+
}
|
|
15745
|
+
/**
|
|
15746
|
+
* `x = …`, `x += …`, `x++`, `for (x of …)`, and the writes to what it
|
|
15747
|
+
* holds that change the config it is (`x.name = …`, `delete x.name`,
|
|
15748
|
+
* `x.parameters.push(…)`, `Object.assign(x, …)`): a value not known.
|
|
15749
|
+
*/
|
|
15750
|
+
writeAt(at3, before, after, properties) {
|
|
15751
|
+
const { code } = this;
|
|
15752
|
+
if (this.isClassBody(this.innermost(at3))) return void 0;
|
|
15753
|
+
const { keys, end } = this.memberChain(after);
|
|
15754
|
+
const written2 = ["++", "--"].includes(code.slice(before - 1, before + 1)) || this.isWriteOperator(end) || keys.length > 0 && (this.wordBefore(before + 1).text === "delete" || keys.length > 1 && code.charAt(end) === "(" && MUTATORS.has(keys[keys.length - 1])) || keys.length === 0 && this.isForTarget(before, end) || keys.length === 0 && this.isMutatedArgument(before, end);
|
|
15755
|
+
const first = keys[0];
|
|
15756
|
+
if (!written2 || first && !properties.has(first)) return void 0;
|
|
15757
|
+
return {
|
|
15758
|
+
scope: this.top,
|
|
15759
|
+
at: at3,
|
|
15760
|
+
ordered: true,
|
|
15761
|
+
write: true
|
|
15762
|
+
};
|
|
15763
|
+
}
|
|
15764
|
+
/** Whether the group is the body of a class: its members are its own. */
|
|
15765
|
+
isClassBody(group) {
|
|
15766
|
+
if (group?.kind !== "{") return false;
|
|
15767
|
+
let start = group.open;
|
|
15768
|
+
while (start > 0 && !"{};".includes(this.code.charAt(start - 1))) start--;
|
|
15769
|
+
return /(?<![\w$.])class(?![\w$])/.test(this.code.slice(start, group.open));
|
|
15770
|
+
}
|
|
15771
|
+
/**
|
|
15772
|
+
* The properties read from a name at `from` (`.a.b[c]`, a key is null if
|
|
15773
|
+
* computed), and where the chain ends.
|
|
15774
|
+
*/
|
|
15775
|
+
memberChain(from) {
|
|
15776
|
+
const { code } = this;
|
|
15777
|
+
const keys = [];
|
|
15778
|
+
let end = from;
|
|
15779
|
+
for (; ; ) {
|
|
15780
|
+
let i2 = end;
|
|
15781
|
+
if (code.startsWith("?.", i2)) i2 += 2;
|
|
15782
|
+
else if (code.charAt(i2) === "." && code.charAt(i2 + 1) !== ".") i2++;
|
|
15783
|
+
else if (code.charAt(i2) !== "[") break;
|
|
15784
|
+
i2 = this.forward(i2);
|
|
15785
|
+
const bracket = code.charAt(i2) === "[" ? this.byOpen.get(i2) : void 0;
|
|
15786
|
+
const key = bracket ? "" : this.wordAt(i2);
|
|
15787
|
+
if (!bracket && !key) break;
|
|
15788
|
+
keys.push(bracket ? null : key);
|
|
15789
|
+
end = this.forward(bracket ? bracket.close + 1 : i2 + key.length);
|
|
15790
|
+
}
|
|
15791
|
+
return {
|
|
15792
|
+
keys,
|
|
15793
|
+
end
|
|
15794
|
+
};
|
|
15795
|
+
}
|
|
15796
|
+
/** `for (x of …)`: the name is assigned each item. */
|
|
15797
|
+
isForTarget(before, end) {
|
|
15798
|
+
const group = this.byOpen.get(before);
|
|
15799
|
+
return group?.kind === "(" && this.ownerWord(group) === "for" && /^(?:of|in)(?![\w$])/.test(this.code.slice(end));
|
|
15800
|
+
}
|
|
15801
|
+
/** `Object.assign(x, …)` and the like: the name is the first argument. */
|
|
15802
|
+
isMutatedArgument(before, end) {
|
|
15803
|
+
const group = this.byOpen.get(before);
|
|
15804
|
+
return group?.kind === "(" && ",)".includes(this.code.charAt(end)) && MUTATING_CALL_RE.test(this.code.slice(0, group.open));
|
|
15805
|
+
}
|
|
15806
|
+
};
|
|
14588
15807
|
CALL_RE = /(?<![\w$])defineMacro\s*\(\s*/g;
|
|
14589
15808
|
IDENTIFIER_ARGUMENT_RE = /^([A-Za-z_$][\w$]*)\s*[,)]/;
|
|
14590
15809
|
WORD_RE = /[A-Za-z_]+/y;
|
|
15810
|
+
MODIFIER_RE = /^(?:get|set|async)?$/;
|
|
15811
|
+
KEY_START_RE = /[\w$'"[.*]/;
|
|
15812
|
+
CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
15813
|
+
"name",
|
|
15814
|
+
"block",
|
|
15815
|
+
"subMacros",
|
|
15816
|
+
"parameters",
|
|
15817
|
+
"interpolate",
|
|
15818
|
+
"storeVar",
|
|
15819
|
+
"merged",
|
|
15820
|
+
"description"
|
|
15821
|
+
]);
|
|
14591
15822
|
ConfigReader = class extends Reader {
|
|
14592
15823
|
constructor(..._args) {
|
|
14593
15824
|
super(..._args);
|
|
@@ -14686,18 +15917,47 @@ var init_story_variables = __esm({
|
|
|
14686
15917
|
}
|
|
14687
15918
|
record() {
|
|
14688
15919
|
const props = /* @__PURE__ */ new Map();
|
|
14689
|
-
return this.elements("}", () => {
|
|
14690
|
-
const key = this.key();
|
|
14691
|
-
this.space();
|
|
14692
|
-
if (key !== void 0 && this.src.charAt(this.i) === ":") {
|
|
14693
|
-
this.i++;
|
|
14694
|
-
props.set(key, this.member());
|
|
14695
|
-
} else if (!this.skipMember()) this.fail();
|
|
14696
|
-
}) ? {
|
|
15920
|
+
return this.elements("}", () => this.property(props)) ? {
|
|
14697
15921
|
type: "object",
|
|
14698
15922
|
props
|
|
14699
15923
|
} : void 0;
|
|
14700
15924
|
}
|
|
15925
|
+
/**
|
|
15926
|
+
* A member: what it sets replaces an earlier member of the key. One that is
|
|
15927
|
+
* not a literal (a method, an accessor, a shorthand) sets its key to a
|
|
15928
|
+
* value not known; a spread of an object literal sets the members of it, a
|
|
15929
|
+
* spread of anything else or a computed key can set any key.
|
|
15930
|
+
*/
|
|
15931
|
+
property(props) {
|
|
15932
|
+
const { src } = this;
|
|
15933
|
+
if (src.startsWith("...", this.i)) {
|
|
15934
|
+
this.i += 3;
|
|
15935
|
+
this.space();
|
|
15936
|
+
const spread = src.charAt(this.i) === "{" ? this.record() : void 0;
|
|
15937
|
+
this.space();
|
|
15938
|
+
if (spread?.type === "object" && this.atElementEnd()) {
|
|
15939
|
+
for (const [key, value] of spread.props) props.set(key, value);
|
|
15940
|
+
return;
|
|
15941
|
+
}
|
|
15942
|
+
props.clear();
|
|
15943
|
+
} else {
|
|
15944
|
+
let key = this.key();
|
|
15945
|
+
this.space();
|
|
15946
|
+
if (key !== void 0 && src.charAt(this.i) === ":") {
|
|
15947
|
+
this.i++;
|
|
15948
|
+
props.set(key, this.member());
|
|
15949
|
+
return;
|
|
15950
|
+
}
|
|
15951
|
+
if (MODIFIER_RE.test(key ?? "") && KEY_START_RE.test(src.charAt(this.i))) {
|
|
15952
|
+
if (src.charAt(this.i) === "*") this.i++;
|
|
15953
|
+
this.space();
|
|
15954
|
+
key = this.key();
|
|
15955
|
+
}
|
|
15956
|
+
if (key === void 0) props.clear();
|
|
15957
|
+
else props.set(key, void 0);
|
|
15958
|
+
}
|
|
15959
|
+
if (!this.skipMember()) this.fail();
|
|
15960
|
+
}
|
|
14701
15961
|
/** Stop reading: the text cannot be skipped through. */
|
|
14702
15962
|
fail() {
|
|
14703
15963
|
this.failed = true;
|
|
@@ -14707,6 +15967,35 @@ var init_story_variables = __esm({
|
|
|
14707
15967
|
booleanOf = (d) => d?.type === "boolean" ? d.value : void 0;
|
|
14708
15968
|
textOf = (d) => stringOf(d)?.value;
|
|
14709
15969
|
stringsOf = (d) => d?.type === "array" ? d.items.flatMap((item) => stringOf(item)?.value ?? []) : [];
|
|
15970
|
+
VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
15971
|
+
"area",
|
|
15972
|
+
"base",
|
|
15973
|
+
"br",
|
|
15974
|
+
"col",
|
|
15975
|
+
"embed",
|
|
15976
|
+
"hr",
|
|
15977
|
+
"img",
|
|
15978
|
+
"input",
|
|
15979
|
+
"link",
|
|
15980
|
+
"meta",
|
|
15981
|
+
"param",
|
|
15982
|
+
"source",
|
|
15983
|
+
"track",
|
|
15984
|
+
"wbr"
|
|
15985
|
+
]);
|
|
15986
|
+
DEFAULT_PRETTIER_OPTIONS = { tabWidth: 2 };
|
|
15987
|
+
SVG_PLACEHOLDERS = (i2) => [`<!--SVG:${i2}-->`];
|
|
15988
|
+
SPINDLE_PLACEHOLDERS = (i2) => [`<!--SP:${i2}-->`, `__SP${i2}__`];
|
|
15989
|
+
DEFAULT_DEDENTING = /* @__PURE__ */ new Set([
|
|
15990
|
+
"else",
|
|
15991
|
+
"elseif",
|
|
15992
|
+
"next",
|
|
15993
|
+
"case",
|
|
15994
|
+
"default"
|
|
15995
|
+
]);
|
|
15996
|
+
WHITESPACE_AS_WRITTEN = /<(?:pre|textarea)[\s>]|white-space\s*:/i;
|
|
15997
|
+
LIST_ITEM_REGEX = /^(?:[-+*]|\d{1,9}[.)])(?:[ \t]|$)/;
|
|
15998
|
+
CODE_FENCE_REGEX = /^(?:`{3,}|~{3,})/;
|
|
14710
15999
|
NOT_MARKUP_TAGS = ["script", "stylesheet"];
|
|
14711
16000
|
}
|
|
14712
16001
|
});
|
|
@@ -14956,48 +16245,56 @@ var init_macro_registry = __esm({
|
|
|
14956
16245
|
"name": "story-title",
|
|
14957
16246
|
"block": false,
|
|
14958
16247
|
"subMacros": [],
|
|
16248
|
+
"interpolate": true,
|
|
14959
16249
|
"source": "builtin"
|
|
14960
16250
|
},
|
|
14961
16251
|
{
|
|
14962
16252
|
"name": "back",
|
|
14963
16253
|
"block": false,
|
|
14964
16254
|
"subMacros": [],
|
|
16255
|
+
"interpolate": true,
|
|
14965
16256
|
"source": "builtin"
|
|
14966
16257
|
},
|
|
14967
16258
|
{
|
|
14968
16259
|
"name": "forward",
|
|
14969
16260
|
"block": false,
|
|
14970
16261
|
"subMacros": [],
|
|
16262
|
+
"interpolate": true,
|
|
14971
16263
|
"source": "builtin"
|
|
14972
16264
|
},
|
|
14973
16265
|
{
|
|
14974
16266
|
"name": "quicksave",
|
|
14975
16267
|
"block": false,
|
|
14976
16268
|
"subMacros": [],
|
|
16269
|
+
"interpolate": true,
|
|
14977
16270
|
"source": "builtin"
|
|
14978
16271
|
},
|
|
14979
16272
|
{
|
|
14980
16273
|
"name": "quickload",
|
|
14981
16274
|
"block": false,
|
|
14982
16275
|
"subMacros": [],
|
|
16276
|
+
"interpolate": true,
|
|
14983
16277
|
"source": "builtin"
|
|
14984
16278
|
},
|
|
14985
16279
|
{
|
|
14986
16280
|
"name": "restart",
|
|
14987
16281
|
"block": false,
|
|
14988
16282
|
"subMacros": [],
|
|
16283
|
+
"interpolate": true,
|
|
14989
16284
|
"source": "builtin"
|
|
14990
16285
|
},
|
|
14991
16286
|
{
|
|
14992
16287
|
"name": "saves",
|
|
14993
16288
|
"block": false,
|
|
14994
16289
|
"subMacros": [],
|
|
16290
|
+
"interpolate": true,
|
|
14995
16291
|
"source": "builtin"
|
|
14996
16292
|
},
|
|
14997
16293
|
{
|
|
14998
16294
|
"name": "settings",
|
|
14999
16295
|
"block": false,
|
|
15000
16296
|
"subMacros": [],
|
|
16297
|
+
"interpolate": true,
|
|
15001
16298
|
"source": "builtin"
|
|
15002
16299
|
},
|
|
15003
16300
|
{
|
|
@@ -15023,12 +16320,14 @@ var init_macro_registry = __esm({
|
|
|
15023
16320
|
"name": "save-manager",
|
|
15024
16321
|
"block": false,
|
|
15025
16322
|
"subMacros": [],
|
|
16323
|
+
"interpolate": true,
|
|
15026
16324
|
"source": "builtin"
|
|
15027
16325
|
},
|
|
15028
16326
|
{
|
|
15029
16327
|
"name": "settings-controls",
|
|
15030
16328
|
"block": false,
|
|
15031
16329
|
"subMacros": [],
|
|
16330
|
+
"interpolate": true,
|
|
15032
16331
|
"source": "builtin"
|
|
15033
16332
|
},
|
|
15034
16333
|
{
|
|
@@ -15054,6 +16353,7 @@ var init_macro_registry = __esm({
|
|
|
15054
16353
|
"name": "nobr",
|
|
15055
16354
|
"block": true,
|
|
15056
16355
|
"subMacros": [],
|
|
16356
|
+
"interpolate": true,
|
|
15057
16357
|
"source": "builtin"
|
|
15058
16358
|
},
|
|
15059
16359
|
{
|
|
@@ -15088,6 +16388,7 @@ var init_macro_registry = __esm({
|
|
|
15088
16388
|
"block": false,
|
|
15089
16389
|
"subMacros": [],
|
|
15090
16390
|
"storeVar": true,
|
|
16391
|
+
"interpolate": true,
|
|
15091
16392
|
"parameters": [
|
|
15092
16393
|
{
|
|
15093
16394
|
"name": "variable",
|
|
@@ -15107,6 +16408,7 @@ var init_macro_registry = __esm({
|
|
|
15107
16408
|
"block": false,
|
|
15108
16409
|
"subMacros": [],
|
|
15109
16410
|
"storeVar": true,
|
|
16411
|
+
"interpolate": true,
|
|
15110
16412
|
"parameters": [
|
|
15111
16413
|
{
|
|
15112
16414
|
"name": "variable",
|
|
@@ -15126,6 +16428,7 @@ var init_macro_registry = __esm({
|
|
|
15126
16428
|
"block": false,
|
|
15127
16429
|
"subMacros": [],
|
|
15128
16430
|
"storeVar": true,
|
|
16431
|
+
"interpolate": true,
|
|
15129
16432
|
"parameters": [
|
|
15130
16433
|
{
|
|
15131
16434
|
"name": "variable",
|
|
@@ -15145,6 +16448,7 @@ var init_macro_registry = __esm({
|
|
|
15145
16448
|
"block": false,
|
|
15146
16449
|
"subMacros": [],
|
|
15147
16450
|
"storeVar": true,
|
|
16451
|
+
"interpolate": true,
|
|
15148
16452
|
"parameters": [
|
|
15149
16453
|
{
|
|
15150
16454
|
"name": "variable",
|
|
@@ -15164,6 +16468,7 @@ var init_macro_registry = __esm({
|
|
|
15164
16468
|
"block": false,
|
|
15165
16469
|
"subMacros": [],
|
|
15166
16470
|
"storeVar": true,
|
|
16471
|
+
"interpolate": true,
|
|
15167
16472
|
"parameters": [
|
|
15168
16473
|
{
|
|
15169
16474
|
"name": "variable",
|
|
@@ -15191,6 +16496,7 @@ var init_macro_registry = __esm({
|
|
|
15191
16496
|
"option"
|
|
15192
16497
|
],
|
|
15193
16498
|
"storeVar": true,
|
|
16499
|
+
"interpolate": true,
|
|
15194
16500
|
"parameters": [
|
|
15195
16501
|
{
|
|
15196
16502
|
"name": "variable",
|
|
@@ -15205,6 +16511,7 @@ var init_macro_registry = __esm({
|
|
|
15205
16511
|
"block": true,
|
|
15206
16512
|
"subMacros": [],
|
|
15207
16513
|
"storeVar": true,
|
|
16514
|
+
"interpolate": true,
|
|
15208
16515
|
"parameters": [
|
|
15209
16516
|
{
|
|
15210
16517
|
"name": "variable",
|
|
@@ -15218,6 +16525,7 @@ var init_macro_registry = __esm({
|
|
|
15218
16525
|
"name": "span",
|
|
15219
16526
|
"block": true,
|
|
15220
16527
|
"subMacros": [],
|
|
16528
|
+
"interpolate": true,
|
|
15221
16529
|
"source": "builtin"
|
|
15222
16530
|
},
|
|
15223
16531
|
{
|
|
@@ -23929,7 +25237,7 @@ var MINIMUM_SPINDLE_VERSION, DEFAULT_TARGET;
|
|
|
23929
25237
|
var init_spindle_version = __esm({
|
|
23930
25238
|
"src/core/workspace/spindle-version.ts"() {
|
|
23931
25239
|
"use strict";
|
|
23932
|
-
MINIMUM_SPINDLE_VERSION = "0.
|
|
25240
|
+
MINIMUM_SPINDLE_VERSION = "0.60.0";
|
|
23933
25241
|
DEFAULT_TARGET = { version: void 0, source: "default", supported: true };
|
|
23934
25242
|
}
|
|
23935
25243
|
});
|
|
@@ -26955,322 +28263,31 @@ function headerTags(header) {
|
|
|
26955
28263
|
const unescaped = header.replace(/\\./g, "ec");
|
|
26956
28264
|
return (unescaped.match(/\[[^\]]*\]/g) ?? []).flatMap((t) => t.slice(1, -1).split(/\s+/));
|
|
26957
28265
|
}
|
|
26958
|
-
|
|
26959
|
-
const lines = body.split("\n");
|
|
26960
|
-
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
26961
|
-
lines.pop();
|
|
26962
|
-
}
|
|
26963
|
-
if (lines.length === 0) return [];
|
|
26964
|
-
const regions = [];
|
|
26965
|
-
let i2 = 0;
|
|
26966
|
-
while (i2 < lines.length) {
|
|
26967
|
-
const line = lines[i2];
|
|
26968
|
-
const trimmed2 = line.trim();
|
|
26969
|
-
if (/^<script(\s|>)/i.test(trimmed2)) {
|
|
26970
|
-
const scriptLines = [line];
|
|
26971
|
-
i2++;
|
|
26972
|
-
if (/<\/script\s*>/i.test(line)) {
|
|
26973
|
-
regions.push({ type: "script", lines: scriptLines });
|
|
26974
|
-
continue;
|
|
26975
|
-
}
|
|
26976
|
-
while (i2 < lines.length && !/<\/script>/i.test(lines[i2])) {
|
|
26977
|
-
scriptLines.push(lines[i2]);
|
|
26978
|
-
i2++;
|
|
26979
|
-
}
|
|
26980
|
-
if (i2 < lines.length) {
|
|
26981
|
-
scriptLines.push(lines[i2]);
|
|
26982
|
-
i2++;
|
|
26983
|
-
}
|
|
26984
|
-
regions.push({ type: "script", lines: scriptLines });
|
|
26985
|
-
continue;
|
|
26986
|
-
}
|
|
26987
|
-
if (/^<svg(\s|>)/i.test(trimmed2)) {
|
|
26988
|
-
const svgLines = [line];
|
|
26989
|
-
i2++;
|
|
26990
|
-
while (i2 < lines.length && !/<\/svg>/i.test(lines[i2])) {
|
|
26991
|
-
svgLines.push(lines[i2]);
|
|
26992
|
-
i2++;
|
|
26993
|
-
}
|
|
26994
|
-
if (i2 < lines.length) {
|
|
26995
|
-
svgLines.push(lines[i2]);
|
|
26996
|
-
i2++;
|
|
26997
|
-
}
|
|
26998
|
-
regions.push({ type: "svg", lines: svgLines });
|
|
26999
|
-
continue;
|
|
27000
|
-
}
|
|
27001
|
-
if (/^<([a-zA-Z][\w-]*)/.test(trimmed2)) {
|
|
27002
|
-
const tagMatch = trimmed2.match(/^<([a-zA-Z][\w-]*)/);
|
|
27003
|
-
const tagName = tagMatch[1].toLowerCase();
|
|
27004
|
-
if (VOID_ELEMENTS.has(tagName) && !lines[i2 + 1]?.trim().startsWith("<")) {
|
|
27005
|
-
pushSpindleLine(regions, line);
|
|
27006
|
-
i2++;
|
|
27007
|
-
continue;
|
|
27008
|
-
}
|
|
27009
|
-
const selfClosing = new RegExp(`</${tagName}\\s*>`, "i");
|
|
27010
|
-
if (selfClosing.test(trimmed2)) {
|
|
27011
|
-
pushSpindleLine(regions, line);
|
|
27012
|
-
i2++;
|
|
27013
|
-
continue;
|
|
27014
|
-
}
|
|
27015
|
-
const htmlLines = [line];
|
|
27016
|
-
let depth = 1;
|
|
27017
|
-
i2++;
|
|
27018
|
-
while (i2 < lines.length && depth > 0) {
|
|
27019
|
-
htmlLines.push(lines[i2]);
|
|
27020
|
-
const opens = (lines[i2].match(new RegExp(`<${tagName}(?:[\\s>]|$)`, "gi")) ?? []).length;
|
|
27021
|
-
const closes2 = (lines[i2].match(new RegExp(`</${tagName}\\s*>`, "gi")) ?? []).length;
|
|
27022
|
-
depth += opens - closes2;
|
|
27023
|
-
i2++;
|
|
27024
|
-
}
|
|
27025
|
-
regions.push({ type: "html", lines: htmlLines });
|
|
27026
|
-
continue;
|
|
27027
|
-
}
|
|
27028
|
-
pushSpindleLine(regions, line);
|
|
27029
|
-
i2++;
|
|
27030
|
-
}
|
|
27031
|
-
return regions;
|
|
27032
|
-
}
|
|
27033
|
-
function pushSpindleLine(regions, line) {
|
|
27034
|
-
const last2 = regions[regions.length - 1];
|
|
27035
|
-
if (last2?.type === "spindle") {
|
|
27036
|
-
last2.lines.push(line);
|
|
27037
|
-
} else {
|
|
27038
|
-
regions.push({ type: "spindle", lines: [line] });
|
|
27039
|
-
}
|
|
27040
|
-
}
|
|
27041
|
-
var PASSAGE_HEADER_REGEX, VOID_ELEMENTS;
|
|
28266
|
+
var PASSAGE_HEADER_REGEX;
|
|
27042
28267
|
var init_segment = __esm({
|
|
27043
28268
|
"src/plugins/format/segment.ts"() {
|
|
27044
28269
|
"use strict";
|
|
27045
28270
|
init_passage_parser();
|
|
27046
28271
|
PASSAGE_HEADER_REGEX = /^::\s+/;
|
|
27047
|
-
VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
27048
|
-
"area",
|
|
27049
|
-
"base",
|
|
27050
|
-
"br",
|
|
27051
|
-
"col",
|
|
27052
|
-
"embed",
|
|
27053
|
-
"hr",
|
|
27054
|
-
"img",
|
|
27055
|
-
"input",
|
|
27056
|
-
"link",
|
|
27057
|
-
"meta",
|
|
27058
|
-
"param",
|
|
27059
|
-
"source",
|
|
27060
|
-
"track",
|
|
27061
|
-
"wbr"
|
|
27062
|
-
]);
|
|
27063
28272
|
}
|
|
27064
28273
|
});
|
|
27065
28274
|
|
|
27066
28275
|
// src/plugins/format/prettier-bridge.ts
|
|
27067
28276
|
async function loadPrettier() {
|
|
27068
|
-
|
|
27069
|
-
|
|
27070
|
-
|
|
27071
|
-
prettier = await import("prettier");
|
|
27072
|
-
} catch {
|
|
27073
|
-
prettier = null;
|
|
27074
|
-
}
|
|
27075
|
-
return prettier;
|
|
27076
|
-
}
|
|
27077
|
-
async function getBaseConfig() {
|
|
27078
|
-
const p = await loadPrettier();
|
|
27079
|
-
if (!p) return {};
|
|
28277
|
+
prettier ??= import("prettier").catch(() => null);
|
|
28278
|
+
const p = await prettier;
|
|
28279
|
+
if (!p) return void 0;
|
|
27080
28280
|
try {
|
|
27081
28281
|
const resolved = await p.resolveConfig(process.cwd());
|
|
27082
|
-
return { tabWidth: 2, ...resolved ?? {} };
|
|
27083
|
-
} catch {
|
|
27084
|
-
return { tabWidth: 2 };
|
|
27085
|
-
}
|
|
27086
|
-
}
|
|
27087
|
-
async function formatJS(code) {
|
|
27088
|
-
const p = await loadPrettier();
|
|
27089
|
-
if (!p) return code;
|
|
27090
|
-
try {
|
|
27091
|
-
const config2 = await getBaseConfig();
|
|
27092
|
-
return await p.format(code, { ...config2, parser: "babel" });
|
|
27093
|
-
} catch {
|
|
27094
|
-
return code;
|
|
27095
|
-
}
|
|
27096
|
-
}
|
|
27097
|
-
async function formatCSS(code) {
|
|
27098
|
-
const p = await loadPrettier();
|
|
27099
|
-
if (!p) return code;
|
|
27100
|
-
try {
|
|
27101
|
-
const config2 = await getBaseConfig();
|
|
27102
|
-
return await p.format(code, { ...config2, parser: "css" });
|
|
27103
|
-
} catch {
|
|
27104
|
-
return code;
|
|
27105
|
-
}
|
|
27106
|
-
}
|
|
27107
|
-
async function formatHTML(code) {
|
|
27108
|
-
const p = await loadPrettier();
|
|
27109
|
-
if (!p) return code;
|
|
27110
|
-
try {
|
|
27111
|
-
const config2 = await getBaseConfig();
|
|
27112
|
-
return await p.format(code, {
|
|
27113
|
-
...config2,
|
|
27114
|
-
parser: "html",
|
|
27115
|
-
htmlWhitespaceSensitivity: "ignore"
|
|
27116
|
-
});
|
|
28282
|
+
return { prettier: p, options: { tabWidth: 2, ...resolved ?? {} } };
|
|
27117
28283
|
} catch {
|
|
27118
|
-
return
|
|
28284
|
+
return { prettier: p, options: { tabWidth: 2 } };
|
|
27119
28285
|
}
|
|
27120
28286
|
}
|
|
27121
|
-
var prettier
|
|
28287
|
+
var prettier;
|
|
27122
28288
|
var init_prettier_bridge = __esm({
|
|
27123
28289
|
"src/plugins/format/prettier-bridge.ts"() {
|
|
27124
28290
|
"use strict";
|
|
27125
|
-
prettier = null;
|
|
27126
|
-
prettierLoaded = false;
|
|
27127
|
-
}
|
|
27128
|
-
});
|
|
27129
|
-
|
|
27130
|
-
// src/plugins/format/placeholders.ts
|
|
27131
|
-
function scanSpindleMarkup(text2) {
|
|
27132
|
-
const tokens2 = [];
|
|
27133
|
-
const tags = [];
|
|
27134
|
-
const doBlocks = [];
|
|
27135
|
-
let open;
|
|
27136
|
-
const push = (t, inAttribute) => {
|
|
27137
|
-
const match = { start: t.start, end: t.end, token: text2.slice(t.start, t.end) };
|
|
27138
|
-
if (inAttribute) match.inAttribute = true;
|
|
27139
|
-
tokens2.push(match);
|
|
27140
|
-
};
|
|
27141
|
-
for (const t of tokenizeMarkupTolerant(text2).tokens) {
|
|
27142
|
-
if (t.type === "html") {
|
|
27143
|
-
tags.push({ start: t.start, end: t.end });
|
|
27144
|
-
for (const attribute of t.attributeSpans) {
|
|
27145
|
-
if (attribute.valueStart === void 0 || attribute.valueEnd === void 0) continue;
|
|
27146
|
-
const value = text2.slice(attribute.valueStart, attribute.valueEnd);
|
|
27147
|
-
if (!value.includes("{")) continue;
|
|
27148
|
-
for (const inner of tokenizeMarkupTolerant(value, { text: true }).tokens) {
|
|
27149
|
-
if (inner.type === "macro" || inner.type === "variable" || inner.type === "expression") {
|
|
27150
|
-
push({ start: attribute.valueStart + inner.start, end: attribute.valueStart + inner.end }, true);
|
|
27151
|
-
}
|
|
27152
|
-
}
|
|
27153
|
-
}
|
|
27154
|
-
} else if (t.type !== "text") {
|
|
27155
|
-
if (t.type === "macro" && t.name === "do") {
|
|
27156
|
-
if (!t.isClose) open = t;
|
|
27157
|
-
else if (open) {
|
|
27158
|
-
doBlocks.push({ start: open.start, end: t.end, bodyStart: open.end, bodyEnd: t.start });
|
|
27159
|
-
open = void 0;
|
|
27160
|
-
}
|
|
27161
|
-
}
|
|
27162
|
-
push(t);
|
|
27163
|
-
}
|
|
27164
|
-
}
|
|
27165
|
-
return { tokens: tokens2, tags, doBlocks };
|
|
27166
|
-
}
|
|
27167
|
-
function multilineJsLiterals(code) {
|
|
27168
|
-
const spans = [];
|
|
27169
|
-
let skipUntil = 0;
|
|
27170
|
-
lexJs(code, {
|
|
27171
|
-
literal(text2, index, nesting) {
|
|
27172
|
-
if (nesting > 0 || index < skipUntil) return;
|
|
27173
|
-
const quote = text2[0];
|
|
27174
|
-
if (quote === "`") {
|
|
27175
|
-
skipUntil = lexTemplate(code, index);
|
|
27176
|
-
if (code.slice(index, skipUntil).includes("\n")) spans.push([index, skipUntil]);
|
|
27177
|
-
} else if ((quote === '"' || quote === "'") && text2.includes("\n")) {
|
|
27178
|
-
spans.push([index, index + text2.length]);
|
|
27179
|
-
}
|
|
27180
|
-
}
|
|
27181
|
-
}, "statements");
|
|
27182
|
-
return spans;
|
|
27183
|
-
}
|
|
27184
|
-
function lineHasTag(tags, start, end) {
|
|
27185
|
-
return tags.some((tag) => tag.start < end && tag.end > start);
|
|
27186
|
-
}
|
|
27187
|
-
function replaceSvgBlocks(html) {
|
|
27188
|
-
const tokens2 = [];
|
|
27189
|
-
const result = html.replace(/<svg[\s>][\s\S]*?<\/svg>/gi, (match) => {
|
|
27190
|
-
const idx = tokens2.length;
|
|
27191
|
-
tokens2.push(match);
|
|
27192
|
-
return `<!--SVG:${idx}-->`;
|
|
27193
|
-
});
|
|
27194
|
-
return { text: result, tokens: tokens2 };
|
|
27195
|
-
}
|
|
27196
|
-
function restoreSvgBlocks(text2, tokens2) {
|
|
27197
|
-
let result = text2;
|
|
27198
|
-
for (let i2 = 0; i2 < tokens2.length; i2++) {
|
|
27199
|
-
result = result.replace(`<!--SVG:${i2}-->`, () => tokens2[i2]);
|
|
27200
|
-
}
|
|
27201
|
-
return result;
|
|
27202
|
-
}
|
|
27203
|
-
function replaceSpindleTokens(html) {
|
|
27204
|
-
const { tokens: found, tags, doBlocks } = scanSpindleMarkup(html);
|
|
27205
|
-
const units = [];
|
|
27206
|
-
let doIndex = 0;
|
|
27207
|
-
for (const m of found) {
|
|
27208
|
-
while (doIndex < doBlocks.length && doBlocks[doIndex].end <= m.start) {
|
|
27209
|
-
const block = doBlocks[doIndex++];
|
|
27210
|
-
units.push({ start: block.start, end: block.end, token: html.slice(block.start, block.end) });
|
|
27211
|
-
}
|
|
27212
|
-
if (doBlocks[doIndex] && m.start >= doBlocks[doIndex].start) continue;
|
|
27213
|
-
units.push(m);
|
|
27214
|
-
}
|
|
27215
|
-
for (; doIndex < doBlocks.length; doIndex++) {
|
|
27216
|
-
const block = doBlocks[doIndex];
|
|
27217
|
-
units.push({ start: block.start, end: block.end, token: html.slice(block.start, block.end) });
|
|
27218
|
-
}
|
|
27219
|
-
units.sort((a, b) => a.start - b.start);
|
|
27220
|
-
const tokens2 = [];
|
|
27221
|
-
const resultLines = [];
|
|
27222
|
-
let unit = 0;
|
|
27223
|
-
let lineStart = 0;
|
|
27224
|
-
while (lineStart <= html.length) {
|
|
27225
|
-
let lineEnd = lineStart;
|
|
27226
|
-
const lineUnits = [];
|
|
27227
|
-
for (; ; ) {
|
|
27228
|
-
while (unit < units.length && units[unit].end <= lineEnd) unit++;
|
|
27229
|
-
const inside = units[unit] && units[unit].start <= lineEnd ? units[unit] : void 0;
|
|
27230
|
-
if (inside) {
|
|
27231
|
-
lineUnits.push(inside);
|
|
27232
|
-
lineEnd = inside.end;
|
|
27233
|
-
unit++;
|
|
27234
|
-
continue;
|
|
27235
|
-
}
|
|
27236
|
-
if (lineEnd >= html.length || html[lineEnd] === "\n") break;
|
|
27237
|
-
lineEnd++;
|
|
27238
|
-
}
|
|
27239
|
-
const line = html.slice(lineStart, lineEnd);
|
|
27240
|
-
const indent = line.match(/^(\s*)/)?.[1] ?? "";
|
|
27241
|
-
if (lineUnits.length === 0) {
|
|
27242
|
-
resultLines.push(line);
|
|
27243
|
-
} else if (!lineHasTag(tags, lineStart, lineEnd)) {
|
|
27244
|
-
const idx = tokens2.length;
|
|
27245
|
-
tokens2.push(line.trim());
|
|
27246
|
-
resultLines.push(`${indent}<!--SP:${idx}-->`);
|
|
27247
|
-
} else {
|
|
27248
|
-
let replaced = "";
|
|
27249
|
-
let last2 = lineStart;
|
|
27250
|
-
for (const u of lineUnits) {
|
|
27251
|
-
const idx = tokens2.length;
|
|
27252
|
-
tokens2.push(u.token);
|
|
27253
|
-
replaced += html.slice(last2, u.start) + (u.inAttribute ? `__SP${idx}__` : `<!--SP:${idx}-->`);
|
|
27254
|
-
last2 = u.end;
|
|
27255
|
-
}
|
|
27256
|
-
resultLines.push(replaced + html.slice(last2, lineEnd));
|
|
27257
|
-
}
|
|
27258
|
-
lineStart = lineEnd + 1;
|
|
27259
|
-
}
|
|
27260
|
-
return { text: resultLines.join("\n"), tokens: tokens2 };
|
|
27261
|
-
}
|
|
27262
|
-
function restoreSpindleTokens(text2, tokens2) {
|
|
27263
|
-
let result = text2;
|
|
27264
|
-
for (let i2 = 0; i2 < tokens2.length; i2++) {
|
|
27265
|
-
result = result.replace(`<!--SP:${i2}-->`, () => tokens2[i2]);
|
|
27266
|
-
result = result.replace(`__SP${i2}__`, () => tokens2[i2]);
|
|
27267
|
-
}
|
|
27268
|
-
return result;
|
|
27269
|
-
}
|
|
27270
|
-
var init_placeholders = __esm({
|
|
27271
|
-
"src/plugins/format/placeholders.ts"() {
|
|
27272
|
-
"use strict";
|
|
27273
|
-
init_tooling();
|
|
27274
28291
|
}
|
|
27275
28292
|
});
|
|
27276
28293
|
|
|
@@ -27288,50 +28305,22 @@ function buildDefaultIsBlock(text2) {
|
|
|
27288
28305
|
}
|
|
27289
28306
|
async function formatDocument(text2, options) {
|
|
27290
28307
|
if (text2.charCodeAt(0) === 65279) return "\uFEFF" + await formatDocument(text2.slice(1), options);
|
|
27291
|
-
const eol =
|
|
27292
|
-
const output = await
|
|
28308
|
+
const eol = dominantEol2(text2);
|
|
28309
|
+
const output = await formatLf2(text2.replace(/\r\n/g, "\n"), options);
|
|
27293
28310
|
return eol === "\r\n" ? output.replace(/\n/g, "\r\n") : output;
|
|
27294
28311
|
}
|
|
27295
|
-
function
|
|
28312
|
+
function dominantEol2(text2) {
|
|
27296
28313
|
const crlf = (text2.match(/\r\n/g) ?? []).length;
|
|
27297
28314
|
const lf = (text2.match(/\n/g) ?? []).length - crlf;
|
|
27298
28315
|
if (crlf !== lf) return crlf > lf ? "\r\n" : "\n";
|
|
27299
28316
|
return text2.indexOf("\r\n") !== -1 && text2.indexOf("\r\n") < text2.indexOf("\n") ? "\r\n" : "\n";
|
|
27300
28317
|
}
|
|
27301
|
-
function
|
|
27302
|
-
for (let code = 57344; code <= 63743; code++) {
|
|
27303
|
-
const ch = String.fromCharCode(code);
|
|
27304
|
-
if (!text2.includes(ch)) return ch;
|
|
27305
|
-
}
|
|
27306
|
-
throw new Error("no free private-use character for the newline stand-in");
|
|
27307
|
-
}
|
|
27308
|
-
function protectMultilineTokens(body, sentinel) {
|
|
27309
|
-
const { tokens: tokens2, doBlocks } = scanSpindleMarkup(body);
|
|
27310
|
-
const spans = [];
|
|
27311
|
-
for (const m of tokens2) {
|
|
27312
|
-
if (m.token.includes("\n")) spans.push([m.start, m.end]);
|
|
27313
|
-
}
|
|
27314
|
-
for (const block of doBlocks) {
|
|
27315
|
-
for (const [a, b] of multilineJsLiterals(body.slice(block.bodyStart, block.bodyEnd))) {
|
|
27316
|
-
spans.push([block.bodyStart + a, block.bodyStart + b]);
|
|
27317
|
-
}
|
|
27318
|
-
}
|
|
27319
|
-
spans.sort((x2, y) => x2[0] - y[0]);
|
|
27320
|
-
let out = "";
|
|
27321
|
-
let last2 = 0;
|
|
27322
|
-
for (const [a, b] of spans) {
|
|
27323
|
-
out += body.slice(last2, a) + body.slice(a, b).replaceAll("\n", sentinel);
|
|
27324
|
-
last2 = b;
|
|
27325
|
-
}
|
|
27326
|
-
return out + body.slice(last2);
|
|
27327
|
-
}
|
|
27328
|
-
async function formatLf(text2, options) {
|
|
28318
|
+
async function formatLf2(text2, options) {
|
|
27329
28319
|
const isBlock = options?.isBlock ?? buildDefaultIsBlock(text2);
|
|
27330
|
-
const
|
|
28320
|
+
const isDedentingSubMacro = options?.isDedentingSubMacro ?? ((name) => DEFAULT_DEDENTING2.has(name.toLowerCase()));
|
|
28321
|
+
const prettier2 = await loadPrettier();
|
|
27331
28322
|
const passages = splitPassages(text2);
|
|
27332
|
-
const sentinel = newlineSentinel(text2);
|
|
27333
28323
|
const resultLines = [];
|
|
27334
|
-
const hardBreakLines = /* @__PURE__ */ new Set();
|
|
27335
28324
|
for (let pi2 = 0; pi2 < passages.length; pi2++) {
|
|
27336
28325
|
const passage = passages[pi2];
|
|
27337
28326
|
if (pi2 > 0 && passage.header) {
|
|
@@ -27344,226 +28333,24 @@ async function formatLf(text2, options) {
|
|
|
27344
28333
|
}
|
|
27345
28334
|
if (passage.header) {
|
|
27346
28335
|
const header = PASSAGE_HEADER_REGEX2.test(passage.header) ? normalizePassageHeader(passage.header) : passage.header;
|
|
27347
|
-
resultLines.push(header);
|
|
27348
|
-
}
|
|
27349
|
-
|
|
27350
|
-
|
|
27351
|
-
|
|
27352
|
-
|
|
27353
|
-
|
|
27354
|
-
|
|
27355
|
-
|
|
27356
|
-
|
|
27357
|
-
|
|
27358
|
-
|
|
27359
|
-
}
|
|
27360
|
-
const regions = segmentRegions(protectMultilineTokens(passage.body, sentinel));
|
|
27361
|
-
for (const region of regions) {
|
|
27362
|
-
if (region.type !== "spindle") {
|
|
27363
|
-
region.lines = region.lines.map((l) => l.replaceAll(sentinel, "\n"));
|
|
27364
|
-
}
|
|
27365
|
-
if (region.type === "script") {
|
|
27366
|
-
if (region.lines.length === 1) {
|
|
27367
|
-
resultLines.push(region.lines[0]);
|
|
27368
|
-
continue;
|
|
27369
|
-
}
|
|
27370
|
-
const firstLine = region.lines[0];
|
|
27371
|
-
const lastLine = region.lines[region.lines.length - 1];
|
|
27372
|
-
const innerLines = region.lines.slice(1, region.lines.length - 1);
|
|
27373
|
-
const innerCode = innerLines.join("\n");
|
|
27374
|
-
const formatted = await formatJS(innerCode.trim());
|
|
27375
|
-
resultLines.push(firstLine);
|
|
27376
|
-
if (formatted.trim()) {
|
|
27377
|
-
for (const fLine of formatted.trim().split("\n")) {
|
|
27378
|
-
resultLines.push(" " + fLine);
|
|
27379
|
-
}
|
|
27380
|
-
}
|
|
27381
|
-
resultLines.push(lastLine);
|
|
27382
|
-
continue;
|
|
27383
|
-
}
|
|
27384
|
-
if (region.type === "svg") {
|
|
27385
|
-
resultLines.push(...region.lines);
|
|
27386
|
-
continue;
|
|
27387
|
-
}
|
|
27388
|
-
if (region.type === "html") {
|
|
27389
|
-
const htmlText = region.lines.join("\n");
|
|
27390
|
-
const { text: svgPlaceholdered, tokens: svgTokens } = replaceSvgBlocks(htmlText);
|
|
27391
|
-
const { text: placeholdered, tokens: tokens2 } = replaceSpindleTokens(svgPlaceholdered);
|
|
27392
|
-
const formatted = await formatHTML(placeholdered);
|
|
27393
|
-
const restoredSpindle = restoreSpindleTokens(formatted.trim(), tokens2.map((t) => t.replaceAll("\n", sentinel)));
|
|
27394
|
-
const restored = restoreSvgBlocks(restoredSpindle, svgTokens);
|
|
27395
|
-
for (const fLine of restored.split("\n")) {
|
|
27396
|
-
resultLines.push(fLine);
|
|
27397
|
-
}
|
|
27398
|
-
continue;
|
|
27399
|
-
}
|
|
27400
|
-
let indented = indentMacros(region.lines, isBlock, isDedenting);
|
|
27401
|
-
if (options?.maxLineLength) {
|
|
27402
|
-
indented = wrapLines(indented, options.maxLineLength);
|
|
27403
|
-
}
|
|
27404
|
-
for (const line of indented) {
|
|
27405
|
-
if (line.endsWith(" ")) hardBreakLines.add(resultLines.length);
|
|
27406
|
-
resultLines.push(line);
|
|
27407
|
-
}
|
|
27408
|
-
}
|
|
27409
|
-
}
|
|
27410
|
-
let output = resultLines.map((l, i2) => hardBreakLines.has(i2) ? l : l.replace(/\s+$/, "")).join("\n");
|
|
27411
|
-
output = output.replace(/\n*$/, "\n");
|
|
27412
|
-
return output.replaceAll(sentinel, "\n");
|
|
27413
|
-
}
|
|
27414
|
-
function indentMacros(lines, isBlock, isDedenting) {
|
|
27415
|
-
const macrosOnLine = macroTokensByLine(lines);
|
|
27416
|
-
const bodies = [{ openLine: -1, minCol: Infinity, keepRelative: false }];
|
|
27417
|
-
const stack = [0];
|
|
27418
|
-
const info = [];
|
|
27419
|
-
const openBody = (line) => {
|
|
27420
|
-
bodies.push({ openLine: line, minCol: Infinity, keepRelative: false });
|
|
27421
|
-
stack.push(bodies.length - 1);
|
|
27422
|
-
};
|
|
27423
|
-
const closeBody = () => stack.length > 1 ? stack.pop() : void 0;
|
|
27424
|
-
const addLine = (col, text2) => {
|
|
27425
|
-
const body = bodies[stack[stack.length - 1]];
|
|
27426
|
-
body.minCol = Math.min(body.minCol, col);
|
|
27427
|
-
if (LIST_ITEM_REGEX.test(text2) || CODE_FENCE_REGEX.test(text2)) body.keepRelative = true;
|
|
27428
|
-
info.push({ body: stack[stack.length - 1], col, text: text2 });
|
|
27429
|
-
};
|
|
27430
|
-
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
27431
|
-
const trimmed2 = lines[i2].trim();
|
|
27432
|
-
if (trimmed2 === "") {
|
|
27433
|
-
info.push(null);
|
|
27434
|
-
continue;
|
|
27435
|
-
}
|
|
27436
|
-
const col = indentColumn(lines[i2]);
|
|
27437
|
-
const lead = lines[i2].length - lines[i2].trimStart().length;
|
|
27438
|
-
const [first, ...rest] = macrosOnLine[i2];
|
|
27439
|
-
const startsWithMacro = first !== void 0 && first.start === lead;
|
|
27440
|
-
if (startsWithMacro && !first.isClose && isDedenting(first.name)) {
|
|
27441
|
-
const closed2 = closeBody();
|
|
27442
|
-
if (closed2 === void 0) addLine(col, trimmed2);
|
|
27443
|
-
else info.push({ body: stack[stack.length - 1], closes: closed2, col, text: trimmed2 });
|
|
27444
|
-
openBody(i2);
|
|
27445
|
-
continue;
|
|
27446
|
-
}
|
|
27447
|
-
const closed = startsWithMacro && first.isClose ? closeBody() : void 0;
|
|
27448
|
-
if (closed === void 0) addLine(col, trimmed2);
|
|
27449
|
-
else info.push({ body: stack[stack.length - 1], closes: closed, col, text: trimmed2 });
|
|
27450
|
-
if (startsWithMacro && !first.isClose && isBlock(first.name)) {
|
|
27451
|
-
openBody(i2);
|
|
27452
|
-
}
|
|
27453
|
-
for (const macro of startsWithMacro ? rest : macrosOnLine[i2]) {
|
|
27454
|
-
if (macro.isClose && macro.start > lead) closeBody();
|
|
27455
|
-
}
|
|
27456
|
-
}
|
|
27457
|
-
const outCol = [];
|
|
27458
|
-
const result = [];
|
|
27459
|
-
for (let i2 = 0; i2 < info.length; i2++) {
|
|
27460
|
-
const line = info[i2];
|
|
27461
|
-
if (!line) {
|
|
27462
|
-
outCol.push(0);
|
|
27463
|
-
result.push("");
|
|
27464
|
-
continue;
|
|
27465
|
-
}
|
|
27466
|
-
let col;
|
|
27467
|
-
if (line.closes !== void 0) {
|
|
27468
|
-
col = outCol[bodies[line.closes].openLine];
|
|
27469
|
-
} else {
|
|
27470
|
-
const body = bodies[line.body];
|
|
27471
|
-
const isRoot = body.openLine === -1;
|
|
27472
|
-
const base = isRoot ? 0 : outCol[body.openLine] + 2;
|
|
27473
|
-
col = base + (body.keepRelative ? line.col - (isRoot ? 0 : body.minCol) : 0);
|
|
27474
|
-
}
|
|
27475
|
-
outCol.push(col);
|
|
27476
|
-
const hardBreak = / {2,}$/.test(lines[i2]) && info[i2 + 1] ? " " : "";
|
|
27477
|
-
result.push(" ".repeat(col) + line.text + hardBreak);
|
|
27478
|
-
}
|
|
27479
|
-
return result;
|
|
27480
|
-
}
|
|
27481
|
-
function macroTokensByLine(lines) {
|
|
27482
|
-
const byLine = lines.map(() => []);
|
|
27483
|
-
const starts = [];
|
|
27484
|
-
let offset2 = 0;
|
|
27485
|
-
for (const line2 of lines) {
|
|
27486
|
-
starts.push(offset2);
|
|
27487
|
-
offset2 += line2.length + 1;
|
|
27488
|
-
}
|
|
27489
|
-
let line = 0;
|
|
27490
|
-
for (const token of tokenizeMarkupTolerant(lines.join("\n")).tokens) {
|
|
27491
|
-
if (token.type !== "macro") continue;
|
|
27492
|
-
while (line + 1 < lines.length && starts[line + 1] <= token.start) line++;
|
|
27493
|
-
byLine[line].push({ ...token, start: token.start - starts[line], end: token.end - starts[line] });
|
|
27494
|
-
}
|
|
27495
|
-
return byLine;
|
|
27496
|
-
}
|
|
27497
|
-
function indentColumn(line) {
|
|
27498
|
-
let col = 0;
|
|
27499
|
-
for (const ch of line) {
|
|
27500
|
-
if (ch === " ") col++;
|
|
27501
|
-
else if (ch === " ") col += 4 - col % 4;
|
|
27502
|
-
else break;
|
|
28336
|
+
resultLines.push(header.replace(/\s+$/, ""));
|
|
28337
|
+
}
|
|
28338
|
+
if (passage.body === "") continue;
|
|
28339
|
+
const body = await formatPassage(passage.body, {
|
|
28340
|
+
kind: classifyPassage(passage.header),
|
|
28341
|
+
prettier: prettier2?.prettier,
|
|
28342
|
+
prettierOptions: prettier2?.options,
|
|
28343
|
+
isBlock,
|
|
28344
|
+
isDedentingSubMacro,
|
|
28345
|
+
maxLineLength: options?.maxLineLength
|
|
28346
|
+
});
|
|
28347
|
+
resultLines.push(body.replace(/\n$/, ""));
|
|
27503
28348
|
}
|
|
27504
|
-
return
|
|
28349
|
+
return resultLines.join("\n").replace(/\n*$/, "\n");
|
|
27505
28350
|
}
|
|
27506
28351
|
async function formatRange(text2, _range, options) {
|
|
27507
28352
|
return formatDocument(text2, options);
|
|
27508
28353
|
}
|
|
27509
|
-
function wrapLines(lines, maxLen) {
|
|
27510
|
-
const result = [];
|
|
27511
|
-
for (const line of lines) {
|
|
27512
|
-
if (line.length <= maxLen) {
|
|
27513
|
-
result.push(line);
|
|
27514
|
-
continue;
|
|
27515
|
-
}
|
|
27516
|
-
const trimmed2 = line.trim();
|
|
27517
|
-
if (trimmed2 === "" || /^::/.test(trimmed2) || /^\{[\/#.]/.test(trimmed2) || // closing/opening-only macro lines
|
|
27518
|
-
/^\[\[/.test(trimmed2) || // links
|
|
27519
|
-
/^\{choice\b/.test(trimmed2) || // choice macros
|
|
27520
|
-
/^\{choices\b/.test(trimmed2)) {
|
|
27521
|
-
result.push(line);
|
|
27522
|
-
continue;
|
|
27523
|
-
}
|
|
27524
|
-
const indentMatch = line.match(/^(\s*)/);
|
|
27525
|
-
const indent = indentMatch ? indentMatch[1] : "";
|
|
27526
|
-
const wrapped = wordWrap(trimmed2, maxLen, indent);
|
|
27527
|
-
if (line.endsWith(" ")) wrapped[wrapped.length - 1] += " ";
|
|
27528
|
-
result.push(...wrapped);
|
|
27529
|
-
}
|
|
27530
|
-
return result;
|
|
27531
|
-
}
|
|
27532
|
-
function wordWrap(text2, maxLen, indent) {
|
|
27533
|
-
const lines = [];
|
|
27534
|
-
const inToken = new Array(text2.length).fill(false);
|
|
27535
|
-
for (const token of tokenizeMarkupTolerant(text2).tokens) {
|
|
27536
|
-
if (token.type === "text" || token.type === "html") continue;
|
|
27537
|
-
inToken.fill(true, token.start, token.end);
|
|
27538
|
-
}
|
|
27539
|
-
const room = maxLen - indent.length;
|
|
27540
|
-
let pos = 0;
|
|
27541
|
-
while (pos < text2.length) {
|
|
27542
|
-
if (text2.length - pos <= room) {
|
|
27543
|
-
lines.push(indent + text2.slice(pos));
|
|
27544
|
-
break;
|
|
27545
|
-
}
|
|
27546
|
-
let breakIdx = -1;
|
|
27547
|
-
for (let i2 = pos + 1; i2 < text2.length && i2 - pos <= room; i2++) {
|
|
27548
|
-
if (text2[i2] === " " && !inToken[i2]) breakIdx = i2;
|
|
27549
|
-
}
|
|
27550
|
-
if (breakIdx === -1) {
|
|
27551
|
-
for (let i2 = pos + room + 1; i2 < text2.length; i2++) {
|
|
27552
|
-
if (text2[i2] === " " && !inToken[i2]) {
|
|
27553
|
-
breakIdx = i2;
|
|
27554
|
-
break;
|
|
27555
|
-
}
|
|
27556
|
-
}
|
|
27557
|
-
}
|
|
27558
|
-
if (breakIdx === -1) {
|
|
27559
|
-
lines.push(indent + text2.slice(pos));
|
|
27560
|
-
break;
|
|
27561
|
-
}
|
|
27562
|
-
lines.push(indent + text2.slice(pos, breakIdx));
|
|
27563
|
-
pos = breakIdx + 1;
|
|
27564
|
-
}
|
|
27565
|
-
return lines;
|
|
27566
|
-
}
|
|
27567
28354
|
function normalizePassageHeader(line) {
|
|
27568
28355
|
const headerMatch = line.match(/^::\s+(.*)/);
|
|
27569
28356
|
if (!headerMatch) return line;
|
|
@@ -27584,19 +28371,16 @@ function normalizePassageHeader(line) {
|
|
|
27584
28371
|
}
|
|
27585
28372
|
return `:: ${name}${suffix}`;
|
|
27586
28373
|
}
|
|
27587
|
-
var PASSAGE_HEADER_REGEX2,
|
|
28374
|
+
var PASSAGE_HEADER_REGEX2, DEFAULT_DEDENTING2, BUILTIN_CONTAINERS, formatPlugin;
|
|
27588
28375
|
var init_format = __esm({
|
|
27589
28376
|
"src/plugins/format.ts"() {
|
|
27590
28377
|
"use strict";
|
|
27591
28378
|
init_tooling();
|
|
27592
28379
|
init_segment();
|
|
27593
28380
|
init_prettier_bridge();
|
|
27594
|
-
init_placeholders();
|
|
27595
28381
|
PASSAGE_HEADER_REGEX2 = /^(::)\s+/;
|
|
27596
|
-
|
|
28382
|
+
DEFAULT_DEDENTING2 = /* @__PURE__ */ new Set(["else", "elseif", "next", "case", "default"]);
|
|
27597
28383
|
BUILTIN_CONTAINERS = new Set(builtinMacros.filter((m) => m.block).map((m) => m.name.toLowerCase()));
|
|
27598
|
-
LIST_ITEM_REGEX = /^(?:[-+*]|\d{1,9}[.)])(?:[ \t]|$)/;
|
|
27599
|
-
CODE_FENCE_REGEX = /^(?:`{3,}|~{3,})/;
|
|
27600
28384
|
formatPlugin = {
|
|
27601
28385
|
id: "format",
|
|
27602
28386
|
capabilities: {
|
|
@@ -27607,7 +28391,7 @@ var init_format = __esm({
|
|
|
27607
28391
|
const formatOpts = {
|
|
27608
28392
|
// Block widgets (whose body renders {@children}) are containers too
|
|
27609
28393
|
isBlock: (name) => ctx.workspace.isContainer(name),
|
|
27610
|
-
isDedentingSubMacro: (name) =>
|
|
28394
|
+
isDedentingSubMacro: (name) => DEFAULT_DEDENTING2.has(name.toLowerCase())
|
|
27611
28395
|
};
|
|
27612
28396
|
ctx.connection.onDocumentFormatting(async (params) => {
|
|
27613
28397
|
const text2 = ctx.workspace.documents.getText(params.textDocument.uri);
|
|
@@ -71918,7 +72702,7 @@ var init_server4 = __esm({
|
|
|
71918
72702
|
|
|
71919
72703
|
// src/bin.ts
|
|
71920
72704
|
var args = process.argv.slice(2);
|
|
71921
|
-
var VERSION = "0.
|
|
72705
|
+
var VERSION = "0.14.0";
|
|
71922
72706
|
var HELP = `spindle-lsp v${VERSION}
|
|
71923
72707
|
Language Server Protocol server for Spindle story format
|
|
71924
72708
|
|