@rohal12/spindle 0.52.9 → 0.54.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/README.md +5 -1
- package/dist/pkg/format.js +1 -1
- package/dist/pkg/headless.js +6484 -2558
- package/dist/pkg/story-variables.js +4009 -940
- package/dist/pkg/tooling.js +13 -1
- package/package.json +6 -1
- package/src/class-registry.ts +252 -250
- package/src/components/App.tsx +2 -0
- package/src/components/Passage.tsx +3 -3
- package/src/components/PassageDialog.tsx +2 -4
- package/src/components/RuntimeErrors.tsx +46 -0
- package/src/components/StoryInterface.tsx +2 -4
- package/src/components/macros/Computed.tsx +5 -2
- package/src/components/macros/Do.tsx +4 -2
- package/src/components/macros/Goto.tsx +13 -3
- package/src/components/macros/Include.tsx +2 -3
- package/src/components/macros/MacroError.tsx +14 -7
- package/src/components/macros/SaveManager.tsx +2 -2
- package/src/components/macros/VarDisplay.tsx +1 -1
- package/src/components/macros/Widget.tsx +5 -33
- package/src/index.tsx +57 -37
- package/src/interpolation.ts +4 -5
- package/src/markup/ast.ts +11 -226
- package/src/markup/code-attributes.ts +3 -3
- package/src/markup/code-end.ts +121 -0
- package/src/markup/parse.ts +118 -0
- package/src/markup/render.tsx +1 -1
- package/src/markup/spindle.d.peggy.ts +24 -0
- package/src/markup/spindle.peggy +463 -0
- package/src/markup/tokens.ts +95 -0
- package/src/markup/validate.ts +219 -0
- package/src/parser.ts +19 -4
- package/src/runtime-errors.ts +65 -0
- package/src/saves/format.ts +199 -0
- package/src/saves/save-manager.ts +45 -63
- package/src/saves/types.ts +71 -88
- package/src/store.ts +167 -87
- package/src/story-init.ts +3 -5
- package/src/story-variables.ts +18 -4
- package/src/structural.ts +266 -57
- package/src/styles.css +45 -0
- package/src/tooling.ts +50 -0
- package/src/types-drift-check.ts +28 -1
- package/src/utils/object-path.ts +13 -12
- package/src/utils/stable-key.ts +2 -1
- package/src/utils/value-kinds.ts +45 -0
- package/src/widgets/widget-def.ts +60 -0
- package/types/index.d.ts +32 -8
- package/types/tooling.d.ts +42 -0
- package/src/markup/tokenizer.ts +0 -1112
|
@@ -1,3 +1,3419 @@
|
|
|
1
|
+
//#region src/markup/spindle.peggy
|
|
2
|
+
var LB = String.fromCharCode(123);
|
|
3
|
+
var RB = String.fromCharCode(125);
|
|
4
|
+
var SIGIL_SCOPES$1 = {
|
|
5
|
+
$: "variable",
|
|
6
|
+
_: "temporary",
|
|
7
|
+
"@": "local",
|
|
8
|
+
"%": "transient"
|
|
9
|
+
};
|
|
10
|
+
var VOID_TAGS = new Set([
|
|
11
|
+
"area",
|
|
12
|
+
"base",
|
|
13
|
+
"br",
|
|
14
|
+
"col",
|
|
15
|
+
"embed",
|
|
16
|
+
"hr",
|
|
17
|
+
"img",
|
|
18
|
+
"input",
|
|
19
|
+
"link",
|
|
20
|
+
"meta",
|
|
21
|
+
"param",
|
|
22
|
+
"source",
|
|
23
|
+
"track",
|
|
24
|
+
"wbr"
|
|
25
|
+
]);
|
|
26
|
+
var BRANCH_PARENT = {
|
|
27
|
+
elseif: "if",
|
|
28
|
+
else: "if",
|
|
29
|
+
case: "switch",
|
|
30
|
+
default: "switch",
|
|
31
|
+
next: "timed"
|
|
32
|
+
};
|
|
33
|
+
var BRANCHING = new Set([
|
|
34
|
+
"if",
|
|
35
|
+
"switch",
|
|
36
|
+
"timed"
|
|
37
|
+
]);
|
|
38
|
+
var LINK_SEPARATORS = [
|
|
39
|
+
["|", false],
|
|
40
|
+
["->", false],
|
|
41
|
+
["<-", true]
|
|
42
|
+
];
|
|
43
|
+
var NO_SELECTORS = {};
|
|
44
|
+
function parseLink(inner) {
|
|
45
|
+
for (const [separator, targetFirst] of LINK_SEPARATORS) {
|
|
46
|
+
const idx = inner.indexOf(separator);
|
|
47
|
+
if (idx === -1) continue;
|
|
48
|
+
const before = inner.slice(0, idx).trim();
|
|
49
|
+
const after = inner.slice(idx + separator.length).trim();
|
|
50
|
+
return targetFirst ? {
|
|
51
|
+
display: after,
|
|
52
|
+
target: before
|
|
53
|
+
} : {
|
|
54
|
+
display: before,
|
|
55
|
+
target: after
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const trimmed = inner.trim();
|
|
59
|
+
return {
|
|
60
|
+
display: trimmed,
|
|
61
|
+
target: trimmed
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function quoteArg(value) {
|
|
65
|
+
return "\"" + value.replace(/[\\"]/g, "\\$&") + "\"";
|
|
66
|
+
}
|
|
67
|
+
function withSelectors(target, from) {
|
|
68
|
+
if (from.className) target.className = from.className;
|
|
69
|
+
if (from.id) target.id = from.id;
|
|
70
|
+
return target;
|
|
71
|
+
}
|
|
72
|
+
function selectorsOf(parts) {
|
|
73
|
+
const classes = [];
|
|
74
|
+
let id = "";
|
|
75
|
+
for (const [prefix, name] of parts) {
|
|
76
|
+
if (!name) continue;
|
|
77
|
+
if (prefix === ".") classes.push(name);
|
|
78
|
+
else id = name;
|
|
79
|
+
}
|
|
80
|
+
return withSelectors({}, {
|
|
81
|
+
className: classes.join(" "),
|
|
82
|
+
id
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/** How a tag reads in an error message. */
|
|
86
|
+
function label(tag) {
|
|
87
|
+
if (tag.lex === "html") return (tag.isClose ? "</" : "<") + tag.tag + ">";
|
|
88
|
+
return LB + (tag.isClose ? "/" : "") + tag.name + RB;
|
|
89
|
+
}
|
|
90
|
+
function closerOf(tag) {
|
|
91
|
+
return tag.lex === "html" ? "</" + tag.tag + ">" : LB + "/" + tag.name + RB;
|
|
92
|
+
}
|
|
93
|
+
function at(loc) {
|
|
94
|
+
return "line " + loc.start.line + ", column " + loc.start.column;
|
|
95
|
+
}
|
|
96
|
+
function sameName(open, close) {
|
|
97
|
+
return open.lex === close.lex && open.lower === close.lower;
|
|
98
|
+
}
|
|
99
|
+
/** A lexeme: what one token of the flat stream holds, with its span. */
|
|
100
|
+
function lexeme(lex, loc, fields) {
|
|
101
|
+
fields.lex = lex;
|
|
102
|
+
fields.start = loc.start.offset;
|
|
103
|
+
fields.end = loc.end.offset;
|
|
104
|
+
fields.loc = loc;
|
|
105
|
+
return fields;
|
|
106
|
+
}
|
|
107
|
+
/** The AST node of a lexeme that stands alone (not a macro or element). */
|
|
108
|
+
function nodeOf(x) {
|
|
109
|
+
switch (x.lex) {
|
|
110
|
+
case "text": return {
|
|
111
|
+
type: "text",
|
|
112
|
+
value: x.value
|
|
113
|
+
};
|
|
114
|
+
case "link": return withSelectors({
|
|
115
|
+
type: "macro",
|
|
116
|
+
name: "link",
|
|
117
|
+
rawArgs: quoteArg(x.display) + " " + quoteArg(x.target),
|
|
118
|
+
children: []
|
|
119
|
+
}, x);
|
|
120
|
+
case "variable": return withSelectors({
|
|
121
|
+
type: "variable",
|
|
122
|
+
name: x.name,
|
|
123
|
+
scope: x.scope
|
|
124
|
+
}, x);
|
|
125
|
+
case "expression": return withSelectors({
|
|
126
|
+
type: "expression",
|
|
127
|
+
expression: x.expression
|
|
128
|
+
}, x);
|
|
129
|
+
default: return x;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/** The token of a lexeme (tokens.ts Token). */
|
|
133
|
+
function tokenOf(x) {
|
|
134
|
+
const span = {
|
|
135
|
+
start: x.start,
|
|
136
|
+
end: x.end
|
|
137
|
+
};
|
|
138
|
+
switch (x.lex) {
|
|
139
|
+
case "text": return {
|
|
140
|
+
type: "text",
|
|
141
|
+
value: x.value,
|
|
142
|
+
...span
|
|
143
|
+
};
|
|
144
|
+
case "link": return withSelectors({
|
|
145
|
+
type: "link",
|
|
146
|
+
display: x.display,
|
|
147
|
+
target: x.target,
|
|
148
|
+
...span
|
|
149
|
+
}, x);
|
|
150
|
+
case "variable": return withSelectors({
|
|
151
|
+
type: "variable",
|
|
152
|
+
name: x.name,
|
|
153
|
+
scope: x.scope,
|
|
154
|
+
...span
|
|
155
|
+
}, x);
|
|
156
|
+
case "expression": return withSelectors({
|
|
157
|
+
type: "expression",
|
|
158
|
+
expression: x.expression,
|
|
159
|
+
...span
|
|
160
|
+
}, x);
|
|
161
|
+
case "macro": return withSelectors({
|
|
162
|
+
type: "macro",
|
|
163
|
+
name: x.name,
|
|
164
|
+
rawArgs: x.rawArgs,
|
|
165
|
+
isClose: x.isClose,
|
|
166
|
+
...span
|
|
167
|
+
}, x);
|
|
168
|
+
case "html": return {
|
|
169
|
+
type: "html",
|
|
170
|
+
tag: x.tag,
|
|
171
|
+
attributes: x.attributes,
|
|
172
|
+
isClose: x.isClose,
|
|
173
|
+
isSelfClose: x.isSelfClose,
|
|
174
|
+
...span
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Flatten items (lexemes, nodes, arrays of them, nulls) and join adjacent
|
|
180
|
+
* text, except escaped braces, which stay a text item of their own.
|
|
181
|
+
*/
|
|
182
|
+
function joinText(items, convert) {
|
|
183
|
+
const out = [];
|
|
184
|
+
let last = null;
|
|
185
|
+
const add = (item) => {
|
|
186
|
+
if (item === null || item === void 0) return;
|
|
187
|
+
if (Array.isArray(item)) return item.forEach(add);
|
|
188
|
+
if (item.lex === "text" && !item.escape && last && last.lex === "text" && !last.escape && last.end === item.start) {
|
|
189
|
+
last.value += item.value;
|
|
190
|
+
last.end = item.end;
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
out.push(item);
|
|
194
|
+
last = item;
|
|
195
|
+
};
|
|
196
|
+
add(items);
|
|
197
|
+
return convert ? out.map(convert) : out;
|
|
198
|
+
}
|
|
199
|
+
var peg$SyntaxError = class extends SyntaxError {
|
|
200
|
+
constructor(message, expected, found, location) {
|
|
201
|
+
super(message);
|
|
202
|
+
this.expected = expected;
|
|
203
|
+
this.found = found;
|
|
204
|
+
this.location = location;
|
|
205
|
+
this.name = "SyntaxError";
|
|
206
|
+
}
|
|
207
|
+
format(sources) {
|
|
208
|
+
let str = "Error: " + this.message;
|
|
209
|
+
if (this.location) {
|
|
210
|
+
let src = null;
|
|
211
|
+
const st = sources.find((s) => s.source === this.location.source);
|
|
212
|
+
if (st) src = st.text.split(/\r\n|\n|\r/g);
|
|
213
|
+
const s = this.location.start;
|
|
214
|
+
const offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
|
|
215
|
+
const loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
|
|
216
|
+
if (src) {
|
|
217
|
+
const e = this.location.end;
|
|
218
|
+
const filler = "".padEnd(offset_s.line.toString().length, " ");
|
|
219
|
+
const line = src[s.line - 1];
|
|
220
|
+
const hatLen = (s.line === e.line ? e.column : line.length + 1) - s.column || 1;
|
|
221
|
+
str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line + "\n" + filler + " | " + "".padEnd(s.column - 1, " ") + "".padEnd(hatLen, "^");
|
|
222
|
+
} else str += "\n at " + loc;
|
|
223
|
+
}
|
|
224
|
+
return str;
|
|
225
|
+
}
|
|
226
|
+
static buildMessage(expected, found) {
|
|
227
|
+
function hex(ch) {
|
|
228
|
+
return ch.codePointAt(0).toString(16).toUpperCase();
|
|
229
|
+
}
|
|
230
|
+
const nonPrintable = Object.prototype.hasOwnProperty.call(RegExp.prototype, "unicode") ? /* @__PURE__ */ new RegExp("[\\p{C}\\p{Mn}\\p{Mc}]", "gu") : null;
|
|
231
|
+
function unicodeEscape(s) {
|
|
232
|
+
if (nonPrintable) return s.replace(nonPrintable, (ch) => "\\u{" + hex(ch) + "}");
|
|
233
|
+
return s;
|
|
234
|
+
}
|
|
235
|
+
function literalEscape(s) {
|
|
236
|
+
return unicodeEscape(s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, (ch) => "\\x0" + hex(ch)).replace(/[\x10-\x1F\x7F-\x9F]/g, (ch) => "\\x" + hex(ch)));
|
|
237
|
+
}
|
|
238
|
+
function classEscape(s) {
|
|
239
|
+
return unicodeEscape(s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, (ch) => "\\x0" + hex(ch)).replace(/[\x10-\x1F\x7F-\x9F]/g, (ch) => "\\x" + hex(ch)));
|
|
240
|
+
}
|
|
241
|
+
const DESCRIBE_EXPECTATION_FNS = {
|
|
242
|
+
literal(expectation) {
|
|
243
|
+
return "\"" + literalEscape(expectation.text) + "\"";
|
|
244
|
+
},
|
|
245
|
+
class(expectation) {
|
|
246
|
+
const escapedParts = expectation.parts.map((part) => Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part));
|
|
247
|
+
return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]" + (expectation.unicode ? "u" : "");
|
|
248
|
+
},
|
|
249
|
+
any() {
|
|
250
|
+
return "any character";
|
|
251
|
+
},
|
|
252
|
+
end() {
|
|
253
|
+
return "end of input";
|
|
254
|
+
},
|
|
255
|
+
other(expectation) {
|
|
256
|
+
return expectation.description;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
function describeExpectation(expectation) {
|
|
260
|
+
return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
|
|
261
|
+
}
|
|
262
|
+
function describeExpected(expected) {
|
|
263
|
+
const descriptions = expected.map(describeExpectation);
|
|
264
|
+
descriptions.sort();
|
|
265
|
+
if (descriptions.length > 0) {
|
|
266
|
+
let j = 1;
|
|
267
|
+
for (let i = 1; i < descriptions.length; i++) if (descriptions[i - 1] !== descriptions[i]) {
|
|
268
|
+
descriptions[j] = descriptions[i];
|
|
269
|
+
j++;
|
|
270
|
+
}
|
|
271
|
+
descriptions.length = j;
|
|
272
|
+
}
|
|
273
|
+
switch (descriptions.length) {
|
|
274
|
+
case 1: return descriptions[0];
|
|
275
|
+
case 2: return descriptions[0] + " or " + descriptions[1];
|
|
276
|
+
default: return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function describeFound(found) {
|
|
280
|
+
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
|
|
281
|
+
}
|
|
282
|
+
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
function peg$parse(input, options) {
|
|
286
|
+
options = options !== void 0 ? options : {};
|
|
287
|
+
const peg$FAILED = {};
|
|
288
|
+
const peg$source = options.grammarSource;
|
|
289
|
+
const peg$startRuleFunctions = {
|
|
290
|
+
Markup: peg$parseMarkup,
|
|
291
|
+
Tokens: peg$parseTokens
|
|
292
|
+
};
|
|
293
|
+
let peg$startRuleFunction = peg$parseMarkup;
|
|
294
|
+
const peg$c0 = "\\";
|
|
295
|
+
const peg$c1 = "{";
|
|
296
|
+
const peg$c2 = "<";
|
|
297
|
+
const peg$c3 = "[";
|
|
298
|
+
const peg$c4 = "[[";
|
|
299
|
+
const peg$c5 = "]]";
|
|
300
|
+
const peg$c6 = " ";
|
|
301
|
+
const peg$c7 = "}";
|
|
302
|
+
const peg$c8 = "/";
|
|
303
|
+
const peg$c9 = ">";
|
|
304
|
+
const peg$c10 = "</";
|
|
305
|
+
const peg$c11 = "=";
|
|
306
|
+
const peg$c12 = "\"";
|
|
307
|
+
const peg$c13 = "'";
|
|
308
|
+
const peg$r0 = /^[^\\{[<]/;
|
|
309
|
+
const peg$r1 = /^[{}]/;
|
|
310
|
+
const peg$r2 = /^[$_@%(!\/a-zA-Z]/;
|
|
311
|
+
const peg$r3 = /^[.#]/;
|
|
312
|
+
const peg$r4 = /^[a-zA-Z0-9_\-]/;
|
|
313
|
+
const peg$r5 = /^[$_@%]/;
|
|
314
|
+
const peg$r6 = /^[a-zA-Z0-9_.]/;
|
|
315
|
+
const peg$r7 = /^[$_@%(!]/;
|
|
316
|
+
const peg$r8 = /^[a-zA-Z]/;
|
|
317
|
+
const peg$r9 = /^[^ \t\n\r\v\f\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF}]/;
|
|
318
|
+
const peg$r10 = /^[\t-\r \/>\xA0\u1680\u2000-\u200A\u2028-\u2029\u202F\u205F\u3000\uFEFF]/;
|
|
319
|
+
const peg$r11 = /^[a-zA-Z0-9\-]/;
|
|
320
|
+
const peg$r12 = /^[\t-\r "'\/<->{}\xA0\u1680\u2000-\u200A\u2028-\u2029\u202F\u205F\u3000\uFEFF]/;
|
|
321
|
+
const peg$r13 = /^[^"]/;
|
|
322
|
+
const peg$r14 = /^[^']/;
|
|
323
|
+
const peg$r15 = /^["']/;
|
|
324
|
+
const peg$r16 = /^[^ \t\n\r\v\f\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF>]/;
|
|
325
|
+
const peg$r17 = /^[ \t\n\r\v\f\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/;
|
|
326
|
+
const peg$e0 = peg$anyExpectation();
|
|
327
|
+
const peg$e1 = peg$classExpectation([
|
|
328
|
+
"\\",
|
|
329
|
+
"{",
|
|
330
|
+
"[",
|
|
331
|
+
"<"
|
|
332
|
+
], true, false, false);
|
|
333
|
+
const peg$e2 = peg$literalExpectation("\\", false);
|
|
334
|
+
const peg$e3 = peg$classExpectation(["{", "}"], false, false, false);
|
|
335
|
+
const peg$e4 = peg$literalExpectation("{", false);
|
|
336
|
+
const peg$e5 = peg$classExpectation([
|
|
337
|
+
"$",
|
|
338
|
+
"_",
|
|
339
|
+
"@",
|
|
340
|
+
"%",
|
|
341
|
+
"(",
|
|
342
|
+
"!",
|
|
343
|
+
"/",
|
|
344
|
+
["a", "z"],
|
|
345
|
+
["A", "Z"]
|
|
346
|
+
], false, false, false);
|
|
347
|
+
const peg$e6 = peg$literalExpectation("<", false);
|
|
348
|
+
const peg$e7 = peg$literalExpectation("[", false);
|
|
349
|
+
const peg$e8 = peg$literalExpectation("[[", false);
|
|
350
|
+
const peg$e9 = peg$literalExpectation("]]", false);
|
|
351
|
+
const peg$e10 = peg$literalExpectation(" ", false);
|
|
352
|
+
const peg$e11 = peg$classExpectation([".", "#"], false, false, false);
|
|
353
|
+
const peg$e12 = peg$classExpectation([
|
|
354
|
+
["a", "z"],
|
|
355
|
+
["A", "Z"],
|
|
356
|
+
["0", "9"],
|
|
357
|
+
"_",
|
|
358
|
+
"-"
|
|
359
|
+
], false, false, false);
|
|
360
|
+
const peg$e13 = peg$classExpectation([
|
|
361
|
+
"$",
|
|
362
|
+
"_",
|
|
363
|
+
"@",
|
|
364
|
+
"%"
|
|
365
|
+
], false, false, false);
|
|
366
|
+
const peg$e14 = peg$classExpectation([
|
|
367
|
+
["a", "z"],
|
|
368
|
+
["A", "Z"],
|
|
369
|
+
["0", "9"],
|
|
370
|
+
"_",
|
|
371
|
+
"."
|
|
372
|
+
], false, false, false);
|
|
373
|
+
const peg$e15 = peg$literalExpectation("}", false);
|
|
374
|
+
const peg$e16 = peg$classExpectation([
|
|
375
|
+
"$",
|
|
376
|
+
"_",
|
|
377
|
+
"@",
|
|
378
|
+
"%",
|
|
379
|
+
"(",
|
|
380
|
+
"!"
|
|
381
|
+
], false, false, false);
|
|
382
|
+
const peg$e17 = peg$literalExpectation("/", false);
|
|
383
|
+
const peg$e18 = peg$classExpectation([["a", "z"], ["A", "Z"]], false, false, false);
|
|
384
|
+
const peg$e19 = peg$classExpectation([
|
|
385
|
+
" ",
|
|
386
|
+
" ",
|
|
387
|
+
"\n",
|
|
388
|
+
"\r",
|
|
389
|
+
"\v",
|
|
390
|
+
"\f",
|
|
391
|
+
"\xA0",
|
|
392
|
+
" ",
|
|
393
|
+
[" ", " "],
|
|
394
|
+
"\u2028",
|
|
395
|
+
"\u2029",
|
|
396
|
+
" ",
|
|
397
|
+
" ",
|
|
398
|
+
" ",
|
|
399
|
+
"",
|
|
400
|
+
"}"
|
|
401
|
+
], true, false, false);
|
|
402
|
+
const peg$e20 = peg$literalExpectation(">", false);
|
|
403
|
+
const peg$e21 = peg$classExpectation([
|
|
404
|
+
[" ", "\r"],
|
|
405
|
+
" ",
|
|
406
|
+
"/",
|
|
407
|
+
">",
|
|
408
|
+
"\xA0",
|
|
409
|
+
" ",
|
|
410
|
+
[" ", " "],
|
|
411
|
+
["\u2028", "\u2029"],
|
|
412
|
+
" ",
|
|
413
|
+
" ",
|
|
414
|
+
" ",
|
|
415
|
+
""
|
|
416
|
+
], false, false, false);
|
|
417
|
+
const peg$e22 = peg$literalExpectation("</", false);
|
|
418
|
+
const peg$e23 = peg$classExpectation([
|
|
419
|
+
["a", "z"],
|
|
420
|
+
["A", "Z"],
|
|
421
|
+
["0", "9"],
|
|
422
|
+
"-"
|
|
423
|
+
], false, false, false);
|
|
424
|
+
const peg$e24 = peg$classExpectation([
|
|
425
|
+
[" ", "\r"],
|
|
426
|
+
" ",
|
|
427
|
+
"\"",
|
|
428
|
+
"'",
|
|
429
|
+
"/",
|
|
430
|
+
["<", ">"],
|
|
431
|
+
"{",
|
|
432
|
+
"}",
|
|
433
|
+
"\xA0",
|
|
434
|
+
" ",
|
|
435
|
+
[" ", " "],
|
|
436
|
+
["\u2028", "\u2029"],
|
|
437
|
+
" ",
|
|
438
|
+
" ",
|
|
439
|
+
" ",
|
|
440
|
+
""
|
|
441
|
+
], false, false, false);
|
|
442
|
+
const peg$e25 = peg$literalExpectation("=", false);
|
|
443
|
+
const peg$e26 = peg$literalExpectation("\"", false);
|
|
444
|
+
const peg$e27 = peg$classExpectation(["\""], true, false, false);
|
|
445
|
+
const peg$e28 = peg$literalExpectation("'", false);
|
|
446
|
+
const peg$e29 = peg$classExpectation(["'"], true, false, false);
|
|
447
|
+
const peg$e30 = peg$classExpectation(["\"", "'"], false, false, false);
|
|
448
|
+
const peg$e31 = peg$classExpectation([
|
|
449
|
+
" ",
|
|
450
|
+
" ",
|
|
451
|
+
"\n",
|
|
452
|
+
"\r",
|
|
453
|
+
"\v",
|
|
454
|
+
"\f",
|
|
455
|
+
"\xA0",
|
|
456
|
+
" ",
|
|
457
|
+
[" ", " "],
|
|
458
|
+
"\u2028",
|
|
459
|
+
"\u2029",
|
|
460
|
+
" ",
|
|
461
|
+
" ",
|
|
462
|
+
" ",
|
|
463
|
+
"",
|
|
464
|
+
">"
|
|
465
|
+
], true, false, false);
|
|
466
|
+
const peg$e32 = peg$classExpectation([
|
|
467
|
+
" ",
|
|
468
|
+
" ",
|
|
469
|
+
"\n",
|
|
470
|
+
"\r",
|
|
471
|
+
"\v",
|
|
472
|
+
"\f",
|
|
473
|
+
"\xA0",
|
|
474
|
+
" ",
|
|
475
|
+
[" ", " "],
|
|
476
|
+
"\u2028",
|
|
477
|
+
"\u2029",
|
|
478
|
+
" ",
|
|
479
|
+
" ",
|
|
480
|
+
" ",
|
|
481
|
+
""
|
|
482
|
+
], false, false, false);
|
|
483
|
+
function peg$f0(nodes) {
|
|
484
|
+
return nodes;
|
|
485
|
+
}
|
|
486
|
+
function peg$f1(tag) {
|
|
487
|
+
fail(label(tag) + " must be directly inside {" + BRANCH_PARENT[tag.lower] + RB, tag.loc);
|
|
488
|
+
}
|
|
489
|
+
function peg$f2(tag) {
|
|
490
|
+
fail(label(tag) + " closes nothing: no " + (tag.lex === "html" ? "<" + tag.tag + ">" : LB + tag.name + RB) + " is open here", tag.loc);
|
|
491
|
+
}
|
|
492
|
+
function peg$f3(items) {
|
|
493
|
+
return joinText(items, nodeOf);
|
|
494
|
+
}
|
|
495
|
+
function peg$f4(tag) {
|
|
496
|
+
return tag.kind === "open";
|
|
497
|
+
}
|
|
498
|
+
function peg$f5(tag) {
|
|
499
|
+
rawName = tag.lower;
|
|
500
|
+
return hooks.isRaw(rawName);
|
|
501
|
+
}
|
|
502
|
+
function peg$f6(tag, b) {
|
|
503
|
+
return b;
|
|
504
|
+
}
|
|
505
|
+
function peg$f7(tag) {
|
|
506
|
+
return hooks.isBlock(tag.lower);
|
|
507
|
+
}
|
|
508
|
+
function peg$f8(tag, b) {
|
|
509
|
+
return b;
|
|
510
|
+
}
|
|
511
|
+
function peg$f9(tag) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
function peg$f10(tag, body) {
|
|
515
|
+
return macroNode(tag, body);
|
|
516
|
+
}
|
|
517
|
+
function peg$f11() {
|
|
518
|
+
return !textMode;
|
|
519
|
+
}
|
|
520
|
+
function peg$f12(open) {
|
|
521
|
+
return !open.isSelfClose;
|
|
522
|
+
}
|
|
523
|
+
function peg$f13(open, b) {
|
|
524
|
+
return b;
|
|
525
|
+
}
|
|
526
|
+
function peg$f14(open, body) {
|
|
527
|
+
const node = {
|
|
528
|
+
type: "html",
|
|
529
|
+
tag: open.tag,
|
|
530
|
+
attributes: open.attributes,
|
|
531
|
+
children: []
|
|
532
|
+
};
|
|
533
|
+
if (body) {
|
|
534
|
+
checkBody(open, body);
|
|
535
|
+
node.children = body.children;
|
|
536
|
+
}
|
|
537
|
+
return node;
|
|
538
|
+
}
|
|
539
|
+
function peg$f15(children, branches, end) {
|
|
540
|
+
return {
|
|
541
|
+
children,
|
|
542
|
+
branches,
|
|
543
|
+
end
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function peg$f16(tag, children) {
|
|
547
|
+
return {
|
|
548
|
+
tag,
|
|
549
|
+
children
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
function peg$f17() {
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
function peg$f18(tag) {
|
|
556
|
+
return tag.kind === "branch";
|
|
557
|
+
}
|
|
558
|
+
function peg$f19(tag) {
|
|
559
|
+
return tag;
|
|
560
|
+
}
|
|
561
|
+
function peg$f20(tag) {
|
|
562
|
+
return tag.kind === "close";
|
|
563
|
+
}
|
|
564
|
+
function peg$f21(tag) {
|
|
565
|
+
return tag;
|
|
566
|
+
}
|
|
567
|
+
function peg$f22() {
|
|
568
|
+
return !textMode;
|
|
569
|
+
}
|
|
570
|
+
function peg$f23(tag) {
|
|
571
|
+
return tag;
|
|
572
|
+
}
|
|
573
|
+
function peg$f24(start) {
|
|
574
|
+
return skipTo(hooks.rawBodyEnd(input, start, rawName));
|
|
575
|
+
}
|
|
576
|
+
function peg$f25(start) {
|
|
577
|
+
return skipEnd - offset();
|
|
578
|
+
}
|
|
579
|
+
function peg$f26(start, body, end) {
|
|
580
|
+
return {
|
|
581
|
+
children: body ? [{
|
|
582
|
+
type: "text",
|
|
583
|
+
value: body
|
|
584
|
+
}] : [],
|
|
585
|
+
branches: [],
|
|
586
|
+
end
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
function peg$f27() {
|
|
590
|
+
return {
|
|
591
|
+
children: [],
|
|
592
|
+
branches: [],
|
|
593
|
+
end: null
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
function peg$f28(items) {
|
|
597
|
+
return joinText(items, tokenOf);
|
|
598
|
+
}
|
|
599
|
+
function peg$f29() {
|
|
600
|
+
return !textMode;
|
|
601
|
+
}
|
|
602
|
+
function peg$f30(tag) {
|
|
603
|
+
return tag;
|
|
604
|
+
}
|
|
605
|
+
function peg$f31() {
|
|
606
|
+
return !textMode;
|
|
607
|
+
}
|
|
608
|
+
function peg$f32(tag) {
|
|
609
|
+
return VOID_TAGS.has(tag.lower) ? null : tag;
|
|
610
|
+
}
|
|
611
|
+
function peg$f33(tag) {
|
|
612
|
+
rawName = tag.lower;
|
|
613
|
+
return tag.kind === "open" && hooks.isRaw(rawName);
|
|
614
|
+
}
|
|
615
|
+
function peg$f34(tag, b) {
|
|
616
|
+
return b;
|
|
617
|
+
}
|
|
618
|
+
function peg$f35(tag, body) {
|
|
619
|
+
return body ? [tag, body] : tag;
|
|
620
|
+
}
|
|
621
|
+
function peg$f36(start) {
|
|
622
|
+
return skipTo(hooks.rawBodyEnd(input, start, rawName));
|
|
623
|
+
}
|
|
624
|
+
function peg$f37(start) {
|
|
625
|
+
return skipEnd - offset();
|
|
626
|
+
}
|
|
627
|
+
function peg$f38(start, body, end) {
|
|
628
|
+
const loc = {
|
|
629
|
+
start: { offset: start },
|
|
630
|
+
end: { offset: start + body.length }
|
|
631
|
+
};
|
|
632
|
+
return [body ? lexeme("text", loc, { value: body }) : null, end];
|
|
633
|
+
}
|
|
634
|
+
function peg$f39() {
|
|
635
|
+
return offset();
|
|
636
|
+
}
|
|
637
|
+
function peg$f40(value) {
|
|
638
|
+
return lexeme("text", location(), { value });
|
|
639
|
+
}
|
|
640
|
+
function peg$f41(bs) {
|
|
641
|
+
return bs.length % 2 === 1;
|
|
642
|
+
}
|
|
643
|
+
function peg$f42(bs, c) {
|
|
644
|
+
return c;
|
|
645
|
+
}
|
|
646
|
+
function peg$f43(bs, brace) {
|
|
647
|
+
const loc = location();
|
|
648
|
+
const next = input.charAt(loc.end.offset);
|
|
649
|
+
if (textMode) {
|
|
650
|
+
if (!brace && next !== LB && next !== RB) return lexeme("text", loc, { value: bs });
|
|
651
|
+
const node = lexeme("text", loc, { value: "\\".repeat(bs.length >> 1) + (brace || "") });
|
|
652
|
+
node.escape = true;
|
|
653
|
+
return node;
|
|
654
|
+
}
|
|
655
|
+
if (!brace) return lexeme("text", loc, { value: bs });
|
|
656
|
+
const before = lexeme("text", loc, { value: bs.slice(1) });
|
|
657
|
+
before.end = loc.end.offset - 2;
|
|
658
|
+
const escaped = lexeme("text", loc, { value: brace });
|
|
659
|
+
escaped.start = loc.end.offset - 2;
|
|
660
|
+
escaped.escape = true;
|
|
661
|
+
return bs.length > 1 ? [before, escaped] : escaped;
|
|
662
|
+
}
|
|
663
|
+
function peg$f44() {
|
|
664
|
+
return lexeme("text", location(), { value: LB });
|
|
665
|
+
}
|
|
666
|
+
function peg$f45() {
|
|
667
|
+
return !textMode;
|
|
668
|
+
}
|
|
669
|
+
function peg$f46() {
|
|
670
|
+
return lexeme("text", location(), { value: "<" });
|
|
671
|
+
}
|
|
672
|
+
function peg$f47() {
|
|
673
|
+
return lexeme("text", location(), { value: "[" });
|
|
674
|
+
}
|
|
675
|
+
function peg$f48() {
|
|
676
|
+
return !textMode;
|
|
677
|
+
}
|
|
678
|
+
function peg$f49(s, inner) {
|
|
679
|
+
return withSelectors(lexeme("link", location(), parseLink(inner)), s);
|
|
680
|
+
}
|
|
681
|
+
function peg$f50() {
|
|
682
|
+
return !textMode;
|
|
683
|
+
}
|
|
684
|
+
function peg$f51() {
|
|
685
|
+
fail("Unclosed link: [[ without ]]", location());
|
|
686
|
+
}
|
|
687
|
+
function peg$f52(parts) {
|
|
688
|
+
return selectorsOf(parts);
|
|
689
|
+
}
|
|
690
|
+
function peg$f53() {
|
|
691
|
+
return NO_SELECTORS;
|
|
692
|
+
}
|
|
693
|
+
function peg$f54(prefix, name) {
|
|
694
|
+
return [prefix, name];
|
|
695
|
+
}
|
|
696
|
+
function peg$f55(s, sigil, name) {
|
|
697
|
+
return withSelectors(lexeme("variable", location(), {
|
|
698
|
+
name,
|
|
699
|
+
scope: SIGIL_SCOPES$1[sigil]
|
|
700
|
+
}), s);
|
|
701
|
+
}
|
|
702
|
+
function peg$f56(s, expression) {
|
|
703
|
+
return withSelectors(lexeme("expression", location(), { expression }), s);
|
|
704
|
+
}
|
|
705
|
+
function peg$f57() {
|
|
706
|
+
fail("Unclosed " + LB + input.substr(location().end.offset, 1) + "…: no } ends it", location());
|
|
707
|
+
}
|
|
708
|
+
function peg$f58(start) {
|
|
709
|
+
return skipTo(hooks.closeBrace(input, start, start));
|
|
710
|
+
}
|
|
711
|
+
function peg$f59(start) {
|
|
712
|
+
return skipEnd - offset();
|
|
713
|
+
}
|
|
714
|
+
function peg$f60(start, code) {
|
|
715
|
+
return code;
|
|
716
|
+
}
|
|
717
|
+
function peg$f61(s, start, close, name, nameEnd) {
|
|
718
|
+
return skipTo(hooks.closeBrace(input, nameEnd, start));
|
|
719
|
+
}
|
|
720
|
+
function peg$f62(s, start, close, name, nameEnd) {
|
|
721
|
+
return skipEnd - offset();
|
|
722
|
+
}
|
|
723
|
+
function peg$f63(s, start, close, name, nameEnd, args) {
|
|
724
|
+
return args;
|
|
725
|
+
}
|
|
726
|
+
function peg$f64(s, start, close, name, nameEnd, tail) {
|
|
727
|
+
const loc = location();
|
|
728
|
+
const lower = name.toLowerCase();
|
|
729
|
+
const tag = lexeme("macro", loc, {
|
|
730
|
+
name,
|
|
731
|
+
lower,
|
|
732
|
+
rawArgs: "",
|
|
733
|
+
isClose: !!close
|
|
734
|
+
});
|
|
735
|
+
if (tail === null) fail("Unclosed " + LB + (close ? "/" : "") + name + "…: no } ends the macro", loc);
|
|
736
|
+
tag.rawArgs = tail.trim();
|
|
737
|
+
if (close) {
|
|
738
|
+
if (s !== NO_SELECTORS) fail("A closing tag takes no selectors: " + label(tag), loc);
|
|
739
|
+
if (tag.rawArgs) fail("A closing tag takes no arguments: " + LB + "/" + name + " " + tag.rawArgs + RB, loc);
|
|
740
|
+
tag.kind = "close";
|
|
741
|
+
} else {
|
|
742
|
+
withSelectors(tag, s);
|
|
743
|
+
tag.kind = Object.prototype.hasOwnProperty.call(BRANCH_PARENT, lower) ? "branch" : "open";
|
|
744
|
+
}
|
|
745
|
+
return tag;
|
|
746
|
+
}
|
|
747
|
+
function peg$f65(s) {
|
|
748
|
+
fail("A closing tag starts with a letter after " + LB + "/", location());
|
|
749
|
+
}
|
|
750
|
+
function peg$f66() {
|
|
751
|
+
return !textMode;
|
|
752
|
+
}
|
|
753
|
+
function peg$f67(tag) {
|
|
754
|
+
return VOID_TAGS.has(tag.lower);
|
|
755
|
+
}
|
|
756
|
+
function peg$f68(tag) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
function peg$f69(tag, list, slash) {
|
|
760
|
+
const lower = tag.toLowerCase();
|
|
761
|
+
return lexeme("html", location(), {
|
|
762
|
+
tag,
|
|
763
|
+
lower,
|
|
764
|
+
attributes: attrs(list),
|
|
765
|
+
isClose: false,
|
|
766
|
+
isSelfClose: !!slash || VOID_TAGS.has(lower)
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
function peg$f70(tag, bad) {
|
|
770
|
+
const c = input.charAt(bad);
|
|
771
|
+
if (!c) fail("Unclosed tag <" + tag + ": no > ends it (write < for a < that starts no tag)", location());
|
|
772
|
+
const at = {
|
|
773
|
+
source: location().source,
|
|
774
|
+
start: {
|
|
775
|
+
offset: bad,
|
|
776
|
+
line: 0,
|
|
777
|
+
column: 0
|
|
778
|
+
},
|
|
779
|
+
end: {
|
|
780
|
+
offset: bad + 1,
|
|
781
|
+
line: 0,
|
|
782
|
+
column: 0
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
fail("Unexpected " + JSON.stringify(c) + " in the tag <" + tag + ">: expected an attribute, or > to end the tag", at);
|
|
786
|
+
}
|
|
787
|
+
function peg$f71(tag) {
|
|
788
|
+
return lexeme("html", location(), {
|
|
789
|
+
tag,
|
|
790
|
+
lower: tag.toLowerCase(),
|
|
791
|
+
attributes: {},
|
|
792
|
+
isClose: true,
|
|
793
|
+
isSelfClose: false
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
function peg$f72(name) {
|
|
797
|
+
attrCode = hooks.isCodeAttribute(name);
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
function peg$f73(name, v) {
|
|
801
|
+
return v;
|
|
802
|
+
}
|
|
803
|
+
function peg$f74(name, value) {
|
|
804
|
+
return [name, value ?? ""];
|
|
805
|
+
}
|
|
806
|
+
function peg$f75(v) {
|
|
807
|
+
return v;
|
|
808
|
+
}
|
|
809
|
+
function peg$f76(v) {
|
|
810
|
+
return v;
|
|
811
|
+
}
|
|
812
|
+
function peg$f77(q) {
|
|
813
|
+
fail("Unclosed attribute value: the " + q + " here has no closing " + q, location());
|
|
814
|
+
}
|
|
815
|
+
function peg$f78() {
|
|
816
|
+
return !attrCode;
|
|
817
|
+
}
|
|
818
|
+
function peg$f79(bs) {
|
|
819
|
+
return bs.length % 2 === 1;
|
|
820
|
+
}
|
|
821
|
+
function peg$f80() {
|
|
822
|
+
return !attrCode;
|
|
823
|
+
}
|
|
824
|
+
function peg$f81(start, nameEnd) {
|
|
825
|
+
return skipTo(hooks.closeBrace(input, nameEnd, start));
|
|
826
|
+
}
|
|
827
|
+
function peg$f82(start, nameEnd) {
|
|
828
|
+
return skipEnd - offset();
|
|
829
|
+
}
|
|
830
|
+
function peg$f83() {
|
|
831
|
+
return !attrCode;
|
|
832
|
+
}
|
|
833
|
+
function peg$f84() {
|
|
834
|
+
return attrCode;
|
|
835
|
+
}
|
|
836
|
+
let peg$currPos = options.peg$currPos | 0;
|
|
837
|
+
let peg$savedPos = peg$currPos;
|
|
838
|
+
const peg$posDetailsCache = [{
|
|
839
|
+
line: 1,
|
|
840
|
+
column: 1
|
|
841
|
+
}];
|
|
842
|
+
let peg$maxFailPos = peg$currPos;
|
|
843
|
+
let peg$maxFailExpected = options.peg$maxFailExpected || [];
|
|
844
|
+
let peg$silentFails = options.peg$silentFails | 0;
|
|
845
|
+
let peg$result;
|
|
846
|
+
if (options.startRule) {
|
|
847
|
+
if (!(options.startRule in peg$startRuleFunctions)) throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
|
848
|
+
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
|
849
|
+
}
|
|
850
|
+
function offset() {
|
|
851
|
+
return peg$savedPos;
|
|
852
|
+
}
|
|
853
|
+
function location() {
|
|
854
|
+
return peg$computeLocation(peg$savedPos, peg$currPos);
|
|
855
|
+
}
|
|
856
|
+
function error(message, location) {
|
|
857
|
+
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos);
|
|
858
|
+
throw peg$buildSimpleError(message, location);
|
|
859
|
+
}
|
|
860
|
+
function peg$getUnicode(pos = peg$currPos) {
|
|
861
|
+
const cp = input.codePointAt(pos);
|
|
862
|
+
if (cp === void 0) return "";
|
|
863
|
+
return String.fromCodePoint(cp);
|
|
864
|
+
}
|
|
865
|
+
function peg$literalExpectation(text, ignoreCase) {
|
|
866
|
+
return {
|
|
867
|
+
type: "literal",
|
|
868
|
+
text,
|
|
869
|
+
ignoreCase
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
function peg$classExpectation(parts, inverted, ignoreCase, unicode) {
|
|
873
|
+
return {
|
|
874
|
+
type: "class",
|
|
875
|
+
parts,
|
|
876
|
+
inverted,
|
|
877
|
+
ignoreCase,
|
|
878
|
+
unicode
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
function peg$anyExpectation() {
|
|
882
|
+
return { type: "any" };
|
|
883
|
+
}
|
|
884
|
+
function peg$endExpectation() {
|
|
885
|
+
return { type: "end" };
|
|
886
|
+
}
|
|
887
|
+
function peg$computePosDetails(pos) {
|
|
888
|
+
let details = peg$posDetailsCache[pos];
|
|
889
|
+
let p;
|
|
890
|
+
if (details) return details;
|
|
891
|
+
else {
|
|
892
|
+
if (pos >= peg$posDetailsCache.length) p = peg$posDetailsCache.length - 1;
|
|
893
|
+
else {
|
|
894
|
+
p = pos;
|
|
895
|
+
while (!peg$posDetailsCache[--p]);
|
|
896
|
+
}
|
|
897
|
+
details = peg$posDetailsCache[p];
|
|
898
|
+
details = {
|
|
899
|
+
line: details.line,
|
|
900
|
+
column: details.column
|
|
901
|
+
};
|
|
902
|
+
while (p < pos) {
|
|
903
|
+
if (input.charCodeAt(p) === 10) {
|
|
904
|
+
details.line++;
|
|
905
|
+
details.column = 1;
|
|
906
|
+
} else details.column++;
|
|
907
|
+
p++;
|
|
908
|
+
}
|
|
909
|
+
peg$posDetailsCache[pos] = details;
|
|
910
|
+
return details;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function peg$computeLocation(startPos, endPos, offset) {
|
|
914
|
+
const startPosDetails = peg$computePosDetails(startPos);
|
|
915
|
+
const endPosDetails = peg$computePosDetails(endPos);
|
|
916
|
+
const res = {
|
|
917
|
+
source: peg$source,
|
|
918
|
+
start: {
|
|
919
|
+
offset: startPos,
|
|
920
|
+
line: startPosDetails.line,
|
|
921
|
+
column: startPosDetails.column
|
|
922
|
+
},
|
|
923
|
+
end: {
|
|
924
|
+
offset: endPos,
|
|
925
|
+
line: endPosDetails.line,
|
|
926
|
+
column: endPosDetails.column
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
if (offset && peg$source && typeof peg$source.offset === "function") {
|
|
930
|
+
res.start = peg$source.offset(res.start);
|
|
931
|
+
res.end = peg$source.offset(res.end);
|
|
932
|
+
}
|
|
933
|
+
return res;
|
|
934
|
+
}
|
|
935
|
+
function peg$fail(expected) {
|
|
936
|
+
if (peg$currPos < peg$maxFailPos) return;
|
|
937
|
+
if (peg$currPos > peg$maxFailPos) {
|
|
938
|
+
peg$maxFailPos = peg$currPos;
|
|
939
|
+
peg$maxFailExpected = [];
|
|
940
|
+
}
|
|
941
|
+
peg$maxFailExpected.push(expected);
|
|
942
|
+
}
|
|
943
|
+
function peg$buildSimpleError(message, location) {
|
|
944
|
+
return new peg$SyntaxError(message, null, null, location);
|
|
945
|
+
}
|
|
946
|
+
function peg$buildStructuredError(expected, found, location) {
|
|
947
|
+
return new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location);
|
|
948
|
+
}
|
|
949
|
+
function peg$parseMarkup() {
|
|
950
|
+
let s0, s1, s2;
|
|
951
|
+
s0 = peg$currPos;
|
|
952
|
+
s1 = peg$parseContent();
|
|
953
|
+
s2 = peg$parseTail();
|
|
954
|
+
if (s2 !== peg$FAILED) {
|
|
955
|
+
peg$savedPos = s0;
|
|
956
|
+
s0 = peg$f0(s1);
|
|
957
|
+
} else {
|
|
958
|
+
peg$currPos = s0;
|
|
959
|
+
s0 = peg$FAILED;
|
|
960
|
+
}
|
|
961
|
+
return s0;
|
|
962
|
+
}
|
|
963
|
+
function peg$parseTail() {
|
|
964
|
+
let s0, s1;
|
|
965
|
+
s0 = peg$currPos;
|
|
966
|
+
peg$silentFails++;
|
|
967
|
+
if (input.length > peg$currPos) {
|
|
968
|
+
s1 = input.charAt(peg$currPos);
|
|
969
|
+
peg$currPos++;
|
|
970
|
+
} else {
|
|
971
|
+
s1 = peg$FAILED;
|
|
972
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
973
|
+
}
|
|
974
|
+
peg$silentFails--;
|
|
975
|
+
if (s1 === peg$FAILED) s0 = void 0;
|
|
976
|
+
else {
|
|
977
|
+
peg$currPos = s0;
|
|
978
|
+
s0 = peg$FAILED;
|
|
979
|
+
}
|
|
980
|
+
if (s0 === peg$FAILED) {
|
|
981
|
+
s0 = peg$currPos;
|
|
982
|
+
s1 = peg$parseBranchTag();
|
|
983
|
+
if (s1 !== peg$FAILED) {
|
|
984
|
+
peg$savedPos = s0;
|
|
985
|
+
s1 = peg$f1(s1);
|
|
986
|
+
}
|
|
987
|
+
s0 = s1;
|
|
988
|
+
if (s0 === peg$FAILED) {
|
|
989
|
+
s0 = peg$currPos;
|
|
990
|
+
s1 = peg$parseCloseTag();
|
|
991
|
+
if (s1 !== peg$FAILED) {
|
|
992
|
+
peg$savedPos = s0;
|
|
993
|
+
s1 = peg$f2(s1);
|
|
994
|
+
}
|
|
995
|
+
s0 = s1;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return s0;
|
|
999
|
+
}
|
|
1000
|
+
function peg$parseContent() {
|
|
1001
|
+
let s0, s1, s2;
|
|
1002
|
+
s0 = peg$currPos;
|
|
1003
|
+
s1 = [];
|
|
1004
|
+
s2 = peg$parseItem();
|
|
1005
|
+
while (s2 !== peg$FAILED) {
|
|
1006
|
+
s1.push(s2);
|
|
1007
|
+
s2 = peg$parseItem();
|
|
1008
|
+
}
|
|
1009
|
+
peg$savedPos = s0;
|
|
1010
|
+
s1 = peg$f3(s1);
|
|
1011
|
+
s0 = s1;
|
|
1012
|
+
return s0;
|
|
1013
|
+
}
|
|
1014
|
+
function peg$parseItem() {
|
|
1015
|
+
let s0;
|
|
1016
|
+
s0 = peg$parseTextRun();
|
|
1017
|
+
if (s0 === peg$FAILED) {
|
|
1018
|
+
s0 = peg$parseEscape();
|
|
1019
|
+
if (s0 === peg$FAILED) {
|
|
1020
|
+
s0 = peg$parseLinkLexeme();
|
|
1021
|
+
if (s0 === peg$FAILED) {
|
|
1022
|
+
s0 = peg$parseHtmlElement();
|
|
1023
|
+
if (s0 === peg$FAILED) {
|
|
1024
|
+
s0 = peg$parseVoidCloser();
|
|
1025
|
+
if (s0 === peg$FAILED) {
|
|
1026
|
+
s0 = peg$parseValue();
|
|
1027
|
+
if (s0 === peg$FAILED) {
|
|
1028
|
+
s0 = peg$parseMacroElement();
|
|
1029
|
+
if (s0 === peg$FAILED) s0 = peg$parseLiteral();
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return s0;
|
|
1037
|
+
}
|
|
1038
|
+
function peg$parseMacroElement() {
|
|
1039
|
+
let s0, s1, s2, s3, s4, s5;
|
|
1040
|
+
s0 = peg$currPos;
|
|
1041
|
+
s1 = peg$parseMacroTag();
|
|
1042
|
+
if (s1 !== peg$FAILED) {
|
|
1043
|
+
peg$savedPos = peg$currPos;
|
|
1044
|
+
s2 = peg$f4(s1);
|
|
1045
|
+
if (s2) s2 = void 0;
|
|
1046
|
+
else s2 = peg$FAILED;
|
|
1047
|
+
if (s2 !== peg$FAILED) {
|
|
1048
|
+
s3 = peg$currPos;
|
|
1049
|
+
peg$savedPos = peg$currPos;
|
|
1050
|
+
s4 = peg$f5(s1);
|
|
1051
|
+
if (s4) s4 = void 0;
|
|
1052
|
+
else s4 = peg$FAILED;
|
|
1053
|
+
if (s4 !== peg$FAILED) {
|
|
1054
|
+
s5 = peg$parseRawBody();
|
|
1055
|
+
if (s5 !== peg$FAILED) {
|
|
1056
|
+
peg$savedPos = s3;
|
|
1057
|
+
s3 = peg$f6(s1, s5);
|
|
1058
|
+
} else {
|
|
1059
|
+
peg$currPos = s3;
|
|
1060
|
+
s3 = peg$FAILED;
|
|
1061
|
+
}
|
|
1062
|
+
} else {
|
|
1063
|
+
peg$currPos = s3;
|
|
1064
|
+
s3 = peg$FAILED;
|
|
1065
|
+
}
|
|
1066
|
+
if (s3 === peg$FAILED) {
|
|
1067
|
+
s3 = peg$currPos;
|
|
1068
|
+
peg$savedPos = peg$currPos;
|
|
1069
|
+
s4 = peg$f7(s1);
|
|
1070
|
+
if (s4) s4 = void 0;
|
|
1071
|
+
else s4 = peg$FAILED;
|
|
1072
|
+
if (s4 !== peg$FAILED) {
|
|
1073
|
+
s5 = peg$parseBlockBody();
|
|
1074
|
+
if (s5 !== peg$FAILED) {
|
|
1075
|
+
peg$savedPos = s3;
|
|
1076
|
+
s3 = peg$f8(s1, s5);
|
|
1077
|
+
} else {
|
|
1078
|
+
peg$currPos = s3;
|
|
1079
|
+
s3 = peg$FAILED;
|
|
1080
|
+
}
|
|
1081
|
+
} else {
|
|
1082
|
+
peg$currPos = s3;
|
|
1083
|
+
s3 = peg$FAILED;
|
|
1084
|
+
}
|
|
1085
|
+
if (s3 === peg$FAILED) {
|
|
1086
|
+
s3 = peg$currPos;
|
|
1087
|
+
s4 = "";
|
|
1088
|
+
peg$savedPos = s3;
|
|
1089
|
+
s4 = peg$f9(s1);
|
|
1090
|
+
s3 = s4;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
if (s3 !== peg$FAILED) {
|
|
1094
|
+
peg$savedPos = s0;
|
|
1095
|
+
s0 = peg$f10(s1, s3);
|
|
1096
|
+
} else {
|
|
1097
|
+
peg$currPos = s0;
|
|
1098
|
+
s0 = peg$FAILED;
|
|
1099
|
+
}
|
|
1100
|
+
} else {
|
|
1101
|
+
peg$currPos = s0;
|
|
1102
|
+
s0 = peg$FAILED;
|
|
1103
|
+
}
|
|
1104
|
+
} else {
|
|
1105
|
+
peg$currPos = s0;
|
|
1106
|
+
s0 = peg$FAILED;
|
|
1107
|
+
}
|
|
1108
|
+
return s0;
|
|
1109
|
+
}
|
|
1110
|
+
function peg$parseHtmlElement() {
|
|
1111
|
+
let s0, s1, s2, s3, s4, s5;
|
|
1112
|
+
s0 = peg$currPos;
|
|
1113
|
+
peg$savedPos = peg$currPos;
|
|
1114
|
+
s1 = peg$f11();
|
|
1115
|
+
if (s1) s1 = void 0;
|
|
1116
|
+
else s1 = peg$FAILED;
|
|
1117
|
+
if (s1 !== peg$FAILED) {
|
|
1118
|
+
s2 = peg$parseHtmlOpen();
|
|
1119
|
+
if (s2 !== peg$FAILED) {
|
|
1120
|
+
s3 = peg$currPos;
|
|
1121
|
+
peg$savedPos = peg$currPos;
|
|
1122
|
+
s4 = peg$f12(s2);
|
|
1123
|
+
if (s4) s4 = void 0;
|
|
1124
|
+
else s4 = peg$FAILED;
|
|
1125
|
+
if (s4 !== peg$FAILED) {
|
|
1126
|
+
s5 = peg$parseBlockBody();
|
|
1127
|
+
if (s5 !== peg$FAILED) {
|
|
1128
|
+
peg$savedPos = s3;
|
|
1129
|
+
s3 = peg$f13(s2, s5);
|
|
1130
|
+
} else {
|
|
1131
|
+
peg$currPos = s3;
|
|
1132
|
+
s3 = peg$FAILED;
|
|
1133
|
+
}
|
|
1134
|
+
} else {
|
|
1135
|
+
peg$currPos = s3;
|
|
1136
|
+
s3 = peg$FAILED;
|
|
1137
|
+
}
|
|
1138
|
+
if (s3 === peg$FAILED) s3 = null;
|
|
1139
|
+
peg$savedPos = s0;
|
|
1140
|
+
s0 = peg$f14(s2, s3);
|
|
1141
|
+
} else {
|
|
1142
|
+
peg$currPos = s0;
|
|
1143
|
+
s0 = peg$FAILED;
|
|
1144
|
+
}
|
|
1145
|
+
} else {
|
|
1146
|
+
peg$currPos = s0;
|
|
1147
|
+
s0 = peg$FAILED;
|
|
1148
|
+
}
|
|
1149
|
+
return s0;
|
|
1150
|
+
}
|
|
1151
|
+
function peg$parseBlockBody() {
|
|
1152
|
+
let s0, s1, s2, s3;
|
|
1153
|
+
s0 = peg$currPos;
|
|
1154
|
+
s1 = peg$parseContent();
|
|
1155
|
+
if (s1 !== peg$FAILED) {
|
|
1156
|
+
s2 = [];
|
|
1157
|
+
s3 = peg$parseBranchPart();
|
|
1158
|
+
while (s3 !== peg$FAILED) {
|
|
1159
|
+
s2.push(s3);
|
|
1160
|
+
s3 = peg$parseBranchPart();
|
|
1161
|
+
}
|
|
1162
|
+
s3 = peg$parseBlockEnd();
|
|
1163
|
+
if (s3 !== peg$FAILED) {
|
|
1164
|
+
peg$savedPos = s0;
|
|
1165
|
+
s0 = peg$f15(s1, s2, s3);
|
|
1166
|
+
} else {
|
|
1167
|
+
peg$currPos = s0;
|
|
1168
|
+
s0 = peg$FAILED;
|
|
1169
|
+
}
|
|
1170
|
+
} else {
|
|
1171
|
+
peg$currPos = s0;
|
|
1172
|
+
s0 = peg$FAILED;
|
|
1173
|
+
}
|
|
1174
|
+
return s0;
|
|
1175
|
+
}
|
|
1176
|
+
function peg$parseBranchPart() {
|
|
1177
|
+
let s0, s1, s2;
|
|
1178
|
+
s0 = peg$currPos;
|
|
1179
|
+
s1 = peg$parseBranchTag();
|
|
1180
|
+
if (s1 !== peg$FAILED) {
|
|
1181
|
+
s2 = peg$parseContent();
|
|
1182
|
+
if (s2 !== peg$FAILED) {
|
|
1183
|
+
peg$savedPos = s0;
|
|
1184
|
+
s0 = peg$f16(s1, s2);
|
|
1185
|
+
} else {
|
|
1186
|
+
peg$currPos = s0;
|
|
1187
|
+
s0 = peg$FAILED;
|
|
1188
|
+
}
|
|
1189
|
+
} else {
|
|
1190
|
+
peg$currPos = s0;
|
|
1191
|
+
s0 = peg$FAILED;
|
|
1192
|
+
}
|
|
1193
|
+
return s0;
|
|
1194
|
+
}
|
|
1195
|
+
function peg$parseBlockEnd() {
|
|
1196
|
+
let s0, s1, s2;
|
|
1197
|
+
s0 = peg$parseCloseTag();
|
|
1198
|
+
if (s0 === peg$FAILED) {
|
|
1199
|
+
s0 = peg$currPos;
|
|
1200
|
+
s1 = peg$currPos;
|
|
1201
|
+
peg$silentFails++;
|
|
1202
|
+
if (input.length > peg$currPos) {
|
|
1203
|
+
s2 = input.charAt(peg$currPos);
|
|
1204
|
+
peg$currPos++;
|
|
1205
|
+
} else {
|
|
1206
|
+
s2 = peg$FAILED;
|
|
1207
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1208
|
+
}
|
|
1209
|
+
peg$silentFails--;
|
|
1210
|
+
if (s2 === peg$FAILED) s1 = void 0;
|
|
1211
|
+
else {
|
|
1212
|
+
peg$currPos = s1;
|
|
1213
|
+
s1 = peg$FAILED;
|
|
1214
|
+
}
|
|
1215
|
+
if (s1 !== peg$FAILED) {
|
|
1216
|
+
peg$savedPos = s0;
|
|
1217
|
+
s1 = peg$f17();
|
|
1218
|
+
}
|
|
1219
|
+
s0 = s1;
|
|
1220
|
+
}
|
|
1221
|
+
return s0;
|
|
1222
|
+
}
|
|
1223
|
+
function peg$parseBranchTag() {
|
|
1224
|
+
let s0, s1, s2;
|
|
1225
|
+
s0 = peg$currPos;
|
|
1226
|
+
s1 = peg$parseMacroTag();
|
|
1227
|
+
if (s1 !== peg$FAILED) {
|
|
1228
|
+
peg$savedPos = peg$currPos;
|
|
1229
|
+
s2 = peg$f18(s1);
|
|
1230
|
+
if (s2) s2 = void 0;
|
|
1231
|
+
else s2 = peg$FAILED;
|
|
1232
|
+
if (s2 !== peg$FAILED) {
|
|
1233
|
+
peg$savedPos = s0;
|
|
1234
|
+
s0 = peg$f19(s1);
|
|
1235
|
+
} else {
|
|
1236
|
+
peg$currPos = s0;
|
|
1237
|
+
s0 = peg$FAILED;
|
|
1238
|
+
}
|
|
1239
|
+
} else {
|
|
1240
|
+
peg$currPos = s0;
|
|
1241
|
+
s0 = peg$FAILED;
|
|
1242
|
+
}
|
|
1243
|
+
return s0;
|
|
1244
|
+
}
|
|
1245
|
+
function peg$parseCloseTag() {
|
|
1246
|
+
let s0, s1, s2;
|
|
1247
|
+
s0 = peg$currPos;
|
|
1248
|
+
s1 = peg$parseMacroTag();
|
|
1249
|
+
if (s1 !== peg$FAILED) {
|
|
1250
|
+
peg$savedPos = peg$currPos;
|
|
1251
|
+
s2 = peg$f20(s1);
|
|
1252
|
+
if (s2) s2 = void 0;
|
|
1253
|
+
else s2 = peg$FAILED;
|
|
1254
|
+
if (s2 !== peg$FAILED) {
|
|
1255
|
+
peg$savedPos = s0;
|
|
1256
|
+
s0 = peg$f21(s1);
|
|
1257
|
+
} else {
|
|
1258
|
+
peg$currPos = s0;
|
|
1259
|
+
s0 = peg$FAILED;
|
|
1260
|
+
}
|
|
1261
|
+
} else {
|
|
1262
|
+
peg$currPos = s0;
|
|
1263
|
+
s0 = peg$FAILED;
|
|
1264
|
+
}
|
|
1265
|
+
if (s0 === peg$FAILED) {
|
|
1266
|
+
s0 = peg$currPos;
|
|
1267
|
+
peg$savedPos = peg$currPos;
|
|
1268
|
+
s1 = peg$f22();
|
|
1269
|
+
if (s1) s1 = void 0;
|
|
1270
|
+
else s1 = peg$FAILED;
|
|
1271
|
+
if (s1 !== peg$FAILED) {
|
|
1272
|
+
s2 = peg$parseHtmlClose();
|
|
1273
|
+
if (s2 !== peg$FAILED) {
|
|
1274
|
+
peg$savedPos = s0;
|
|
1275
|
+
s0 = peg$f23(s2);
|
|
1276
|
+
} else {
|
|
1277
|
+
peg$currPos = s0;
|
|
1278
|
+
s0 = peg$FAILED;
|
|
1279
|
+
}
|
|
1280
|
+
} else {
|
|
1281
|
+
peg$currPos = s0;
|
|
1282
|
+
s0 = peg$FAILED;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
return s0;
|
|
1286
|
+
}
|
|
1287
|
+
function peg$parseRawBody() {
|
|
1288
|
+
let s0, s1, s2, s3, s4, s5, s6, s7;
|
|
1289
|
+
s0 = peg$currPos;
|
|
1290
|
+
s1 = peg$parseHere();
|
|
1291
|
+
peg$savedPos = peg$currPos;
|
|
1292
|
+
s2 = peg$f24(s1);
|
|
1293
|
+
if (s2) s2 = void 0;
|
|
1294
|
+
else s2 = peg$FAILED;
|
|
1295
|
+
if (s2 !== peg$FAILED) {
|
|
1296
|
+
s3 = peg$currPos;
|
|
1297
|
+
s4 = peg$f25(s1);
|
|
1298
|
+
s5 = peg$currPos;
|
|
1299
|
+
s6 = [];
|
|
1300
|
+
if (s6.length >= (s4 | 0)) s7 = peg$FAILED;
|
|
1301
|
+
else if (input.length > peg$currPos) {
|
|
1302
|
+
s7 = input.charAt(peg$currPos);
|
|
1303
|
+
peg$currPos++;
|
|
1304
|
+
} else {
|
|
1305
|
+
s7 = peg$FAILED;
|
|
1306
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1307
|
+
}
|
|
1308
|
+
while (s7 !== peg$FAILED) {
|
|
1309
|
+
s6.push(s7);
|
|
1310
|
+
if (s6.length >= (s4 | 0)) s7 = peg$FAILED;
|
|
1311
|
+
else if (input.length > peg$currPos) {
|
|
1312
|
+
s7 = input.charAt(peg$currPos);
|
|
1313
|
+
peg$currPos++;
|
|
1314
|
+
} else {
|
|
1315
|
+
s7 = peg$FAILED;
|
|
1316
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (s6.length < (s4 | 0)) {
|
|
1320
|
+
peg$currPos = s5;
|
|
1321
|
+
s5 = peg$FAILED;
|
|
1322
|
+
} else s5 = s6;
|
|
1323
|
+
s4 = s5;
|
|
1324
|
+
if (s4 !== peg$FAILED) s3 = input.substring(s3, peg$currPos);
|
|
1325
|
+
else s3 = s4;
|
|
1326
|
+
if (s3 !== peg$FAILED) {
|
|
1327
|
+
s4 = peg$parseCloseTag();
|
|
1328
|
+
if (s4 !== peg$FAILED) {
|
|
1329
|
+
peg$savedPos = s0;
|
|
1330
|
+
s0 = peg$f26(s1, s3, s4);
|
|
1331
|
+
} else {
|
|
1332
|
+
peg$currPos = s0;
|
|
1333
|
+
s0 = peg$FAILED;
|
|
1334
|
+
}
|
|
1335
|
+
} else {
|
|
1336
|
+
peg$currPos = s0;
|
|
1337
|
+
s0 = peg$FAILED;
|
|
1338
|
+
}
|
|
1339
|
+
} else {
|
|
1340
|
+
peg$currPos = s0;
|
|
1341
|
+
s0 = peg$FAILED;
|
|
1342
|
+
}
|
|
1343
|
+
if (s0 === peg$FAILED) {
|
|
1344
|
+
s0 = peg$currPos;
|
|
1345
|
+
s1 = "";
|
|
1346
|
+
peg$savedPos = s0;
|
|
1347
|
+
s1 = peg$f27();
|
|
1348
|
+
s0 = s1;
|
|
1349
|
+
}
|
|
1350
|
+
return s0;
|
|
1351
|
+
}
|
|
1352
|
+
function peg$parseTokens() {
|
|
1353
|
+
let s0, s1, s2;
|
|
1354
|
+
s0 = peg$currPos;
|
|
1355
|
+
s1 = [];
|
|
1356
|
+
s2 = peg$parseTokenItem();
|
|
1357
|
+
while (s2 !== peg$FAILED) {
|
|
1358
|
+
s1.push(s2);
|
|
1359
|
+
s2 = peg$parseTokenItem();
|
|
1360
|
+
}
|
|
1361
|
+
peg$savedPos = s0;
|
|
1362
|
+
s1 = peg$f28(s1);
|
|
1363
|
+
s0 = s1;
|
|
1364
|
+
return s0;
|
|
1365
|
+
}
|
|
1366
|
+
function peg$parseTokenItem() {
|
|
1367
|
+
let s0, s1, s2, s3, s4;
|
|
1368
|
+
s0 = peg$parseTextRun();
|
|
1369
|
+
if (s0 === peg$FAILED) {
|
|
1370
|
+
s0 = peg$parseEscape();
|
|
1371
|
+
if (s0 === peg$FAILED) {
|
|
1372
|
+
s0 = peg$parseLinkLexeme();
|
|
1373
|
+
if (s0 === peg$FAILED) {
|
|
1374
|
+
s0 = peg$currPos;
|
|
1375
|
+
peg$savedPos = peg$currPos;
|
|
1376
|
+
s1 = peg$f29();
|
|
1377
|
+
if (s1) s1 = void 0;
|
|
1378
|
+
else s1 = peg$FAILED;
|
|
1379
|
+
if (s1 !== peg$FAILED) {
|
|
1380
|
+
s2 = peg$parseHtmlOpen();
|
|
1381
|
+
if (s2 !== peg$FAILED) {
|
|
1382
|
+
peg$savedPos = s0;
|
|
1383
|
+
s0 = peg$f30(s2);
|
|
1384
|
+
} else {
|
|
1385
|
+
peg$currPos = s0;
|
|
1386
|
+
s0 = peg$FAILED;
|
|
1387
|
+
}
|
|
1388
|
+
} else {
|
|
1389
|
+
peg$currPos = s0;
|
|
1390
|
+
s0 = peg$FAILED;
|
|
1391
|
+
}
|
|
1392
|
+
if (s0 === peg$FAILED) {
|
|
1393
|
+
s0 = peg$currPos;
|
|
1394
|
+
peg$savedPos = peg$currPos;
|
|
1395
|
+
s1 = peg$f31();
|
|
1396
|
+
if (s1) s1 = void 0;
|
|
1397
|
+
else s1 = peg$FAILED;
|
|
1398
|
+
if (s1 !== peg$FAILED) {
|
|
1399
|
+
s2 = peg$parseHtmlClose();
|
|
1400
|
+
if (s2 !== peg$FAILED) {
|
|
1401
|
+
peg$savedPos = s0;
|
|
1402
|
+
s0 = peg$f32(s2);
|
|
1403
|
+
} else {
|
|
1404
|
+
peg$currPos = s0;
|
|
1405
|
+
s0 = peg$FAILED;
|
|
1406
|
+
}
|
|
1407
|
+
} else {
|
|
1408
|
+
peg$currPos = s0;
|
|
1409
|
+
s0 = peg$FAILED;
|
|
1410
|
+
}
|
|
1411
|
+
if (s0 === peg$FAILED) {
|
|
1412
|
+
s0 = peg$parseValue();
|
|
1413
|
+
if (s0 === peg$FAILED) {
|
|
1414
|
+
s0 = peg$currPos;
|
|
1415
|
+
s1 = peg$parseMacroTag();
|
|
1416
|
+
if (s1 !== peg$FAILED) {
|
|
1417
|
+
s2 = peg$currPos;
|
|
1418
|
+
peg$savedPos = peg$currPos;
|
|
1419
|
+
s3 = peg$f33(s1);
|
|
1420
|
+
if (s3) s3 = void 0;
|
|
1421
|
+
else s3 = peg$FAILED;
|
|
1422
|
+
if (s3 !== peg$FAILED) {
|
|
1423
|
+
s4 = peg$parseRawTokens();
|
|
1424
|
+
if (s4 !== peg$FAILED) {
|
|
1425
|
+
peg$savedPos = s2;
|
|
1426
|
+
s2 = peg$f34(s1, s4);
|
|
1427
|
+
} else {
|
|
1428
|
+
peg$currPos = s2;
|
|
1429
|
+
s2 = peg$FAILED;
|
|
1430
|
+
}
|
|
1431
|
+
} else {
|
|
1432
|
+
peg$currPos = s2;
|
|
1433
|
+
s2 = peg$FAILED;
|
|
1434
|
+
}
|
|
1435
|
+
if (s2 === peg$FAILED) s2 = null;
|
|
1436
|
+
peg$savedPos = s0;
|
|
1437
|
+
s0 = peg$f35(s1, s2);
|
|
1438
|
+
} else {
|
|
1439
|
+
peg$currPos = s0;
|
|
1440
|
+
s0 = peg$FAILED;
|
|
1441
|
+
}
|
|
1442
|
+
if (s0 === peg$FAILED) s0 = peg$parseLiteral();
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
return s0;
|
|
1450
|
+
}
|
|
1451
|
+
function peg$parseRawTokens() {
|
|
1452
|
+
let s0, s1, s2, s3, s4, s5, s6, s7;
|
|
1453
|
+
s0 = peg$currPos;
|
|
1454
|
+
s1 = peg$parseHere();
|
|
1455
|
+
peg$savedPos = peg$currPos;
|
|
1456
|
+
s2 = peg$f36(s1);
|
|
1457
|
+
if (s2) s2 = void 0;
|
|
1458
|
+
else s2 = peg$FAILED;
|
|
1459
|
+
if (s2 !== peg$FAILED) {
|
|
1460
|
+
s3 = peg$currPos;
|
|
1461
|
+
s4 = peg$f37(s1);
|
|
1462
|
+
s5 = peg$currPos;
|
|
1463
|
+
s6 = [];
|
|
1464
|
+
if (s6.length >= (s4 | 0)) s7 = peg$FAILED;
|
|
1465
|
+
else if (input.length > peg$currPos) {
|
|
1466
|
+
s7 = input.charAt(peg$currPos);
|
|
1467
|
+
peg$currPos++;
|
|
1468
|
+
} else {
|
|
1469
|
+
s7 = peg$FAILED;
|
|
1470
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1471
|
+
}
|
|
1472
|
+
while (s7 !== peg$FAILED) {
|
|
1473
|
+
s6.push(s7);
|
|
1474
|
+
if (s6.length >= (s4 | 0)) s7 = peg$FAILED;
|
|
1475
|
+
else if (input.length > peg$currPos) {
|
|
1476
|
+
s7 = input.charAt(peg$currPos);
|
|
1477
|
+
peg$currPos++;
|
|
1478
|
+
} else {
|
|
1479
|
+
s7 = peg$FAILED;
|
|
1480
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
if (s6.length < (s4 | 0)) {
|
|
1484
|
+
peg$currPos = s5;
|
|
1485
|
+
s5 = peg$FAILED;
|
|
1486
|
+
} else s5 = s6;
|
|
1487
|
+
s4 = s5;
|
|
1488
|
+
if (s4 !== peg$FAILED) s3 = input.substring(s3, peg$currPos);
|
|
1489
|
+
else s3 = s4;
|
|
1490
|
+
if (s3 !== peg$FAILED) {
|
|
1491
|
+
s4 = peg$parseCloseTag();
|
|
1492
|
+
if (s4 !== peg$FAILED) {
|
|
1493
|
+
peg$savedPos = s0;
|
|
1494
|
+
s0 = peg$f38(s1, s3, s4);
|
|
1495
|
+
} else {
|
|
1496
|
+
peg$currPos = s0;
|
|
1497
|
+
s0 = peg$FAILED;
|
|
1498
|
+
}
|
|
1499
|
+
} else {
|
|
1500
|
+
peg$currPos = s0;
|
|
1501
|
+
s0 = peg$FAILED;
|
|
1502
|
+
}
|
|
1503
|
+
} else {
|
|
1504
|
+
peg$currPos = s0;
|
|
1505
|
+
s0 = peg$FAILED;
|
|
1506
|
+
}
|
|
1507
|
+
return s0;
|
|
1508
|
+
}
|
|
1509
|
+
function peg$parseHere() {
|
|
1510
|
+
let s0, s1;
|
|
1511
|
+
s0 = peg$currPos;
|
|
1512
|
+
s1 = "";
|
|
1513
|
+
peg$savedPos = s0;
|
|
1514
|
+
s1 = peg$f39();
|
|
1515
|
+
s0 = s1;
|
|
1516
|
+
return s0;
|
|
1517
|
+
}
|
|
1518
|
+
function peg$parseTextRun() {
|
|
1519
|
+
let s0, s1, s2, s3;
|
|
1520
|
+
s0 = peg$currPos;
|
|
1521
|
+
s1 = peg$currPos;
|
|
1522
|
+
s2 = [];
|
|
1523
|
+
s3 = input.charAt(peg$currPos);
|
|
1524
|
+
if (peg$r0.test(s3)) peg$currPos++;
|
|
1525
|
+
else {
|
|
1526
|
+
s3 = peg$FAILED;
|
|
1527
|
+
if (peg$silentFails === 0) peg$fail(peg$e1);
|
|
1528
|
+
}
|
|
1529
|
+
if (s3 !== peg$FAILED) while (s3 !== peg$FAILED) {
|
|
1530
|
+
s2.push(s3);
|
|
1531
|
+
s3 = input.charAt(peg$currPos);
|
|
1532
|
+
if (peg$r0.test(s3)) peg$currPos++;
|
|
1533
|
+
else {
|
|
1534
|
+
s3 = peg$FAILED;
|
|
1535
|
+
if (peg$silentFails === 0) peg$fail(peg$e1);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
else s2 = peg$FAILED;
|
|
1539
|
+
if (s2 !== peg$FAILED) s1 = input.substring(s1, peg$currPos);
|
|
1540
|
+
else s1 = s2;
|
|
1541
|
+
if (s1 !== peg$FAILED) {
|
|
1542
|
+
peg$savedPos = s0;
|
|
1543
|
+
s1 = peg$f40(s1);
|
|
1544
|
+
}
|
|
1545
|
+
s0 = s1;
|
|
1546
|
+
return s0;
|
|
1547
|
+
}
|
|
1548
|
+
function peg$parseEscape() {
|
|
1549
|
+
let s0, s1, s2, s3, s4;
|
|
1550
|
+
s0 = peg$currPos;
|
|
1551
|
+
s1 = peg$currPos;
|
|
1552
|
+
s2 = [];
|
|
1553
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
1554
|
+
s3 = peg$c0;
|
|
1555
|
+
peg$currPos++;
|
|
1556
|
+
} else {
|
|
1557
|
+
s3 = peg$FAILED;
|
|
1558
|
+
if (peg$silentFails === 0) peg$fail(peg$e2);
|
|
1559
|
+
}
|
|
1560
|
+
if (s3 !== peg$FAILED) while (s3 !== peg$FAILED) {
|
|
1561
|
+
s2.push(s3);
|
|
1562
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
1563
|
+
s3 = peg$c0;
|
|
1564
|
+
peg$currPos++;
|
|
1565
|
+
} else {
|
|
1566
|
+
s3 = peg$FAILED;
|
|
1567
|
+
if (peg$silentFails === 0) peg$fail(peg$e2);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
else s2 = peg$FAILED;
|
|
1571
|
+
if (s2 !== peg$FAILED) s1 = input.substring(s1, peg$currPos);
|
|
1572
|
+
else s1 = s2;
|
|
1573
|
+
if (s1 !== peg$FAILED) {
|
|
1574
|
+
s2 = peg$currPos;
|
|
1575
|
+
peg$savedPos = peg$currPos;
|
|
1576
|
+
s3 = peg$f41(s1);
|
|
1577
|
+
if (s3) s3 = void 0;
|
|
1578
|
+
else s3 = peg$FAILED;
|
|
1579
|
+
if (s3 !== peg$FAILED) {
|
|
1580
|
+
s4 = input.charAt(peg$currPos);
|
|
1581
|
+
if (peg$r1.test(s4)) peg$currPos++;
|
|
1582
|
+
else {
|
|
1583
|
+
s4 = peg$FAILED;
|
|
1584
|
+
if (peg$silentFails === 0) peg$fail(peg$e3);
|
|
1585
|
+
}
|
|
1586
|
+
if (s4 !== peg$FAILED) {
|
|
1587
|
+
peg$savedPos = s2;
|
|
1588
|
+
s2 = peg$f42(s1, s4);
|
|
1589
|
+
} else {
|
|
1590
|
+
peg$currPos = s2;
|
|
1591
|
+
s2 = peg$FAILED;
|
|
1592
|
+
}
|
|
1593
|
+
} else {
|
|
1594
|
+
peg$currPos = s2;
|
|
1595
|
+
s2 = peg$FAILED;
|
|
1596
|
+
}
|
|
1597
|
+
if (s2 === peg$FAILED) s2 = null;
|
|
1598
|
+
peg$savedPos = s0;
|
|
1599
|
+
s0 = peg$f43(s1, s2);
|
|
1600
|
+
} else {
|
|
1601
|
+
peg$currPos = s0;
|
|
1602
|
+
s0 = peg$FAILED;
|
|
1603
|
+
}
|
|
1604
|
+
return s0;
|
|
1605
|
+
}
|
|
1606
|
+
function peg$parseLiteral() {
|
|
1607
|
+
let s0, s1, s2, s3, s4, s5;
|
|
1608
|
+
s0 = peg$currPos;
|
|
1609
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1610
|
+
s1 = peg$c1;
|
|
1611
|
+
peg$currPos++;
|
|
1612
|
+
} else {
|
|
1613
|
+
s1 = peg$FAILED;
|
|
1614
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
1615
|
+
}
|
|
1616
|
+
if (s1 !== peg$FAILED) {
|
|
1617
|
+
s2 = peg$currPos;
|
|
1618
|
+
peg$silentFails++;
|
|
1619
|
+
s3 = peg$currPos;
|
|
1620
|
+
s4 = peg$parseSelectors();
|
|
1621
|
+
if (s4 !== peg$FAILED) {
|
|
1622
|
+
s5 = input.charAt(peg$currPos);
|
|
1623
|
+
if (peg$r2.test(s5)) peg$currPos++;
|
|
1624
|
+
else {
|
|
1625
|
+
s5 = peg$FAILED;
|
|
1626
|
+
if (peg$silentFails === 0) peg$fail(peg$e5);
|
|
1627
|
+
}
|
|
1628
|
+
if (s5 !== peg$FAILED) {
|
|
1629
|
+
s4 = [s4, s5];
|
|
1630
|
+
s3 = s4;
|
|
1631
|
+
} else {
|
|
1632
|
+
peg$currPos = s3;
|
|
1633
|
+
s3 = peg$FAILED;
|
|
1634
|
+
}
|
|
1635
|
+
} else {
|
|
1636
|
+
peg$currPos = s3;
|
|
1637
|
+
s3 = peg$FAILED;
|
|
1638
|
+
}
|
|
1639
|
+
peg$silentFails--;
|
|
1640
|
+
if (s3 === peg$FAILED) s2 = void 0;
|
|
1641
|
+
else {
|
|
1642
|
+
peg$currPos = s2;
|
|
1643
|
+
s2 = peg$FAILED;
|
|
1644
|
+
}
|
|
1645
|
+
if (s2 !== peg$FAILED) {
|
|
1646
|
+
peg$savedPos = s0;
|
|
1647
|
+
s0 = peg$f44();
|
|
1648
|
+
} else {
|
|
1649
|
+
peg$currPos = s0;
|
|
1650
|
+
s0 = peg$FAILED;
|
|
1651
|
+
}
|
|
1652
|
+
} else {
|
|
1653
|
+
peg$currPos = s0;
|
|
1654
|
+
s0 = peg$FAILED;
|
|
1655
|
+
}
|
|
1656
|
+
if (s0 === peg$FAILED) {
|
|
1657
|
+
s0 = peg$currPos;
|
|
1658
|
+
s1 = peg$currPos;
|
|
1659
|
+
peg$silentFails++;
|
|
1660
|
+
s2 = peg$currPos;
|
|
1661
|
+
peg$savedPos = peg$currPos;
|
|
1662
|
+
s3 = peg$f45();
|
|
1663
|
+
if (s3) s3 = void 0;
|
|
1664
|
+
else s3 = peg$FAILED;
|
|
1665
|
+
if (s3 !== peg$FAILED) {
|
|
1666
|
+
s4 = peg$parseHtmlClose();
|
|
1667
|
+
if (s4 !== peg$FAILED) {
|
|
1668
|
+
s3 = [s3, s4];
|
|
1669
|
+
s2 = s3;
|
|
1670
|
+
} else {
|
|
1671
|
+
peg$currPos = s2;
|
|
1672
|
+
s2 = peg$FAILED;
|
|
1673
|
+
}
|
|
1674
|
+
} else {
|
|
1675
|
+
peg$currPos = s2;
|
|
1676
|
+
s2 = peg$FAILED;
|
|
1677
|
+
}
|
|
1678
|
+
peg$silentFails--;
|
|
1679
|
+
if (s2 === peg$FAILED) s1 = void 0;
|
|
1680
|
+
else {
|
|
1681
|
+
peg$currPos = s1;
|
|
1682
|
+
s1 = peg$FAILED;
|
|
1683
|
+
}
|
|
1684
|
+
if (s1 !== peg$FAILED) {
|
|
1685
|
+
if (input.charCodeAt(peg$currPos) === 60) {
|
|
1686
|
+
s2 = peg$c2;
|
|
1687
|
+
peg$currPos++;
|
|
1688
|
+
} else {
|
|
1689
|
+
s2 = peg$FAILED;
|
|
1690
|
+
if (peg$silentFails === 0) peg$fail(peg$e6);
|
|
1691
|
+
}
|
|
1692
|
+
if (s2 !== peg$FAILED) {
|
|
1693
|
+
peg$savedPos = s0;
|
|
1694
|
+
s0 = peg$f46();
|
|
1695
|
+
} else {
|
|
1696
|
+
peg$currPos = s0;
|
|
1697
|
+
s0 = peg$FAILED;
|
|
1698
|
+
}
|
|
1699
|
+
} else {
|
|
1700
|
+
peg$currPos = s0;
|
|
1701
|
+
s0 = peg$FAILED;
|
|
1702
|
+
}
|
|
1703
|
+
if (s0 === peg$FAILED) {
|
|
1704
|
+
s0 = peg$currPos;
|
|
1705
|
+
if (input.charCodeAt(peg$currPos) === 91) {
|
|
1706
|
+
s1 = peg$c3;
|
|
1707
|
+
peg$currPos++;
|
|
1708
|
+
} else {
|
|
1709
|
+
s1 = peg$FAILED;
|
|
1710
|
+
if (peg$silentFails === 0) peg$fail(peg$e7);
|
|
1711
|
+
}
|
|
1712
|
+
if (s1 !== peg$FAILED) {
|
|
1713
|
+
peg$savedPos = s0;
|
|
1714
|
+
s1 = peg$f47();
|
|
1715
|
+
}
|
|
1716
|
+
s0 = s1;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return s0;
|
|
1720
|
+
}
|
|
1721
|
+
function peg$parseLinkLexeme() {
|
|
1722
|
+
let s0, s1, s2, s3, s4, s5;
|
|
1723
|
+
s0 = peg$currPos;
|
|
1724
|
+
peg$savedPos = peg$currPos;
|
|
1725
|
+
s1 = peg$f48();
|
|
1726
|
+
if (s1) s1 = void 0;
|
|
1727
|
+
else s1 = peg$FAILED;
|
|
1728
|
+
if (s1 !== peg$FAILED) {
|
|
1729
|
+
if (input.substr(peg$currPos, 2) === peg$c4) {
|
|
1730
|
+
s2 = peg$c4;
|
|
1731
|
+
peg$currPos += 2;
|
|
1732
|
+
} else {
|
|
1733
|
+
s2 = peg$FAILED;
|
|
1734
|
+
if (peg$silentFails === 0) peg$fail(peg$e8);
|
|
1735
|
+
}
|
|
1736
|
+
if (s2 !== peg$FAILED) {
|
|
1737
|
+
s3 = peg$parseSelectors();
|
|
1738
|
+
if (s3 !== peg$FAILED) {
|
|
1739
|
+
s4 = peg$currPos;
|
|
1740
|
+
s5 = peg$parseLinkText();
|
|
1741
|
+
s4 = input.substring(s4, peg$currPos);
|
|
1742
|
+
if (input.substr(peg$currPos, 2) === peg$c5) {
|
|
1743
|
+
s5 = peg$c5;
|
|
1744
|
+
peg$currPos += 2;
|
|
1745
|
+
} else {
|
|
1746
|
+
s5 = peg$FAILED;
|
|
1747
|
+
if (peg$silentFails === 0) peg$fail(peg$e9);
|
|
1748
|
+
}
|
|
1749
|
+
if (s5 !== peg$FAILED) {
|
|
1750
|
+
peg$savedPos = s0;
|
|
1751
|
+
s0 = peg$f49(s3, s4);
|
|
1752
|
+
} else {
|
|
1753
|
+
peg$currPos = s0;
|
|
1754
|
+
s0 = peg$FAILED;
|
|
1755
|
+
}
|
|
1756
|
+
} else {
|
|
1757
|
+
peg$currPos = s0;
|
|
1758
|
+
s0 = peg$FAILED;
|
|
1759
|
+
}
|
|
1760
|
+
} else {
|
|
1761
|
+
peg$currPos = s0;
|
|
1762
|
+
s0 = peg$FAILED;
|
|
1763
|
+
}
|
|
1764
|
+
} else {
|
|
1765
|
+
peg$currPos = s0;
|
|
1766
|
+
s0 = peg$FAILED;
|
|
1767
|
+
}
|
|
1768
|
+
if (s0 === peg$FAILED) {
|
|
1769
|
+
s0 = peg$currPos;
|
|
1770
|
+
peg$savedPos = peg$currPos;
|
|
1771
|
+
s1 = peg$f50();
|
|
1772
|
+
if (s1) s1 = void 0;
|
|
1773
|
+
else s1 = peg$FAILED;
|
|
1774
|
+
if (s1 !== peg$FAILED) {
|
|
1775
|
+
if (input.substr(peg$currPos, 2) === peg$c4) {
|
|
1776
|
+
s2 = peg$c4;
|
|
1777
|
+
peg$currPos += 2;
|
|
1778
|
+
} else {
|
|
1779
|
+
s2 = peg$FAILED;
|
|
1780
|
+
if (peg$silentFails === 0) peg$fail(peg$e8);
|
|
1781
|
+
}
|
|
1782
|
+
if (s2 !== peg$FAILED) {
|
|
1783
|
+
peg$savedPos = s0;
|
|
1784
|
+
s0 = peg$f51();
|
|
1785
|
+
} else {
|
|
1786
|
+
peg$currPos = s0;
|
|
1787
|
+
s0 = peg$FAILED;
|
|
1788
|
+
}
|
|
1789
|
+
} else {
|
|
1790
|
+
peg$currPos = s0;
|
|
1791
|
+
s0 = peg$FAILED;
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
return s0;
|
|
1795
|
+
}
|
|
1796
|
+
function peg$parseLinkText() {
|
|
1797
|
+
let s0, s1, s2, s3;
|
|
1798
|
+
s0 = [];
|
|
1799
|
+
s1 = peg$currPos;
|
|
1800
|
+
s2 = peg$currPos;
|
|
1801
|
+
peg$silentFails++;
|
|
1802
|
+
if (input.substr(peg$currPos, 2) === peg$c5) {
|
|
1803
|
+
s3 = peg$c5;
|
|
1804
|
+
peg$currPos += 2;
|
|
1805
|
+
} else {
|
|
1806
|
+
s3 = peg$FAILED;
|
|
1807
|
+
if (peg$silentFails === 0) peg$fail(peg$e9);
|
|
1808
|
+
}
|
|
1809
|
+
if (s3 === peg$FAILED) if (input.substr(peg$currPos, 2) === peg$c4) {
|
|
1810
|
+
s3 = peg$c4;
|
|
1811
|
+
peg$currPos += 2;
|
|
1812
|
+
} else {
|
|
1813
|
+
s3 = peg$FAILED;
|
|
1814
|
+
if (peg$silentFails === 0) peg$fail(peg$e8);
|
|
1815
|
+
}
|
|
1816
|
+
peg$silentFails--;
|
|
1817
|
+
if (s3 === peg$FAILED) s2 = void 0;
|
|
1818
|
+
else {
|
|
1819
|
+
peg$currPos = s2;
|
|
1820
|
+
s2 = peg$FAILED;
|
|
1821
|
+
}
|
|
1822
|
+
if (s2 !== peg$FAILED) {
|
|
1823
|
+
if (input.length > peg$currPos) {
|
|
1824
|
+
s3 = input.charAt(peg$currPos);
|
|
1825
|
+
peg$currPos++;
|
|
1826
|
+
} else {
|
|
1827
|
+
s3 = peg$FAILED;
|
|
1828
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1829
|
+
}
|
|
1830
|
+
if (s3 !== peg$FAILED) {
|
|
1831
|
+
s2 = [s2, s3];
|
|
1832
|
+
s1 = s2;
|
|
1833
|
+
} else {
|
|
1834
|
+
peg$currPos = s1;
|
|
1835
|
+
s1 = peg$FAILED;
|
|
1836
|
+
}
|
|
1837
|
+
} else {
|
|
1838
|
+
peg$currPos = s1;
|
|
1839
|
+
s1 = peg$FAILED;
|
|
1840
|
+
}
|
|
1841
|
+
while (s1 !== peg$FAILED) {
|
|
1842
|
+
s0.push(s1);
|
|
1843
|
+
s1 = peg$currPos;
|
|
1844
|
+
s2 = peg$currPos;
|
|
1845
|
+
peg$silentFails++;
|
|
1846
|
+
if (input.substr(peg$currPos, 2) === peg$c5) {
|
|
1847
|
+
s3 = peg$c5;
|
|
1848
|
+
peg$currPos += 2;
|
|
1849
|
+
} else {
|
|
1850
|
+
s3 = peg$FAILED;
|
|
1851
|
+
if (peg$silentFails === 0) peg$fail(peg$e9);
|
|
1852
|
+
}
|
|
1853
|
+
if (s3 === peg$FAILED) if (input.substr(peg$currPos, 2) === peg$c4) {
|
|
1854
|
+
s3 = peg$c4;
|
|
1855
|
+
peg$currPos += 2;
|
|
1856
|
+
} else {
|
|
1857
|
+
s3 = peg$FAILED;
|
|
1858
|
+
if (peg$silentFails === 0) peg$fail(peg$e8);
|
|
1859
|
+
}
|
|
1860
|
+
peg$silentFails--;
|
|
1861
|
+
if (s3 === peg$FAILED) s2 = void 0;
|
|
1862
|
+
else {
|
|
1863
|
+
peg$currPos = s2;
|
|
1864
|
+
s2 = peg$FAILED;
|
|
1865
|
+
}
|
|
1866
|
+
if (s2 !== peg$FAILED) {
|
|
1867
|
+
if (input.length > peg$currPos) {
|
|
1868
|
+
s3 = input.charAt(peg$currPos);
|
|
1869
|
+
peg$currPos++;
|
|
1870
|
+
} else {
|
|
1871
|
+
s3 = peg$FAILED;
|
|
1872
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
1873
|
+
}
|
|
1874
|
+
if (s3 !== peg$FAILED) {
|
|
1875
|
+
s2 = [s2, s3];
|
|
1876
|
+
s1 = s2;
|
|
1877
|
+
} else {
|
|
1878
|
+
peg$currPos = s1;
|
|
1879
|
+
s1 = peg$FAILED;
|
|
1880
|
+
}
|
|
1881
|
+
} else {
|
|
1882
|
+
peg$currPos = s1;
|
|
1883
|
+
s1 = peg$FAILED;
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
return s0;
|
|
1887
|
+
}
|
|
1888
|
+
function peg$parseSelectors() {
|
|
1889
|
+
let s0, s1, s2;
|
|
1890
|
+
s0 = peg$currPos;
|
|
1891
|
+
s1 = [];
|
|
1892
|
+
s2 = peg$parseSelectorPart();
|
|
1893
|
+
if (s2 !== peg$FAILED) while (s2 !== peg$FAILED) {
|
|
1894
|
+
s1.push(s2);
|
|
1895
|
+
s2 = peg$parseSelectorPart();
|
|
1896
|
+
}
|
|
1897
|
+
else s1 = peg$FAILED;
|
|
1898
|
+
if (s1 !== peg$FAILED) {
|
|
1899
|
+
if (input.charCodeAt(peg$currPos) === 32) {
|
|
1900
|
+
s2 = peg$c6;
|
|
1901
|
+
peg$currPos++;
|
|
1902
|
+
} else {
|
|
1903
|
+
s2 = peg$FAILED;
|
|
1904
|
+
if (peg$silentFails === 0) peg$fail(peg$e10);
|
|
1905
|
+
}
|
|
1906
|
+
if (s2 === peg$FAILED) s2 = null;
|
|
1907
|
+
peg$savedPos = s0;
|
|
1908
|
+
s0 = peg$f52(s1);
|
|
1909
|
+
} else {
|
|
1910
|
+
peg$currPos = s0;
|
|
1911
|
+
s0 = peg$FAILED;
|
|
1912
|
+
}
|
|
1913
|
+
if (s0 === peg$FAILED) {
|
|
1914
|
+
s0 = peg$currPos;
|
|
1915
|
+
s1 = "";
|
|
1916
|
+
peg$savedPos = s0;
|
|
1917
|
+
s1 = peg$f53();
|
|
1918
|
+
s0 = s1;
|
|
1919
|
+
}
|
|
1920
|
+
return s0;
|
|
1921
|
+
}
|
|
1922
|
+
function peg$parseSelectorPart() {
|
|
1923
|
+
let s0, s1, s2, s3, s4;
|
|
1924
|
+
s0 = peg$currPos;
|
|
1925
|
+
s1 = input.charAt(peg$currPos);
|
|
1926
|
+
if (peg$r3.test(s1)) peg$currPos++;
|
|
1927
|
+
else {
|
|
1928
|
+
s1 = peg$FAILED;
|
|
1929
|
+
if (peg$silentFails === 0) peg$fail(peg$e11);
|
|
1930
|
+
}
|
|
1931
|
+
if (s1 !== peg$FAILED) {
|
|
1932
|
+
s2 = peg$currPos;
|
|
1933
|
+
s3 = [];
|
|
1934
|
+
s4 = peg$parseSelectorChar();
|
|
1935
|
+
while (s4 !== peg$FAILED) {
|
|
1936
|
+
s3.push(s4);
|
|
1937
|
+
s4 = peg$parseSelectorChar();
|
|
1938
|
+
}
|
|
1939
|
+
s2 = input.substring(s2, peg$currPos);
|
|
1940
|
+
peg$savedPos = s0;
|
|
1941
|
+
s0 = peg$f54(s1, s2);
|
|
1942
|
+
} else {
|
|
1943
|
+
peg$currPos = s0;
|
|
1944
|
+
s0 = peg$FAILED;
|
|
1945
|
+
}
|
|
1946
|
+
return s0;
|
|
1947
|
+
}
|
|
1948
|
+
function peg$parseSelectorChar() {
|
|
1949
|
+
let s0, s1, s2, s3, s4;
|
|
1950
|
+
s0 = input.charAt(peg$currPos);
|
|
1951
|
+
if (peg$r4.test(s0)) peg$currPos++;
|
|
1952
|
+
else {
|
|
1953
|
+
s0 = peg$FAILED;
|
|
1954
|
+
if (peg$silentFails === 0) peg$fail(peg$e12);
|
|
1955
|
+
}
|
|
1956
|
+
if (s0 === peg$FAILED) {
|
|
1957
|
+
s0 = peg$currPos;
|
|
1958
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1959
|
+
s1 = peg$c1;
|
|
1960
|
+
peg$currPos++;
|
|
1961
|
+
} else {
|
|
1962
|
+
s1 = peg$FAILED;
|
|
1963
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
1964
|
+
}
|
|
1965
|
+
if (s1 !== peg$FAILED) {
|
|
1966
|
+
s2 = input.charAt(peg$currPos);
|
|
1967
|
+
if (peg$r5.test(s2)) peg$currPos++;
|
|
1968
|
+
else {
|
|
1969
|
+
s2 = peg$FAILED;
|
|
1970
|
+
if (peg$silentFails === 0) peg$fail(peg$e13);
|
|
1971
|
+
}
|
|
1972
|
+
if (s2 !== peg$FAILED) {
|
|
1973
|
+
s3 = [];
|
|
1974
|
+
s4 = input.charAt(peg$currPos);
|
|
1975
|
+
if (peg$r6.test(s4)) peg$currPos++;
|
|
1976
|
+
else {
|
|
1977
|
+
s4 = peg$FAILED;
|
|
1978
|
+
if (peg$silentFails === 0) peg$fail(peg$e14);
|
|
1979
|
+
}
|
|
1980
|
+
while (s4 !== peg$FAILED) {
|
|
1981
|
+
s3.push(s4);
|
|
1982
|
+
s4 = input.charAt(peg$currPos);
|
|
1983
|
+
if (peg$r6.test(s4)) peg$currPos++;
|
|
1984
|
+
else {
|
|
1985
|
+
s4 = peg$FAILED;
|
|
1986
|
+
if (peg$silentFails === 0) peg$fail(peg$e14);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
1990
|
+
s4 = peg$c7;
|
|
1991
|
+
peg$currPos++;
|
|
1992
|
+
} else {
|
|
1993
|
+
s4 = peg$FAILED;
|
|
1994
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
1995
|
+
}
|
|
1996
|
+
if (s4 !== peg$FAILED) {
|
|
1997
|
+
s1 = [
|
|
1998
|
+
s1,
|
|
1999
|
+
s2,
|
|
2000
|
+
s3,
|
|
2001
|
+
s4
|
|
2002
|
+
];
|
|
2003
|
+
s0 = s1;
|
|
2004
|
+
} else {
|
|
2005
|
+
peg$currPos = s0;
|
|
2006
|
+
s0 = peg$FAILED;
|
|
2007
|
+
}
|
|
2008
|
+
} else {
|
|
2009
|
+
peg$currPos = s0;
|
|
2010
|
+
s0 = peg$FAILED;
|
|
2011
|
+
}
|
|
2012
|
+
} else {
|
|
2013
|
+
peg$currPos = s0;
|
|
2014
|
+
s0 = peg$FAILED;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
return s0;
|
|
2018
|
+
}
|
|
2019
|
+
function peg$parseValue() {
|
|
2020
|
+
let s0, s1, s2, s3, s4, s5, s6;
|
|
2021
|
+
s0 = peg$currPos;
|
|
2022
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
2023
|
+
s1 = peg$c1;
|
|
2024
|
+
peg$currPos++;
|
|
2025
|
+
} else {
|
|
2026
|
+
s1 = peg$FAILED;
|
|
2027
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
2028
|
+
}
|
|
2029
|
+
if (s1 !== peg$FAILED) {
|
|
2030
|
+
s2 = peg$parseSelectors();
|
|
2031
|
+
if (s2 !== peg$FAILED) {
|
|
2032
|
+
s3 = input.charAt(peg$currPos);
|
|
2033
|
+
if (peg$r5.test(s3)) peg$currPos++;
|
|
2034
|
+
else {
|
|
2035
|
+
s3 = peg$FAILED;
|
|
2036
|
+
if (peg$silentFails === 0) peg$fail(peg$e13);
|
|
2037
|
+
}
|
|
2038
|
+
if (s3 !== peg$FAILED) {
|
|
2039
|
+
s4 = peg$currPos;
|
|
2040
|
+
s5 = [];
|
|
2041
|
+
s6 = input.charAt(peg$currPos);
|
|
2042
|
+
if (peg$r6.test(s6)) peg$currPos++;
|
|
2043
|
+
else {
|
|
2044
|
+
s6 = peg$FAILED;
|
|
2045
|
+
if (peg$silentFails === 0) peg$fail(peg$e14);
|
|
2046
|
+
}
|
|
2047
|
+
while (s6 !== peg$FAILED) {
|
|
2048
|
+
s5.push(s6);
|
|
2049
|
+
s6 = input.charAt(peg$currPos);
|
|
2050
|
+
if (peg$r6.test(s6)) peg$currPos++;
|
|
2051
|
+
else {
|
|
2052
|
+
s6 = peg$FAILED;
|
|
2053
|
+
if (peg$silentFails === 0) peg$fail(peg$e14);
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
s4 = input.substring(s4, peg$currPos);
|
|
2057
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
2058
|
+
s5 = peg$c7;
|
|
2059
|
+
peg$currPos++;
|
|
2060
|
+
} else {
|
|
2061
|
+
s5 = peg$FAILED;
|
|
2062
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
2063
|
+
}
|
|
2064
|
+
if (s5 !== peg$FAILED) {
|
|
2065
|
+
peg$savedPos = s0;
|
|
2066
|
+
s0 = peg$f55(s2, s3, s4);
|
|
2067
|
+
} else {
|
|
2068
|
+
peg$currPos = s0;
|
|
2069
|
+
s0 = peg$FAILED;
|
|
2070
|
+
}
|
|
2071
|
+
} else {
|
|
2072
|
+
peg$currPos = s0;
|
|
2073
|
+
s0 = peg$FAILED;
|
|
2074
|
+
}
|
|
2075
|
+
} else {
|
|
2076
|
+
peg$currPos = s0;
|
|
2077
|
+
s0 = peg$FAILED;
|
|
2078
|
+
}
|
|
2079
|
+
} else {
|
|
2080
|
+
peg$currPos = s0;
|
|
2081
|
+
s0 = peg$FAILED;
|
|
2082
|
+
}
|
|
2083
|
+
if (s0 === peg$FAILED) {
|
|
2084
|
+
s0 = peg$currPos;
|
|
2085
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
2086
|
+
s1 = peg$c1;
|
|
2087
|
+
peg$currPos++;
|
|
2088
|
+
} else {
|
|
2089
|
+
s1 = peg$FAILED;
|
|
2090
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
2091
|
+
}
|
|
2092
|
+
if (s1 !== peg$FAILED) {
|
|
2093
|
+
s2 = peg$parseSelectors();
|
|
2094
|
+
if (s2 !== peg$FAILED) {
|
|
2095
|
+
s3 = peg$currPos;
|
|
2096
|
+
peg$silentFails++;
|
|
2097
|
+
s4 = input.charAt(peg$currPos);
|
|
2098
|
+
if (peg$r7.test(s4)) peg$currPos++;
|
|
2099
|
+
else {
|
|
2100
|
+
s4 = peg$FAILED;
|
|
2101
|
+
if (peg$silentFails === 0) peg$fail(peg$e16);
|
|
2102
|
+
}
|
|
2103
|
+
peg$silentFails--;
|
|
2104
|
+
if (s4 !== peg$FAILED) {
|
|
2105
|
+
peg$currPos = s3;
|
|
2106
|
+
s3 = void 0;
|
|
2107
|
+
} else s3 = peg$FAILED;
|
|
2108
|
+
if (s3 !== peg$FAILED) {
|
|
2109
|
+
s4 = peg$parseCodeToBrace();
|
|
2110
|
+
if (s4 !== peg$FAILED) {
|
|
2111
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
2112
|
+
s5 = peg$c7;
|
|
2113
|
+
peg$currPos++;
|
|
2114
|
+
} else {
|
|
2115
|
+
s5 = peg$FAILED;
|
|
2116
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
2117
|
+
}
|
|
2118
|
+
if (s5 !== peg$FAILED) {
|
|
2119
|
+
peg$savedPos = s0;
|
|
2120
|
+
s0 = peg$f56(s2, s4);
|
|
2121
|
+
} else {
|
|
2122
|
+
peg$currPos = s0;
|
|
2123
|
+
s0 = peg$FAILED;
|
|
2124
|
+
}
|
|
2125
|
+
} else {
|
|
2126
|
+
peg$currPos = s0;
|
|
2127
|
+
s0 = peg$FAILED;
|
|
2128
|
+
}
|
|
2129
|
+
} else {
|
|
2130
|
+
peg$currPos = s0;
|
|
2131
|
+
s0 = peg$FAILED;
|
|
2132
|
+
}
|
|
2133
|
+
} else {
|
|
2134
|
+
peg$currPos = s0;
|
|
2135
|
+
s0 = peg$FAILED;
|
|
2136
|
+
}
|
|
2137
|
+
} else {
|
|
2138
|
+
peg$currPos = s0;
|
|
2139
|
+
s0 = peg$FAILED;
|
|
2140
|
+
}
|
|
2141
|
+
if (s0 === peg$FAILED) {
|
|
2142
|
+
s0 = peg$currPos;
|
|
2143
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
2144
|
+
s1 = peg$c1;
|
|
2145
|
+
peg$currPos++;
|
|
2146
|
+
} else {
|
|
2147
|
+
s1 = peg$FAILED;
|
|
2148
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
2149
|
+
}
|
|
2150
|
+
if (s1 !== peg$FAILED) {
|
|
2151
|
+
s2 = peg$parseSelectors();
|
|
2152
|
+
if (s2 !== peg$FAILED) {
|
|
2153
|
+
s3 = peg$currPos;
|
|
2154
|
+
peg$silentFails++;
|
|
2155
|
+
s4 = input.charAt(peg$currPos);
|
|
2156
|
+
if (peg$r7.test(s4)) peg$currPos++;
|
|
2157
|
+
else {
|
|
2158
|
+
s4 = peg$FAILED;
|
|
2159
|
+
if (peg$silentFails === 0) peg$fail(peg$e16);
|
|
2160
|
+
}
|
|
2161
|
+
peg$silentFails--;
|
|
2162
|
+
if (s4 !== peg$FAILED) {
|
|
2163
|
+
peg$currPos = s3;
|
|
2164
|
+
s3 = void 0;
|
|
2165
|
+
} else s3 = peg$FAILED;
|
|
2166
|
+
if (s3 !== peg$FAILED) {
|
|
2167
|
+
peg$savedPos = s0;
|
|
2168
|
+
s0 = peg$f57();
|
|
2169
|
+
} else {
|
|
2170
|
+
peg$currPos = s0;
|
|
2171
|
+
s0 = peg$FAILED;
|
|
2172
|
+
}
|
|
2173
|
+
} else {
|
|
2174
|
+
peg$currPos = s0;
|
|
2175
|
+
s0 = peg$FAILED;
|
|
2176
|
+
}
|
|
2177
|
+
} else {
|
|
2178
|
+
peg$currPos = s0;
|
|
2179
|
+
s0 = peg$FAILED;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return s0;
|
|
2184
|
+
}
|
|
2185
|
+
function peg$parseCodeToBrace() {
|
|
2186
|
+
let s0, s1, s2, s3, s4, s5, s6, s7;
|
|
2187
|
+
s0 = peg$currPos;
|
|
2188
|
+
s1 = peg$parseHere();
|
|
2189
|
+
peg$savedPos = peg$currPos;
|
|
2190
|
+
s2 = peg$f58(s1);
|
|
2191
|
+
if (s2) s2 = void 0;
|
|
2192
|
+
else s2 = peg$FAILED;
|
|
2193
|
+
if (s2 !== peg$FAILED) {
|
|
2194
|
+
s3 = peg$currPos;
|
|
2195
|
+
s4 = peg$f59(s1);
|
|
2196
|
+
s5 = peg$currPos;
|
|
2197
|
+
s6 = [];
|
|
2198
|
+
if (s6.length >= (s4 | 0)) s7 = peg$FAILED;
|
|
2199
|
+
else if (input.length > peg$currPos) {
|
|
2200
|
+
s7 = input.charAt(peg$currPos);
|
|
2201
|
+
peg$currPos++;
|
|
2202
|
+
} else {
|
|
2203
|
+
s7 = peg$FAILED;
|
|
2204
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2205
|
+
}
|
|
2206
|
+
while (s7 !== peg$FAILED) {
|
|
2207
|
+
s6.push(s7);
|
|
2208
|
+
if (s6.length >= (s4 | 0)) s7 = peg$FAILED;
|
|
2209
|
+
else if (input.length > peg$currPos) {
|
|
2210
|
+
s7 = input.charAt(peg$currPos);
|
|
2211
|
+
peg$currPos++;
|
|
2212
|
+
} else {
|
|
2213
|
+
s7 = peg$FAILED;
|
|
2214
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
if (s6.length < (s4 | 0)) {
|
|
2218
|
+
peg$currPos = s5;
|
|
2219
|
+
s5 = peg$FAILED;
|
|
2220
|
+
} else s5 = s6;
|
|
2221
|
+
s4 = s5;
|
|
2222
|
+
if (s4 !== peg$FAILED) s3 = input.substring(s3, peg$currPos);
|
|
2223
|
+
else s3 = s4;
|
|
2224
|
+
if (s3 !== peg$FAILED) {
|
|
2225
|
+
peg$savedPos = s0;
|
|
2226
|
+
s0 = peg$f60(s1, s3);
|
|
2227
|
+
} else {
|
|
2228
|
+
peg$currPos = s0;
|
|
2229
|
+
s0 = peg$FAILED;
|
|
2230
|
+
}
|
|
2231
|
+
} else {
|
|
2232
|
+
peg$currPos = s0;
|
|
2233
|
+
s0 = peg$FAILED;
|
|
2234
|
+
}
|
|
2235
|
+
return s0;
|
|
2236
|
+
}
|
|
2237
|
+
function peg$parseMacroTag() {
|
|
2238
|
+
let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
|
|
2239
|
+
s0 = peg$currPos;
|
|
2240
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
2241
|
+
s1 = peg$c1;
|
|
2242
|
+
peg$currPos++;
|
|
2243
|
+
} else {
|
|
2244
|
+
s1 = peg$FAILED;
|
|
2245
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
2246
|
+
}
|
|
2247
|
+
if (s1 !== peg$FAILED) {
|
|
2248
|
+
s2 = peg$parseSelectors();
|
|
2249
|
+
if (s2 !== peg$FAILED) {
|
|
2250
|
+
s3 = peg$parseHere();
|
|
2251
|
+
if (input.charCodeAt(peg$currPos) === 47) {
|
|
2252
|
+
s4 = peg$c8;
|
|
2253
|
+
peg$currPos++;
|
|
2254
|
+
} else {
|
|
2255
|
+
s4 = peg$FAILED;
|
|
2256
|
+
if (peg$silentFails === 0) peg$fail(peg$e17);
|
|
2257
|
+
}
|
|
2258
|
+
if (s4 === peg$FAILED) s4 = null;
|
|
2259
|
+
s5 = peg$parseMacroName();
|
|
2260
|
+
if (s5 !== peg$FAILED) {
|
|
2261
|
+
s6 = peg$parseHere();
|
|
2262
|
+
s7 = peg$currPos;
|
|
2263
|
+
peg$savedPos = peg$currPos;
|
|
2264
|
+
s8 = peg$f61(s2, s3, s4, s5, s6);
|
|
2265
|
+
if (s8) s8 = void 0;
|
|
2266
|
+
else s8 = peg$FAILED;
|
|
2267
|
+
if (s8 !== peg$FAILED) {
|
|
2268
|
+
s9 = peg$currPos;
|
|
2269
|
+
s10 = peg$f62(s2, s3, s4, s5, s6);
|
|
2270
|
+
s11 = peg$currPos;
|
|
2271
|
+
s12 = [];
|
|
2272
|
+
if (s12.length >= (s10 | 0)) s13 = peg$FAILED;
|
|
2273
|
+
else if (input.length > peg$currPos) {
|
|
2274
|
+
s13 = input.charAt(peg$currPos);
|
|
2275
|
+
peg$currPos++;
|
|
2276
|
+
} else {
|
|
2277
|
+
s13 = peg$FAILED;
|
|
2278
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2279
|
+
}
|
|
2280
|
+
while (s13 !== peg$FAILED) {
|
|
2281
|
+
s12.push(s13);
|
|
2282
|
+
if (s12.length >= (s10 | 0)) s13 = peg$FAILED;
|
|
2283
|
+
else if (input.length > peg$currPos) {
|
|
2284
|
+
s13 = input.charAt(peg$currPos);
|
|
2285
|
+
peg$currPos++;
|
|
2286
|
+
} else {
|
|
2287
|
+
s13 = peg$FAILED;
|
|
2288
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
if (s12.length < (s10 | 0)) {
|
|
2292
|
+
peg$currPos = s11;
|
|
2293
|
+
s11 = peg$FAILED;
|
|
2294
|
+
} else s11 = s12;
|
|
2295
|
+
s10 = s11;
|
|
2296
|
+
if (s10 !== peg$FAILED) s9 = input.substring(s9, peg$currPos);
|
|
2297
|
+
else s9 = s10;
|
|
2298
|
+
if (s9 !== peg$FAILED) {
|
|
2299
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
2300
|
+
s10 = peg$c7;
|
|
2301
|
+
peg$currPos++;
|
|
2302
|
+
} else {
|
|
2303
|
+
s10 = peg$FAILED;
|
|
2304
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
2305
|
+
}
|
|
2306
|
+
if (s10 !== peg$FAILED) {
|
|
2307
|
+
peg$savedPos = s7;
|
|
2308
|
+
s7 = peg$f63(s2, s3, s4, s5, s6, s9);
|
|
2309
|
+
} else {
|
|
2310
|
+
peg$currPos = s7;
|
|
2311
|
+
s7 = peg$FAILED;
|
|
2312
|
+
}
|
|
2313
|
+
} else {
|
|
2314
|
+
peg$currPos = s7;
|
|
2315
|
+
s7 = peg$FAILED;
|
|
2316
|
+
}
|
|
2317
|
+
} else {
|
|
2318
|
+
peg$currPos = s7;
|
|
2319
|
+
s7 = peg$FAILED;
|
|
2320
|
+
}
|
|
2321
|
+
if (s7 === peg$FAILED) s7 = null;
|
|
2322
|
+
peg$savedPos = s0;
|
|
2323
|
+
s0 = peg$f64(s2, s3, s4, s5, s6, s7);
|
|
2324
|
+
} else {
|
|
2325
|
+
peg$currPos = s0;
|
|
2326
|
+
s0 = peg$FAILED;
|
|
2327
|
+
}
|
|
2328
|
+
} else {
|
|
2329
|
+
peg$currPos = s0;
|
|
2330
|
+
s0 = peg$FAILED;
|
|
2331
|
+
}
|
|
2332
|
+
} else {
|
|
2333
|
+
peg$currPos = s0;
|
|
2334
|
+
s0 = peg$FAILED;
|
|
2335
|
+
}
|
|
2336
|
+
if (s0 === peg$FAILED) {
|
|
2337
|
+
s0 = peg$currPos;
|
|
2338
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
2339
|
+
s1 = peg$c1;
|
|
2340
|
+
peg$currPos++;
|
|
2341
|
+
} else {
|
|
2342
|
+
s1 = peg$FAILED;
|
|
2343
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
2344
|
+
}
|
|
2345
|
+
if (s1 !== peg$FAILED) {
|
|
2346
|
+
s2 = peg$parseSelectors();
|
|
2347
|
+
if (s2 !== peg$FAILED) {
|
|
2348
|
+
if (input.charCodeAt(peg$currPos) === 47) {
|
|
2349
|
+
s3 = peg$c8;
|
|
2350
|
+
peg$currPos++;
|
|
2351
|
+
} else {
|
|
2352
|
+
s3 = peg$FAILED;
|
|
2353
|
+
if (peg$silentFails === 0) peg$fail(peg$e17);
|
|
2354
|
+
}
|
|
2355
|
+
if (s3 !== peg$FAILED) {
|
|
2356
|
+
peg$savedPos = s0;
|
|
2357
|
+
s0 = peg$f65(s2);
|
|
2358
|
+
} else {
|
|
2359
|
+
peg$currPos = s0;
|
|
2360
|
+
s0 = peg$FAILED;
|
|
2361
|
+
}
|
|
2362
|
+
} else {
|
|
2363
|
+
peg$currPos = s0;
|
|
2364
|
+
s0 = peg$FAILED;
|
|
2365
|
+
}
|
|
2366
|
+
} else {
|
|
2367
|
+
peg$currPos = s0;
|
|
2368
|
+
s0 = peg$FAILED;
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
return s0;
|
|
2372
|
+
}
|
|
2373
|
+
function peg$parseMacroName() {
|
|
2374
|
+
let s0, s1, s2, s3, s4;
|
|
2375
|
+
s0 = peg$currPos;
|
|
2376
|
+
s1 = peg$currPos;
|
|
2377
|
+
s2 = input.charAt(peg$currPos);
|
|
2378
|
+
if (peg$r8.test(s2)) peg$currPos++;
|
|
2379
|
+
else {
|
|
2380
|
+
s2 = peg$FAILED;
|
|
2381
|
+
if (peg$silentFails === 0) peg$fail(peg$e18);
|
|
2382
|
+
}
|
|
2383
|
+
if (s2 !== peg$FAILED) {
|
|
2384
|
+
s3 = [];
|
|
2385
|
+
s4 = input.charAt(peg$currPos);
|
|
2386
|
+
if (peg$r9.test(s4)) peg$currPos++;
|
|
2387
|
+
else {
|
|
2388
|
+
s4 = peg$FAILED;
|
|
2389
|
+
if (peg$silentFails === 0) peg$fail(peg$e19);
|
|
2390
|
+
}
|
|
2391
|
+
while (s4 !== peg$FAILED) {
|
|
2392
|
+
s3.push(s4);
|
|
2393
|
+
s4 = input.charAt(peg$currPos);
|
|
2394
|
+
if (peg$r9.test(s4)) peg$currPos++;
|
|
2395
|
+
else {
|
|
2396
|
+
s4 = peg$FAILED;
|
|
2397
|
+
if (peg$silentFails === 0) peg$fail(peg$e19);
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
s2 = [s2, s3];
|
|
2401
|
+
s1 = s2;
|
|
2402
|
+
} else {
|
|
2403
|
+
peg$currPos = s1;
|
|
2404
|
+
s1 = peg$FAILED;
|
|
2405
|
+
}
|
|
2406
|
+
if (s1 !== peg$FAILED) s0 = input.substring(s0, peg$currPos);
|
|
2407
|
+
else s0 = s1;
|
|
2408
|
+
return s0;
|
|
2409
|
+
}
|
|
2410
|
+
function peg$parseVoidCloser() {
|
|
2411
|
+
let s0, s1, s2, s3;
|
|
2412
|
+
s0 = peg$currPos;
|
|
2413
|
+
peg$savedPos = peg$currPos;
|
|
2414
|
+
s1 = peg$f66();
|
|
2415
|
+
if (s1) s1 = void 0;
|
|
2416
|
+
else s1 = peg$FAILED;
|
|
2417
|
+
if (s1 !== peg$FAILED) {
|
|
2418
|
+
s2 = peg$parseHtmlClose();
|
|
2419
|
+
if (s2 !== peg$FAILED) {
|
|
2420
|
+
peg$savedPos = peg$currPos;
|
|
2421
|
+
s3 = peg$f67(s2);
|
|
2422
|
+
if (s3) s3 = void 0;
|
|
2423
|
+
else s3 = peg$FAILED;
|
|
2424
|
+
if (s3 !== peg$FAILED) {
|
|
2425
|
+
peg$savedPos = s0;
|
|
2426
|
+
s0 = peg$f68(s2);
|
|
2427
|
+
} else {
|
|
2428
|
+
peg$currPos = s0;
|
|
2429
|
+
s0 = peg$FAILED;
|
|
2430
|
+
}
|
|
2431
|
+
} else {
|
|
2432
|
+
peg$currPos = s0;
|
|
2433
|
+
s0 = peg$FAILED;
|
|
2434
|
+
}
|
|
2435
|
+
} else {
|
|
2436
|
+
peg$currPos = s0;
|
|
2437
|
+
s0 = peg$FAILED;
|
|
2438
|
+
}
|
|
2439
|
+
return s0;
|
|
2440
|
+
}
|
|
2441
|
+
function peg$parseHtmlOpen() {
|
|
2442
|
+
let s0, s1, s2, s3, s4, s5, s6;
|
|
2443
|
+
s0 = peg$currPos;
|
|
2444
|
+
if (input.charCodeAt(peg$currPos) === 60) {
|
|
2445
|
+
s1 = peg$c2;
|
|
2446
|
+
peg$currPos++;
|
|
2447
|
+
} else {
|
|
2448
|
+
s1 = peg$FAILED;
|
|
2449
|
+
if (peg$silentFails === 0) peg$fail(peg$e6);
|
|
2450
|
+
}
|
|
2451
|
+
if (s1 !== peg$FAILED) {
|
|
2452
|
+
s2 = peg$parseTagName();
|
|
2453
|
+
if (s2 !== peg$FAILED) {
|
|
2454
|
+
s3 = [];
|
|
2455
|
+
s4 = peg$parseAttribute();
|
|
2456
|
+
while (s4 !== peg$FAILED) {
|
|
2457
|
+
s3.push(s4);
|
|
2458
|
+
s4 = peg$parseAttribute();
|
|
2459
|
+
}
|
|
2460
|
+
s4 = peg$parse_();
|
|
2461
|
+
if (input.charCodeAt(peg$currPos) === 47) {
|
|
2462
|
+
s5 = peg$c8;
|
|
2463
|
+
peg$currPos++;
|
|
2464
|
+
} else {
|
|
2465
|
+
s5 = peg$FAILED;
|
|
2466
|
+
if (peg$silentFails === 0) peg$fail(peg$e17);
|
|
2467
|
+
}
|
|
2468
|
+
if (s5 === peg$FAILED) s5 = null;
|
|
2469
|
+
if (input.charCodeAt(peg$currPos) === 62) {
|
|
2470
|
+
s6 = peg$c9;
|
|
2471
|
+
peg$currPos++;
|
|
2472
|
+
} else {
|
|
2473
|
+
s6 = peg$FAILED;
|
|
2474
|
+
if (peg$silentFails === 0) peg$fail(peg$e20);
|
|
2475
|
+
}
|
|
2476
|
+
if (s6 !== peg$FAILED) {
|
|
2477
|
+
peg$savedPos = s0;
|
|
2478
|
+
s0 = peg$f69(s2, s3, s5);
|
|
2479
|
+
} else {
|
|
2480
|
+
peg$currPos = s0;
|
|
2481
|
+
s0 = peg$FAILED;
|
|
2482
|
+
}
|
|
2483
|
+
} else {
|
|
2484
|
+
peg$currPos = s0;
|
|
2485
|
+
s0 = peg$FAILED;
|
|
2486
|
+
}
|
|
2487
|
+
} else {
|
|
2488
|
+
peg$currPos = s0;
|
|
2489
|
+
s0 = peg$FAILED;
|
|
2490
|
+
}
|
|
2491
|
+
if (s0 === peg$FAILED) {
|
|
2492
|
+
s0 = peg$currPos;
|
|
2493
|
+
if (input.charCodeAt(peg$currPos) === 60) {
|
|
2494
|
+
s1 = peg$c2;
|
|
2495
|
+
peg$currPos++;
|
|
2496
|
+
} else {
|
|
2497
|
+
s1 = peg$FAILED;
|
|
2498
|
+
if (peg$silentFails === 0) peg$fail(peg$e6);
|
|
2499
|
+
}
|
|
2500
|
+
if (s1 !== peg$FAILED) {
|
|
2501
|
+
s2 = peg$parseTagName();
|
|
2502
|
+
if (s2 !== peg$FAILED) {
|
|
2503
|
+
s3 = peg$currPos;
|
|
2504
|
+
peg$silentFails++;
|
|
2505
|
+
s4 = input.charAt(peg$currPos);
|
|
2506
|
+
if (peg$r10.test(s4)) peg$currPos++;
|
|
2507
|
+
else {
|
|
2508
|
+
s4 = peg$FAILED;
|
|
2509
|
+
if (peg$silentFails === 0) peg$fail(peg$e21);
|
|
2510
|
+
}
|
|
2511
|
+
if (s4 === peg$FAILED) {
|
|
2512
|
+
s4 = peg$currPos;
|
|
2513
|
+
peg$silentFails++;
|
|
2514
|
+
if (input.length > peg$currPos) {
|
|
2515
|
+
s5 = input.charAt(peg$currPos);
|
|
2516
|
+
peg$currPos++;
|
|
2517
|
+
} else {
|
|
2518
|
+
s5 = peg$FAILED;
|
|
2519
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2520
|
+
}
|
|
2521
|
+
peg$silentFails--;
|
|
2522
|
+
if (s5 === peg$FAILED) s4 = void 0;
|
|
2523
|
+
else {
|
|
2524
|
+
peg$currPos = s4;
|
|
2525
|
+
s4 = peg$FAILED;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
peg$silentFails--;
|
|
2529
|
+
if (s4 !== peg$FAILED) {
|
|
2530
|
+
peg$currPos = s3;
|
|
2531
|
+
s3 = void 0;
|
|
2532
|
+
} else s3 = peg$FAILED;
|
|
2533
|
+
if (s3 !== peg$FAILED) {
|
|
2534
|
+
s4 = [];
|
|
2535
|
+
s5 = peg$parseAttribute();
|
|
2536
|
+
while (s5 !== peg$FAILED) {
|
|
2537
|
+
s4.push(s5);
|
|
2538
|
+
s5 = peg$parseAttribute();
|
|
2539
|
+
}
|
|
2540
|
+
s5 = peg$parse_();
|
|
2541
|
+
s6 = peg$parseHere();
|
|
2542
|
+
peg$savedPos = s0;
|
|
2543
|
+
s0 = peg$f70(s2, s6);
|
|
2544
|
+
} else {
|
|
2545
|
+
peg$currPos = s0;
|
|
2546
|
+
s0 = peg$FAILED;
|
|
2547
|
+
}
|
|
2548
|
+
} else {
|
|
2549
|
+
peg$currPos = s0;
|
|
2550
|
+
s0 = peg$FAILED;
|
|
2551
|
+
}
|
|
2552
|
+
} else {
|
|
2553
|
+
peg$currPos = s0;
|
|
2554
|
+
s0 = peg$FAILED;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
return s0;
|
|
2558
|
+
}
|
|
2559
|
+
function peg$parseHtmlClose() {
|
|
2560
|
+
let s0, s1, s2, s4;
|
|
2561
|
+
s0 = peg$currPos;
|
|
2562
|
+
if (input.substr(peg$currPos, 2) === peg$c10) {
|
|
2563
|
+
s1 = peg$c10;
|
|
2564
|
+
peg$currPos += 2;
|
|
2565
|
+
} else {
|
|
2566
|
+
s1 = peg$FAILED;
|
|
2567
|
+
if (peg$silentFails === 0) peg$fail(peg$e22);
|
|
2568
|
+
}
|
|
2569
|
+
if (s1 !== peg$FAILED) {
|
|
2570
|
+
s2 = peg$parseTagName();
|
|
2571
|
+
if (s2 !== peg$FAILED) {
|
|
2572
|
+
peg$parse_();
|
|
2573
|
+
if (input.charCodeAt(peg$currPos) === 62) {
|
|
2574
|
+
s4 = peg$c9;
|
|
2575
|
+
peg$currPos++;
|
|
2576
|
+
} else {
|
|
2577
|
+
s4 = peg$FAILED;
|
|
2578
|
+
if (peg$silentFails === 0) peg$fail(peg$e20);
|
|
2579
|
+
}
|
|
2580
|
+
if (s4 !== peg$FAILED) {
|
|
2581
|
+
peg$savedPos = s0;
|
|
2582
|
+
s0 = peg$f71(s2);
|
|
2583
|
+
} else {
|
|
2584
|
+
peg$currPos = s0;
|
|
2585
|
+
s0 = peg$FAILED;
|
|
2586
|
+
}
|
|
2587
|
+
} else {
|
|
2588
|
+
peg$currPos = s0;
|
|
2589
|
+
s0 = peg$FAILED;
|
|
2590
|
+
}
|
|
2591
|
+
} else {
|
|
2592
|
+
peg$currPos = s0;
|
|
2593
|
+
s0 = peg$FAILED;
|
|
2594
|
+
}
|
|
2595
|
+
return s0;
|
|
2596
|
+
}
|
|
2597
|
+
function peg$parseTagName() {
|
|
2598
|
+
let s0, s1, s2, s3, s4;
|
|
2599
|
+
s0 = peg$currPos;
|
|
2600
|
+
s1 = peg$currPos;
|
|
2601
|
+
s2 = input.charAt(peg$currPos);
|
|
2602
|
+
if (peg$r8.test(s2)) peg$currPos++;
|
|
2603
|
+
else {
|
|
2604
|
+
s2 = peg$FAILED;
|
|
2605
|
+
if (peg$silentFails === 0) peg$fail(peg$e18);
|
|
2606
|
+
}
|
|
2607
|
+
if (s2 !== peg$FAILED) {
|
|
2608
|
+
s3 = [];
|
|
2609
|
+
s4 = input.charAt(peg$currPos);
|
|
2610
|
+
if (peg$r11.test(s4)) peg$currPos++;
|
|
2611
|
+
else {
|
|
2612
|
+
s4 = peg$FAILED;
|
|
2613
|
+
if (peg$silentFails === 0) peg$fail(peg$e23);
|
|
2614
|
+
}
|
|
2615
|
+
while (s4 !== peg$FAILED) {
|
|
2616
|
+
s3.push(s4);
|
|
2617
|
+
s4 = input.charAt(peg$currPos);
|
|
2618
|
+
if (peg$r11.test(s4)) peg$currPos++;
|
|
2619
|
+
else {
|
|
2620
|
+
s4 = peg$FAILED;
|
|
2621
|
+
if (peg$silentFails === 0) peg$fail(peg$e23);
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
s2 = [s2, s3];
|
|
2625
|
+
s1 = s2;
|
|
2626
|
+
} else {
|
|
2627
|
+
peg$currPos = s1;
|
|
2628
|
+
s1 = peg$FAILED;
|
|
2629
|
+
}
|
|
2630
|
+
if (s1 !== peg$FAILED) s0 = input.substring(s0, peg$currPos);
|
|
2631
|
+
else s0 = s1;
|
|
2632
|
+
return s0;
|
|
2633
|
+
}
|
|
2634
|
+
function peg$parseAttribute() {
|
|
2635
|
+
let s0, s2, s3, s4, s5, s6, s8;
|
|
2636
|
+
s0 = peg$currPos;
|
|
2637
|
+
peg$parse_();
|
|
2638
|
+
s2 = peg$currPos;
|
|
2639
|
+
s3 = [];
|
|
2640
|
+
s4 = peg$currPos;
|
|
2641
|
+
s5 = peg$currPos;
|
|
2642
|
+
peg$silentFails++;
|
|
2643
|
+
s6 = input.charAt(peg$currPos);
|
|
2644
|
+
if (peg$r12.test(s6)) peg$currPos++;
|
|
2645
|
+
else {
|
|
2646
|
+
s6 = peg$FAILED;
|
|
2647
|
+
if (peg$silentFails === 0) peg$fail(peg$e24);
|
|
2648
|
+
}
|
|
2649
|
+
peg$silentFails--;
|
|
2650
|
+
if (s6 === peg$FAILED) s5 = void 0;
|
|
2651
|
+
else {
|
|
2652
|
+
peg$currPos = s5;
|
|
2653
|
+
s5 = peg$FAILED;
|
|
2654
|
+
}
|
|
2655
|
+
if (s5 !== peg$FAILED) {
|
|
2656
|
+
if (input.length > peg$currPos) {
|
|
2657
|
+
s6 = input.charAt(peg$currPos);
|
|
2658
|
+
peg$currPos++;
|
|
2659
|
+
} else {
|
|
2660
|
+
s6 = peg$FAILED;
|
|
2661
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2662
|
+
}
|
|
2663
|
+
if (s6 !== peg$FAILED) {
|
|
2664
|
+
s5 = [s5, s6];
|
|
2665
|
+
s4 = s5;
|
|
2666
|
+
} else {
|
|
2667
|
+
peg$currPos = s4;
|
|
2668
|
+
s4 = peg$FAILED;
|
|
2669
|
+
}
|
|
2670
|
+
} else {
|
|
2671
|
+
peg$currPos = s4;
|
|
2672
|
+
s4 = peg$FAILED;
|
|
2673
|
+
}
|
|
2674
|
+
if (s4 !== peg$FAILED) while (s4 !== peg$FAILED) {
|
|
2675
|
+
s3.push(s4);
|
|
2676
|
+
s4 = peg$currPos;
|
|
2677
|
+
s5 = peg$currPos;
|
|
2678
|
+
peg$silentFails++;
|
|
2679
|
+
s6 = input.charAt(peg$currPos);
|
|
2680
|
+
if (peg$r12.test(s6)) peg$currPos++;
|
|
2681
|
+
else {
|
|
2682
|
+
s6 = peg$FAILED;
|
|
2683
|
+
if (peg$silentFails === 0) peg$fail(peg$e24);
|
|
2684
|
+
}
|
|
2685
|
+
peg$silentFails--;
|
|
2686
|
+
if (s6 === peg$FAILED) s5 = void 0;
|
|
2687
|
+
else {
|
|
2688
|
+
peg$currPos = s5;
|
|
2689
|
+
s5 = peg$FAILED;
|
|
2690
|
+
}
|
|
2691
|
+
if (s5 !== peg$FAILED) {
|
|
2692
|
+
if (input.length > peg$currPos) {
|
|
2693
|
+
s6 = input.charAt(peg$currPos);
|
|
2694
|
+
peg$currPos++;
|
|
2695
|
+
} else {
|
|
2696
|
+
s6 = peg$FAILED;
|
|
2697
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
2698
|
+
}
|
|
2699
|
+
if (s6 !== peg$FAILED) {
|
|
2700
|
+
s5 = [s5, s6];
|
|
2701
|
+
s4 = s5;
|
|
2702
|
+
} else {
|
|
2703
|
+
peg$currPos = s4;
|
|
2704
|
+
s4 = peg$FAILED;
|
|
2705
|
+
}
|
|
2706
|
+
} else {
|
|
2707
|
+
peg$currPos = s4;
|
|
2708
|
+
s4 = peg$FAILED;
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
else s3 = peg$FAILED;
|
|
2712
|
+
if (s3 !== peg$FAILED) s2 = input.substring(s2, peg$currPos);
|
|
2713
|
+
else s2 = s3;
|
|
2714
|
+
if (s2 !== peg$FAILED) {
|
|
2715
|
+
peg$savedPos = peg$currPos;
|
|
2716
|
+
s3 = peg$f72(s2);
|
|
2717
|
+
if (s3) s3 = void 0;
|
|
2718
|
+
else s3 = peg$FAILED;
|
|
2719
|
+
if (s3 !== peg$FAILED) {
|
|
2720
|
+
s4 = peg$currPos;
|
|
2721
|
+
s5 = peg$parse_();
|
|
2722
|
+
if (input.charCodeAt(peg$currPos) === 61) {
|
|
2723
|
+
s6 = peg$c11;
|
|
2724
|
+
peg$currPos++;
|
|
2725
|
+
} else {
|
|
2726
|
+
s6 = peg$FAILED;
|
|
2727
|
+
if (peg$silentFails === 0) peg$fail(peg$e25);
|
|
2728
|
+
}
|
|
2729
|
+
if (s6 !== peg$FAILED) {
|
|
2730
|
+
peg$parse_();
|
|
2731
|
+
s8 = peg$parseAttrValue();
|
|
2732
|
+
if (s8 !== peg$FAILED) {
|
|
2733
|
+
peg$savedPos = s4;
|
|
2734
|
+
s4 = peg$f73(s2, s8);
|
|
2735
|
+
} else {
|
|
2736
|
+
peg$currPos = s4;
|
|
2737
|
+
s4 = peg$FAILED;
|
|
2738
|
+
}
|
|
2739
|
+
} else {
|
|
2740
|
+
peg$currPos = s4;
|
|
2741
|
+
s4 = peg$FAILED;
|
|
2742
|
+
}
|
|
2743
|
+
if (s4 === peg$FAILED) s4 = null;
|
|
2744
|
+
peg$savedPos = s0;
|
|
2745
|
+
s0 = peg$f74(s2, s4);
|
|
2746
|
+
} else {
|
|
2747
|
+
peg$currPos = s0;
|
|
2748
|
+
s0 = peg$FAILED;
|
|
2749
|
+
}
|
|
2750
|
+
} else {
|
|
2751
|
+
peg$currPos = s0;
|
|
2752
|
+
s0 = peg$FAILED;
|
|
2753
|
+
}
|
|
2754
|
+
return s0;
|
|
2755
|
+
}
|
|
2756
|
+
function peg$parseAttrValue() {
|
|
2757
|
+
let s0, s1, s2, s3, s4;
|
|
2758
|
+
s0 = peg$currPos;
|
|
2759
|
+
if (input.charCodeAt(peg$currPos) === 34) {
|
|
2760
|
+
s1 = peg$c12;
|
|
2761
|
+
peg$currPos++;
|
|
2762
|
+
} else {
|
|
2763
|
+
s1 = peg$FAILED;
|
|
2764
|
+
if (peg$silentFails === 0) peg$fail(peg$e26);
|
|
2765
|
+
}
|
|
2766
|
+
if (s1 !== peg$FAILED) {
|
|
2767
|
+
s2 = peg$currPos;
|
|
2768
|
+
s3 = [];
|
|
2769
|
+
s4 = peg$parseValuePart();
|
|
2770
|
+
if (s4 === peg$FAILED) {
|
|
2771
|
+
s4 = input.charAt(peg$currPos);
|
|
2772
|
+
if (peg$r13.test(s4)) peg$currPos++;
|
|
2773
|
+
else {
|
|
2774
|
+
s4 = peg$FAILED;
|
|
2775
|
+
if (peg$silentFails === 0) peg$fail(peg$e27);
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
while (s4 !== peg$FAILED) {
|
|
2779
|
+
s3.push(s4);
|
|
2780
|
+
s4 = peg$parseValuePart();
|
|
2781
|
+
if (s4 === peg$FAILED) {
|
|
2782
|
+
s4 = input.charAt(peg$currPos);
|
|
2783
|
+
if (peg$r13.test(s4)) peg$currPos++;
|
|
2784
|
+
else {
|
|
2785
|
+
s4 = peg$FAILED;
|
|
2786
|
+
if (peg$silentFails === 0) peg$fail(peg$e27);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
s2 = input.substring(s2, peg$currPos);
|
|
2791
|
+
if (input.charCodeAt(peg$currPos) === 34) {
|
|
2792
|
+
s3 = peg$c12;
|
|
2793
|
+
peg$currPos++;
|
|
2794
|
+
} else {
|
|
2795
|
+
s3 = peg$FAILED;
|
|
2796
|
+
if (peg$silentFails === 0) peg$fail(peg$e26);
|
|
2797
|
+
}
|
|
2798
|
+
if (s3 !== peg$FAILED) {
|
|
2799
|
+
peg$savedPos = s0;
|
|
2800
|
+
s0 = peg$f75(s2);
|
|
2801
|
+
} else {
|
|
2802
|
+
peg$currPos = s0;
|
|
2803
|
+
s0 = peg$FAILED;
|
|
2804
|
+
}
|
|
2805
|
+
} else {
|
|
2806
|
+
peg$currPos = s0;
|
|
2807
|
+
s0 = peg$FAILED;
|
|
2808
|
+
}
|
|
2809
|
+
if (s0 === peg$FAILED) {
|
|
2810
|
+
s0 = peg$currPos;
|
|
2811
|
+
if (input.charCodeAt(peg$currPos) === 39) {
|
|
2812
|
+
s1 = peg$c13;
|
|
2813
|
+
peg$currPos++;
|
|
2814
|
+
} else {
|
|
2815
|
+
s1 = peg$FAILED;
|
|
2816
|
+
if (peg$silentFails === 0) peg$fail(peg$e28);
|
|
2817
|
+
}
|
|
2818
|
+
if (s1 !== peg$FAILED) {
|
|
2819
|
+
s2 = peg$currPos;
|
|
2820
|
+
s3 = [];
|
|
2821
|
+
s4 = peg$parseValuePart();
|
|
2822
|
+
if (s4 === peg$FAILED) {
|
|
2823
|
+
s4 = input.charAt(peg$currPos);
|
|
2824
|
+
if (peg$r14.test(s4)) peg$currPos++;
|
|
2825
|
+
else {
|
|
2826
|
+
s4 = peg$FAILED;
|
|
2827
|
+
if (peg$silentFails === 0) peg$fail(peg$e29);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
while (s4 !== peg$FAILED) {
|
|
2831
|
+
s3.push(s4);
|
|
2832
|
+
s4 = peg$parseValuePart();
|
|
2833
|
+
if (s4 === peg$FAILED) {
|
|
2834
|
+
s4 = input.charAt(peg$currPos);
|
|
2835
|
+
if (peg$r14.test(s4)) peg$currPos++;
|
|
2836
|
+
else {
|
|
2837
|
+
s4 = peg$FAILED;
|
|
2838
|
+
if (peg$silentFails === 0) peg$fail(peg$e29);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
s2 = input.substring(s2, peg$currPos);
|
|
2843
|
+
if (input.charCodeAt(peg$currPos) === 39) {
|
|
2844
|
+
s3 = peg$c13;
|
|
2845
|
+
peg$currPos++;
|
|
2846
|
+
} else {
|
|
2847
|
+
s3 = peg$FAILED;
|
|
2848
|
+
if (peg$silentFails === 0) peg$fail(peg$e28);
|
|
2849
|
+
}
|
|
2850
|
+
if (s3 !== peg$FAILED) {
|
|
2851
|
+
peg$savedPos = s0;
|
|
2852
|
+
s0 = peg$f76(s2);
|
|
2853
|
+
} else {
|
|
2854
|
+
peg$currPos = s0;
|
|
2855
|
+
s0 = peg$FAILED;
|
|
2856
|
+
}
|
|
2857
|
+
} else {
|
|
2858
|
+
peg$currPos = s0;
|
|
2859
|
+
s0 = peg$FAILED;
|
|
2860
|
+
}
|
|
2861
|
+
if (s0 === peg$FAILED) {
|
|
2862
|
+
s0 = peg$currPos;
|
|
2863
|
+
s1 = input.charAt(peg$currPos);
|
|
2864
|
+
if (peg$r15.test(s1)) peg$currPos++;
|
|
2865
|
+
else {
|
|
2866
|
+
s1 = peg$FAILED;
|
|
2867
|
+
if (peg$silentFails === 0) peg$fail(peg$e30);
|
|
2868
|
+
}
|
|
2869
|
+
if (s1 !== peg$FAILED) {
|
|
2870
|
+
peg$savedPos = s0;
|
|
2871
|
+
s1 = peg$f77(s1);
|
|
2872
|
+
}
|
|
2873
|
+
s0 = s1;
|
|
2874
|
+
if (s0 === peg$FAILED) {
|
|
2875
|
+
s0 = peg$currPos;
|
|
2876
|
+
s1 = [];
|
|
2877
|
+
s2 = input.charAt(peg$currPos);
|
|
2878
|
+
if (peg$r16.test(s2)) peg$currPos++;
|
|
2879
|
+
else {
|
|
2880
|
+
s2 = peg$FAILED;
|
|
2881
|
+
if (peg$silentFails === 0) peg$fail(peg$e31);
|
|
2882
|
+
}
|
|
2883
|
+
while (s2 !== peg$FAILED) {
|
|
2884
|
+
s1.push(s2);
|
|
2885
|
+
s2 = input.charAt(peg$currPos);
|
|
2886
|
+
if (peg$r16.test(s2)) peg$currPos++;
|
|
2887
|
+
else {
|
|
2888
|
+
s2 = peg$FAILED;
|
|
2889
|
+
if (peg$silentFails === 0) peg$fail(peg$e31);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
s0 = input.substring(s0, peg$currPos);
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
return s0;
|
|
2897
|
+
}
|
|
2898
|
+
function peg$parseValuePart() {
|
|
2899
|
+
let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
|
|
2900
|
+
s0 = peg$currPos;
|
|
2901
|
+
peg$savedPos = peg$currPos;
|
|
2902
|
+
s1 = peg$f78();
|
|
2903
|
+
if (s1) s1 = void 0;
|
|
2904
|
+
else s1 = peg$FAILED;
|
|
2905
|
+
if (s1 !== peg$FAILED) {
|
|
2906
|
+
s2 = peg$currPos;
|
|
2907
|
+
s3 = [];
|
|
2908
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2909
|
+
s4 = peg$c0;
|
|
2910
|
+
peg$currPos++;
|
|
2911
|
+
} else {
|
|
2912
|
+
s4 = peg$FAILED;
|
|
2913
|
+
if (peg$silentFails === 0) peg$fail(peg$e2);
|
|
2914
|
+
}
|
|
2915
|
+
if (s4 !== peg$FAILED) while (s4 !== peg$FAILED) {
|
|
2916
|
+
s3.push(s4);
|
|
2917
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2918
|
+
s4 = peg$c0;
|
|
2919
|
+
peg$currPos++;
|
|
2920
|
+
} else {
|
|
2921
|
+
s4 = peg$FAILED;
|
|
2922
|
+
if (peg$silentFails === 0) peg$fail(peg$e2);
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
else s3 = peg$FAILED;
|
|
2926
|
+
if (s3 !== peg$FAILED) s2 = input.substring(s2, peg$currPos);
|
|
2927
|
+
else s2 = s3;
|
|
2928
|
+
if (s2 !== peg$FAILED) {
|
|
2929
|
+
s3 = peg$currPos;
|
|
2930
|
+
peg$savedPos = peg$currPos;
|
|
2931
|
+
s4 = peg$f79(s2);
|
|
2932
|
+
if (s4) s4 = void 0;
|
|
2933
|
+
else s4 = peg$FAILED;
|
|
2934
|
+
if (s4 !== peg$FAILED) {
|
|
2935
|
+
s5 = input.charAt(peg$currPos);
|
|
2936
|
+
if (peg$r1.test(s5)) peg$currPos++;
|
|
2937
|
+
else {
|
|
2938
|
+
s5 = peg$FAILED;
|
|
2939
|
+
if (peg$silentFails === 0) peg$fail(peg$e3);
|
|
2940
|
+
}
|
|
2941
|
+
if (s5 !== peg$FAILED) {
|
|
2942
|
+
s4 = [s4, s5];
|
|
2943
|
+
s3 = s4;
|
|
2944
|
+
} else {
|
|
2945
|
+
peg$currPos = s3;
|
|
2946
|
+
s3 = peg$FAILED;
|
|
2947
|
+
}
|
|
2948
|
+
} else {
|
|
2949
|
+
peg$currPos = s3;
|
|
2950
|
+
s3 = peg$FAILED;
|
|
2951
|
+
}
|
|
2952
|
+
if (s3 === peg$FAILED) s3 = null;
|
|
2953
|
+
s1 = [
|
|
2954
|
+
s1,
|
|
2955
|
+
s2,
|
|
2956
|
+
s3
|
|
2957
|
+
];
|
|
2958
|
+
s0 = s1;
|
|
2959
|
+
} else {
|
|
2960
|
+
peg$currPos = s0;
|
|
2961
|
+
s0 = peg$FAILED;
|
|
2962
|
+
}
|
|
2963
|
+
} else {
|
|
2964
|
+
peg$currPos = s0;
|
|
2965
|
+
s0 = peg$FAILED;
|
|
2966
|
+
}
|
|
2967
|
+
if (s0 === peg$FAILED) {
|
|
2968
|
+
s0 = peg$currPos;
|
|
2969
|
+
peg$savedPos = peg$currPos;
|
|
2970
|
+
s1 = peg$f80();
|
|
2971
|
+
if (s1) s1 = void 0;
|
|
2972
|
+
else s1 = peg$FAILED;
|
|
2973
|
+
if (s1 !== peg$FAILED) {
|
|
2974
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
2975
|
+
s2 = peg$c1;
|
|
2976
|
+
peg$currPos++;
|
|
2977
|
+
} else {
|
|
2978
|
+
s2 = peg$FAILED;
|
|
2979
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
2980
|
+
}
|
|
2981
|
+
if (s2 !== peg$FAILED) {
|
|
2982
|
+
s3 = peg$parseSelectors();
|
|
2983
|
+
if (s3 !== peg$FAILED) {
|
|
2984
|
+
s4 = peg$parseHere();
|
|
2985
|
+
if (input.charCodeAt(peg$currPos) === 47) {
|
|
2986
|
+
s5 = peg$c8;
|
|
2987
|
+
peg$currPos++;
|
|
2988
|
+
} else {
|
|
2989
|
+
s5 = peg$FAILED;
|
|
2990
|
+
if (peg$silentFails === 0) peg$fail(peg$e17);
|
|
2991
|
+
}
|
|
2992
|
+
if (s5 === peg$FAILED) s5 = null;
|
|
2993
|
+
s6 = peg$parseMacroName();
|
|
2994
|
+
if (s6 !== peg$FAILED) {
|
|
2995
|
+
s7 = peg$parseHere();
|
|
2996
|
+
peg$savedPos = peg$currPos;
|
|
2997
|
+
s8 = peg$f81(s4, s7);
|
|
2998
|
+
if (s8) s8 = void 0;
|
|
2999
|
+
else s8 = peg$FAILED;
|
|
3000
|
+
if (s8 !== peg$FAILED) {
|
|
3001
|
+
s9 = peg$currPos;
|
|
3002
|
+
s10 = peg$f82(s4, s7);
|
|
3003
|
+
s11 = peg$currPos;
|
|
3004
|
+
s12 = [];
|
|
3005
|
+
if (s12.length >= (s10 | 0)) s13 = peg$FAILED;
|
|
3006
|
+
else if (input.length > peg$currPos) {
|
|
3007
|
+
s13 = input.charAt(peg$currPos);
|
|
3008
|
+
peg$currPos++;
|
|
3009
|
+
} else {
|
|
3010
|
+
s13 = peg$FAILED;
|
|
3011
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
3012
|
+
}
|
|
3013
|
+
while (s13 !== peg$FAILED) {
|
|
3014
|
+
s12.push(s13);
|
|
3015
|
+
if (s12.length >= (s10 | 0)) s13 = peg$FAILED;
|
|
3016
|
+
else if (input.length > peg$currPos) {
|
|
3017
|
+
s13 = input.charAt(peg$currPos);
|
|
3018
|
+
peg$currPos++;
|
|
3019
|
+
} else {
|
|
3020
|
+
s13 = peg$FAILED;
|
|
3021
|
+
if (peg$silentFails === 0) peg$fail(peg$e0);
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
if (s12.length < (s10 | 0)) {
|
|
3025
|
+
peg$currPos = s11;
|
|
3026
|
+
s11 = peg$FAILED;
|
|
3027
|
+
} else s11 = s12;
|
|
3028
|
+
s10 = s11;
|
|
3029
|
+
if (s10 !== peg$FAILED) s9 = input.substring(s9, peg$currPos);
|
|
3030
|
+
else s9 = s10;
|
|
3031
|
+
if (s9 !== peg$FAILED) {
|
|
3032
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
3033
|
+
s10 = peg$c7;
|
|
3034
|
+
peg$currPos++;
|
|
3035
|
+
} else {
|
|
3036
|
+
s10 = peg$FAILED;
|
|
3037
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
3038
|
+
}
|
|
3039
|
+
if (s10 !== peg$FAILED) {
|
|
3040
|
+
s1 = [
|
|
3041
|
+
s1,
|
|
3042
|
+
s2,
|
|
3043
|
+
s3,
|
|
3044
|
+
s4,
|
|
3045
|
+
s5,
|
|
3046
|
+
s6,
|
|
3047
|
+
s7,
|
|
3048
|
+
s8,
|
|
3049
|
+
s9,
|
|
3050
|
+
s10
|
|
3051
|
+
];
|
|
3052
|
+
s0 = s1;
|
|
3053
|
+
} else {
|
|
3054
|
+
peg$currPos = s0;
|
|
3055
|
+
s0 = peg$FAILED;
|
|
3056
|
+
}
|
|
3057
|
+
} else {
|
|
3058
|
+
peg$currPos = s0;
|
|
3059
|
+
s0 = peg$FAILED;
|
|
3060
|
+
}
|
|
3061
|
+
} else {
|
|
3062
|
+
peg$currPos = s0;
|
|
3063
|
+
s0 = peg$FAILED;
|
|
3064
|
+
}
|
|
3065
|
+
} else {
|
|
3066
|
+
peg$currPos = s0;
|
|
3067
|
+
s0 = peg$FAILED;
|
|
3068
|
+
}
|
|
3069
|
+
} else {
|
|
3070
|
+
peg$currPos = s0;
|
|
3071
|
+
s0 = peg$FAILED;
|
|
3072
|
+
}
|
|
3073
|
+
} else {
|
|
3074
|
+
peg$currPos = s0;
|
|
3075
|
+
s0 = peg$FAILED;
|
|
3076
|
+
}
|
|
3077
|
+
} else {
|
|
3078
|
+
peg$currPos = s0;
|
|
3079
|
+
s0 = peg$FAILED;
|
|
3080
|
+
}
|
|
3081
|
+
if (s0 === peg$FAILED) {
|
|
3082
|
+
s0 = peg$currPos;
|
|
3083
|
+
peg$savedPos = peg$currPos;
|
|
3084
|
+
s1 = peg$f83();
|
|
3085
|
+
if (s1) s1 = void 0;
|
|
3086
|
+
else s1 = peg$FAILED;
|
|
3087
|
+
if (s1 !== peg$FAILED) {
|
|
3088
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
3089
|
+
s2 = peg$c1;
|
|
3090
|
+
peg$currPos++;
|
|
3091
|
+
} else {
|
|
3092
|
+
s2 = peg$FAILED;
|
|
3093
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
3094
|
+
}
|
|
3095
|
+
if (s2 !== peg$FAILED) {
|
|
3096
|
+
s3 = peg$parseSelectors();
|
|
3097
|
+
if (s3 !== peg$FAILED) {
|
|
3098
|
+
s4 = peg$currPos;
|
|
3099
|
+
peg$silentFails++;
|
|
3100
|
+
s5 = peg$currPos;
|
|
3101
|
+
if (input.charCodeAt(peg$currPos) === 47) {
|
|
3102
|
+
s6 = peg$c8;
|
|
3103
|
+
peg$currPos++;
|
|
3104
|
+
} else {
|
|
3105
|
+
s6 = peg$FAILED;
|
|
3106
|
+
if (peg$silentFails === 0) peg$fail(peg$e17);
|
|
3107
|
+
}
|
|
3108
|
+
if (s6 === peg$FAILED) s6 = null;
|
|
3109
|
+
s7 = input.charAt(peg$currPos);
|
|
3110
|
+
if (peg$r8.test(s7)) peg$currPos++;
|
|
3111
|
+
else {
|
|
3112
|
+
s7 = peg$FAILED;
|
|
3113
|
+
if (peg$silentFails === 0) peg$fail(peg$e18);
|
|
3114
|
+
}
|
|
3115
|
+
if (s7 !== peg$FAILED) {
|
|
3116
|
+
s6 = [s6, s7];
|
|
3117
|
+
s5 = s6;
|
|
3118
|
+
} else {
|
|
3119
|
+
peg$currPos = s5;
|
|
3120
|
+
s5 = peg$FAILED;
|
|
3121
|
+
}
|
|
3122
|
+
peg$silentFails--;
|
|
3123
|
+
if (s5 === peg$FAILED) s4 = void 0;
|
|
3124
|
+
else {
|
|
3125
|
+
peg$currPos = s4;
|
|
3126
|
+
s4 = peg$FAILED;
|
|
3127
|
+
}
|
|
3128
|
+
if (s4 !== peg$FAILED) {
|
|
3129
|
+
s5 = peg$parseCodeToBrace();
|
|
3130
|
+
if (s5 !== peg$FAILED) {
|
|
3131
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
3132
|
+
s6 = peg$c7;
|
|
3133
|
+
peg$currPos++;
|
|
3134
|
+
} else {
|
|
3135
|
+
s6 = peg$FAILED;
|
|
3136
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
3137
|
+
}
|
|
3138
|
+
if (s6 !== peg$FAILED) {
|
|
3139
|
+
s1 = [
|
|
3140
|
+
s1,
|
|
3141
|
+
s2,
|
|
3142
|
+
s3,
|
|
3143
|
+
s4,
|
|
3144
|
+
s5,
|
|
3145
|
+
s6
|
|
3146
|
+
];
|
|
3147
|
+
s0 = s1;
|
|
3148
|
+
} else {
|
|
3149
|
+
peg$currPos = s0;
|
|
3150
|
+
s0 = peg$FAILED;
|
|
3151
|
+
}
|
|
3152
|
+
} else {
|
|
3153
|
+
peg$currPos = s0;
|
|
3154
|
+
s0 = peg$FAILED;
|
|
3155
|
+
}
|
|
3156
|
+
} else {
|
|
3157
|
+
peg$currPos = s0;
|
|
3158
|
+
s0 = peg$FAILED;
|
|
3159
|
+
}
|
|
3160
|
+
} else {
|
|
3161
|
+
peg$currPos = s0;
|
|
3162
|
+
s0 = peg$FAILED;
|
|
3163
|
+
}
|
|
3164
|
+
} else {
|
|
3165
|
+
peg$currPos = s0;
|
|
3166
|
+
s0 = peg$FAILED;
|
|
3167
|
+
}
|
|
3168
|
+
} else {
|
|
3169
|
+
peg$currPos = s0;
|
|
3170
|
+
s0 = peg$FAILED;
|
|
3171
|
+
}
|
|
3172
|
+
if (s0 === peg$FAILED) {
|
|
3173
|
+
s0 = peg$currPos;
|
|
3174
|
+
peg$savedPos = peg$currPos;
|
|
3175
|
+
s1 = peg$f84();
|
|
3176
|
+
if (s1) s1 = void 0;
|
|
3177
|
+
else s1 = peg$FAILED;
|
|
3178
|
+
if (s1 !== peg$FAILED) {
|
|
3179
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
3180
|
+
s2 = peg$c1;
|
|
3181
|
+
peg$currPos++;
|
|
3182
|
+
} else {
|
|
3183
|
+
s2 = peg$FAILED;
|
|
3184
|
+
if (peg$silentFails === 0) peg$fail(peg$e4);
|
|
3185
|
+
}
|
|
3186
|
+
if (s2 !== peg$FAILED) {
|
|
3187
|
+
s3 = peg$currPos;
|
|
3188
|
+
peg$silentFails++;
|
|
3189
|
+
s4 = input.charAt(peg$currPos);
|
|
3190
|
+
if (peg$r5.test(s4)) peg$currPos++;
|
|
3191
|
+
else {
|
|
3192
|
+
s4 = peg$FAILED;
|
|
3193
|
+
if (peg$silentFails === 0) peg$fail(peg$e13);
|
|
3194
|
+
}
|
|
3195
|
+
peg$silentFails--;
|
|
3196
|
+
if (s4 !== peg$FAILED) {
|
|
3197
|
+
peg$currPos = s3;
|
|
3198
|
+
s3 = void 0;
|
|
3199
|
+
} else s3 = peg$FAILED;
|
|
3200
|
+
if (s3 !== peg$FAILED) {
|
|
3201
|
+
s4 = peg$parseCodeToBrace();
|
|
3202
|
+
if (s4 !== peg$FAILED) {
|
|
3203
|
+
if (input.charCodeAt(peg$currPos) === 125) {
|
|
3204
|
+
s5 = peg$c7;
|
|
3205
|
+
peg$currPos++;
|
|
3206
|
+
} else {
|
|
3207
|
+
s5 = peg$FAILED;
|
|
3208
|
+
if (peg$silentFails === 0) peg$fail(peg$e15);
|
|
3209
|
+
}
|
|
3210
|
+
if (s5 !== peg$FAILED) {
|
|
3211
|
+
s1 = [
|
|
3212
|
+
s1,
|
|
3213
|
+
s2,
|
|
3214
|
+
s3,
|
|
3215
|
+
s4,
|
|
3216
|
+
s5
|
|
3217
|
+
];
|
|
3218
|
+
s0 = s1;
|
|
3219
|
+
} else {
|
|
3220
|
+
peg$currPos = s0;
|
|
3221
|
+
s0 = peg$FAILED;
|
|
3222
|
+
}
|
|
3223
|
+
} else {
|
|
3224
|
+
peg$currPos = s0;
|
|
3225
|
+
s0 = peg$FAILED;
|
|
3226
|
+
}
|
|
3227
|
+
} else {
|
|
3228
|
+
peg$currPos = s0;
|
|
3229
|
+
s0 = peg$FAILED;
|
|
3230
|
+
}
|
|
3231
|
+
} else {
|
|
3232
|
+
peg$currPos = s0;
|
|
3233
|
+
s0 = peg$FAILED;
|
|
3234
|
+
}
|
|
3235
|
+
} else {
|
|
3236
|
+
peg$currPos = s0;
|
|
3237
|
+
s0 = peg$FAILED;
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
return s0;
|
|
3243
|
+
}
|
|
3244
|
+
function peg$parse_() {
|
|
3245
|
+
let s0, s1;
|
|
3246
|
+
s0 = [];
|
|
3247
|
+
s1 = peg$parse_c();
|
|
3248
|
+
while (s1 !== peg$FAILED) {
|
|
3249
|
+
s0.push(s1);
|
|
3250
|
+
s1 = peg$parse_c();
|
|
3251
|
+
}
|
|
3252
|
+
return s0;
|
|
3253
|
+
}
|
|
3254
|
+
function peg$parse_c() {
|
|
3255
|
+
let s0;
|
|
3256
|
+
s0 = input.charAt(peg$currPos);
|
|
3257
|
+
if (peg$r17.test(s0)) peg$currPos++;
|
|
3258
|
+
else {
|
|
3259
|
+
s0 = peg$FAILED;
|
|
3260
|
+
if (peg$silentFails === 0) peg$fail(peg$e32);
|
|
3261
|
+
}
|
|
3262
|
+
return s0;
|
|
3263
|
+
}
|
|
3264
|
+
const textMode = options.text === true;
|
|
3265
|
+
const hooks = options.hooks;
|
|
3266
|
+
/** End of the stretch a `.|n|` repetition consumes (see skipTo). */
|
|
3267
|
+
let skipEnd = -1;
|
|
3268
|
+
/** Whether the attribute whose value is being read holds code. */
|
|
3269
|
+
let attrCode = false;
|
|
3270
|
+
/** The macro whose raw body is being read. */
|
|
3271
|
+
let rawName = "";
|
|
3272
|
+
function skipTo(end) {
|
|
3273
|
+
skipEnd = end;
|
|
3274
|
+
return end >= 0;
|
|
3275
|
+
}
|
|
3276
|
+
function fail(message, loc) {
|
|
3277
|
+
error(message, loc);
|
|
3278
|
+
}
|
|
3279
|
+
function attrs(list) {
|
|
3280
|
+
const attributes = {};
|
|
3281
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3282
|
+
for (const [name, value] of list) {
|
|
3283
|
+
const lower = name.toLowerCase();
|
|
3284
|
+
if (seen.has(lower)) continue;
|
|
3285
|
+
seen.add(lower);
|
|
3286
|
+
Object.defineProperty(attributes, name, {
|
|
3287
|
+
value,
|
|
3288
|
+
enumerable: true,
|
|
3289
|
+
writable: true,
|
|
3290
|
+
configurable: true
|
|
3291
|
+
});
|
|
3292
|
+
}
|
|
3293
|
+
return attributes;
|
|
3294
|
+
}
|
|
3295
|
+
/** Check the body of a macro or element against its opening tag. */
|
|
3296
|
+
function checkBody(open, body) {
|
|
3297
|
+
for (const branch of body.branches) {
|
|
3298
|
+
const parent = BRANCH_PARENT[branch.tag.lower];
|
|
3299
|
+
if (open.lex !== "macro" || open.lower !== parent) fail(label(branch.tag) + " must be directly inside {" + parent + RB + ", not inside " + label(open), branch.tag.loc);
|
|
3300
|
+
}
|
|
3301
|
+
if (!body.end) fail("Unclosed " + label(open) + ": no " + closerOf(open) + " closes it", open.loc);
|
|
3302
|
+
if (!sameName(open, body.end)) fail(label(body.end) + " found where " + closerOf(open) + " should close the " + label(open) + " opened at " + at(open.loc), body.end.loc);
|
|
3303
|
+
}
|
|
3304
|
+
function macroNode(tag, body) {
|
|
3305
|
+
const node = {
|
|
3306
|
+
type: "macro",
|
|
3307
|
+
name: tag.lower,
|
|
3308
|
+
rawArgs: tag.rawArgs,
|
|
3309
|
+
children: []
|
|
3310
|
+
};
|
|
3311
|
+
if (!body) return withSelectors(node, tag);
|
|
3312
|
+
checkBody(tag, body);
|
|
3313
|
+
node.children = body.children;
|
|
3314
|
+
if (BRANCHING.has(tag.lower)) {
|
|
3315
|
+
node.branches = [withSelectors({
|
|
3316
|
+
rawArgs: tag.rawArgs,
|
|
3317
|
+
children: body.children
|
|
3318
|
+
}, tag)];
|
|
3319
|
+
for (const b of body.branches) node.branches.push(withSelectors({
|
|
3320
|
+
rawArgs: b.tag.rawArgs,
|
|
3321
|
+
children: b.children
|
|
3322
|
+
}, b.tag));
|
|
3323
|
+
node.children = [];
|
|
3324
|
+
} else withSelectors(node, tag);
|
|
3325
|
+
return node;
|
|
3326
|
+
}
|
|
3327
|
+
peg$result = peg$startRuleFunction();
|
|
3328
|
+
const peg$success = peg$result !== peg$FAILED && peg$currPos === input.length;
|
|
3329
|
+
function peg$throw() {
|
|
3330
|
+
if (peg$result !== peg$FAILED && peg$currPos < input.length) peg$fail(peg$endExpectation());
|
|
3331
|
+
throw peg$buildStructuredError(peg$maxFailExpected, peg$maxFailPos < input.length ? peg$getUnicode(peg$maxFailPos) : null, peg$maxFailPos < input.length ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) : peg$computeLocation(peg$maxFailPos, peg$maxFailPos));
|
|
3332
|
+
}
|
|
3333
|
+
if (options.peg$library) return {
|
|
3334
|
+
peg$result,
|
|
3335
|
+
peg$currPos,
|
|
3336
|
+
peg$FAILED,
|
|
3337
|
+
peg$maxFailExpected,
|
|
3338
|
+
peg$maxFailPos,
|
|
3339
|
+
peg$success,
|
|
3340
|
+
peg$throw: peg$success ? void 0 : peg$throw
|
|
3341
|
+
};
|
|
3342
|
+
if (peg$success) return peg$result;
|
|
3343
|
+
else peg$throw();
|
|
3344
|
+
}
|
|
3345
|
+
//#endregion
|
|
3346
|
+
//#region src/utils/macro-names.ts
|
|
3347
|
+
/**
|
|
3348
|
+
* Macro and widget names are case-insensitive: `{StatusBar}` invokes the
|
|
3349
|
+
* widget defined as `statusbar`. A NameMap keys its entries by the lowercased
|
|
3350
|
+
* name.
|
|
3351
|
+
*/
|
|
3352
|
+
var NameMap = class extends Map {
|
|
3353
|
+
get(name) {
|
|
3354
|
+
return super.get(name.toLowerCase());
|
|
3355
|
+
}
|
|
3356
|
+
set(name, value) {
|
|
3357
|
+
return super.set(name.toLowerCase(), value);
|
|
3358
|
+
}
|
|
3359
|
+
has(name) {
|
|
3360
|
+
return super.has(name.toLowerCase());
|
|
3361
|
+
}
|
|
3362
|
+
delete(name) {
|
|
3363
|
+
return super.delete(name.toLowerCase());
|
|
3364
|
+
}
|
|
3365
|
+
};
|
|
3366
|
+
/** A set of macro or widget names (see NameMap). */
|
|
3367
|
+
var NameSet = class {
|
|
3368
|
+
constructor(names = []) {
|
|
3369
|
+
this.names = new NameMap();
|
|
3370
|
+
for (const name of names) this.add(name);
|
|
3371
|
+
}
|
|
3372
|
+
add(name) {
|
|
3373
|
+
this.names.set(name, true);
|
|
3374
|
+
}
|
|
3375
|
+
has(name) {
|
|
3376
|
+
return this.names.has(name);
|
|
3377
|
+
}
|
|
3378
|
+
delete(name) {
|
|
3379
|
+
this.names.delete(name);
|
|
3380
|
+
}
|
|
3381
|
+
};
|
|
3382
|
+
//#endregion
|
|
3383
|
+
//#region src/markup/ast.ts
|
|
3384
|
+
/** Macros that require a closing tag and can contain children */
|
|
3385
|
+
var BLOCK_MACROS = new NameSet([
|
|
3386
|
+
"if",
|
|
3387
|
+
"for",
|
|
3388
|
+
"do",
|
|
3389
|
+
"button",
|
|
3390
|
+
"link",
|
|
3391
|
+
"listbox",
|
|
3392
|
+
"cycle",
|
|
3393
|
+
"switch",
|
|
3394
|
+
"timed",
|
|
3395
|
+
"repeat",
|
|
3396
|
+
"type",
|
|
3397
|
+
"widget",
|
|
3398
|
+
"span",
|
|
3399
|
+
"nobr"
|
|
3400
|
+
]);
|
|
3401
|
+
/** Whether a macro takes a body closed by `{/name}`. */
|
|
3402
|
+
function isBlockMacro(name) {
|
|
3403
|
+
return BLOCK_MACROS.has(name);
|
|
3404
|
+
}
|
|
3405
|
+
//#endregion
|
|
3406
|
+
//#region src/markup/tokens.ts
|
|
3407
|
+
/** Variable sigils: story ($), temporary (_), local (@), transient (%). */
|
|
3408
|
+
var SIGIL_SCOPES = {
|
|
3409
|
+
$: "variable",
|
|
3410
|
+
_: "temporary",
|
|
3411
|
+
"@": "local",
|
|
3412
|
+
"%": "transient"
|
|
3413
|
+
};
|
|
3414
|
+
Object.fromEntries(Object.entries(SIGIL_SCOPES).map(([sigil, scope]) => [scope, sigil]));
|
|
3415
|
+
new Set(Object.keys(SIGIL_SCOPES));
|
|
3416
|
+
//#endregion
|
|
1
3417
|
//#region src/js-lexer.ts
|
|
2
3418
|
/** Transient name after `%`: an identifier, so `%3` is never a reference. */
|
|
3
3419
|
var TRANS_NAME_RE = /[A-Za-z_]\w*/y;
|
|
@@ -277,26 +3693,6 @@ function frameKey(f) {
|
|
|
277
3693
|
const kind = f.interpolation ? 4 : FRAME_KINDS.indexOf(f.kind);
|
|
278
3694
|
return kind < 0 ? void 0 : f.open * 5 + kind;
|
|
279
3695
|
}
|
|
280
|
-
function createJsScanCache() {
|
|
281
|
-
return {
|
|
282
|
-
checkpoints: /* @__PURE__ */ new Map(),
|
|
283
|
-
stacks: /* @__PURE__ */ new Map(),
|
|
284
|
-
parens: /* @__PURE__ */ new Map(),
|
|
285
|
-
shareAfter: SHARE_AFTER,
|
|
286
|
-
braces: /* @__PURE__ */ new Map(),
|
|
287
|
-
brackets: /* @__PURE__ */ new Map(),
|
|
288
|
-
classes: /* @__PURE__ */ new Map(),
|
|
289
|
-
regexes: /* @__PURE__ */ new Map(),
|
|
290
|
-
lineEnd: {
|
|
291
|
-
from: Infinity,
|
|
292
|
-
at: -1
|
|
293
|
-
},
|
|
294
|
-
commentClose: {
|
|
295
|
-
from: Infinity,
|
|
296
|
-
at: -1
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
3696
|
var newContext = () => ({
|
|
301
3697
|
lookahead: true,
|
|
302
3698
|
brackets: /* @__PURE__ */ new Map()
|
|
@@ -1105,6 +4501,95 @@ function scan(src, handlers, start, nesting, outer, ctx) {
|
|
|
1105
4501
|
}
|
|
1106
4502
|
}
|
|
1107
4503
|
//#endregion
|
|
4504
|
+
//#region src/markup/code-end.ts
|
|
4505
|
+
/**
|
|
4506
|
+
* A quote directly after a letter/digit is an apostrophe (don't), not a
|
|
4507
|
+
* string; after a backslash it is an escaped attribute delimiter (\").
|
|
4508
|
+
*/
|
|
4509
|
+
var NON_STRING_QUOTE_PREFIX = /[\p{L}\p{N}_\\]/u;
|
|
4510
|
+
/**
|
|
4511
|
+
* Skip the literal opening at `i`: a '…' or "…" string, which must close on
|
|
4512
|
+
* its line, or a `…` template, whose `${…}` parts are read as braces.
|
|
4513
|
+
* Returns the index just past its closing quote or backtick, or -1.
|
|
4514
|
+
*/
|
|
4515
|
+
function skipLiteral(input, i) {
|
|
4516
|
+
const quote = input[i];
|
|
4517
|
+
const template = quote === "`";
|
|
4518
|
+
for (let j = i + 1; j < input.length;) {
|
|
4519
|
+
const c = input[j];
|
|
4520
|
+
if (c === "\\") j += 2;
|
|
4521
|
+
else if (c === quote) return j + 1;
|
|
4522
|
+
else if (!template && c === "\n") return -1;
|
|
4523
|
+
else if (template && c === "$" && input[j + 1] === "{") {
|
|
4524
|
+
const close = lenientClose(input, j + 2);
|
|
4525
|
+
if (close === -1) return -1;
|
|
4526
|
+
j = close + 1;
|
|
4527
|
+
} else j++;
|
|
4528
|
+
}
|
|
4529
|
+
return -1;
|
|
4530
|
+
}
|
|
4531
|
+
/**
|
|
4532
|
+
* The closing `}` of braces read leniently from `i` (just past a `{`): braces
|
|
4533
|
+
* count except inside string and template literals, and a quote that can't
|
|
4534
|
+
* start a string (an apostrophe, or one not closed on its line) is text, as
|
|
4535
|
+
* is a backtick without a closing one.
|
|
4536
|
+
*/
|
|
4537
|
+
function lenientClose(input, i) {
|
|
4538
|
+
if (memoInput !== input) {
|
|
4539
|
+
memoInput = input;
|
|
4540
|
+
memo.clear();
|
|
4541
|
+
}
|
|
4542
|
+
let end = memo.get(i);
|
|
4543
|
+
if (end === void 0) {
|
|
4544
|
+
end = scanLenient(input, i);
|
|
4545
|
+
memo.set(i, end);
|
|
4546
|
+
}
|
|
4547
|
+
return end;
|
|
4548
|
+
}
|
|
4549
|
+
var memoInput = "";
|
|
4550
|
+
var memo = /* @__PURE__ */ new Map();
|
|
4551
|
+
function scanLenient(input, i) {
|
|
4552
|
+
let depth = 0;
|
|
4553
|
+
while (i < input.length) {
|
|
4554
|
+
const c = input[i];
|
|
4555
|
+
if (c === "{") {
|
|
4556
|
+
depth++;
|
|
4557
|
+
i++;
|
|
4558
|
+
} else if (c === "}") {
|
|
4559
|
+
if (depth === 0) return i;
|
|
4560
|
+
depth--;
|
|
4561
|
+
i++;
|
|
4562
|
+
} else if (c === "`" || (c === "\"" || c === "'") && !(i > 0 && NON_STRING_QUOTE_PREFIX.test(input[i - 1]))) {
|
|
4563
|
+
const close = skipLiteral(input, i);
|
|
4564
|
+
i = close === -1 ? i + 1 : close;
|
|
4565
|
+
} else i++;
|
|
4566
|
+
}
|
|
4567
|
+
return -1;
|
|
4568
|
+
}
|
|
4569
|
+
/** The JavaScript reader Spindle uses today: js-lexer, then a lenient scan. */
|
|
4570
|
+
var defaultCodeEnd = {
|
|
4571
|
+
closeBrace(input, codeStart, lenientStart) {
|
|
4572
|
+
const end = findCodeEnd(input, codeStart);
|
|
4573
|
+
return end !== -1 ? end : lenientClose(input, lenientStart);
|
|
4574
|
+
},
|
|
4575
|
+
rawBodyEnd(input, bodyStart, name) {
|
|
4576
|
+
const closer = `\\{/${name}\\s*\\}`;
|
|
4577
|
+
const first = new RegExp(closer, "gi");
|
|
4578
|
+
first.lastIndex = bodyStart;
|
|
4579
|
+
const firstAt = first.exec(input)?.index ?? -1;
|
|
4580
|
+
if (firstAt === -1) return -1;
|
|
4581
|
+
const at = new RegExp(closer, "iy");
|
|
4582
|
+
const end = findCodeEnd(input, bodyStart, {
|
|
4583
|
+
goal: "statements",
|
|
4584
|
+
stop: (k) => {
|
|
4585
|
+
at.lastIndex = k;
|
|
4586
|
+
return at.test(input);
|
|
4587
|
+
}
|
|
4588
|
+
});
|
|
4589
|
+
return end === -1 ? firstAt : end;
|
|
4590
|
+
}
|
|
4591
|
+
};
|
|
4592
|
+
//#endregion
|
|
1108
4593
|
//#region src/markup/code-attributes.ts
|
|
1109
4594
|
/**
|
|
1110
4595
|
* Attributes whose value is code with braces of its own, not text: event
|
|
@@ -1118,811 +4603,558 @@ function isCodeAttribute(name) {
|
|
|
1118
4603
|
const lower = name.toLowerCase();
|
|
1119
4604
|
return lower.startsWith("on") || lower === "pattern" || lower === "srcdoc";
|
|
1120
4605
|
}
|
|
4606
|
+
//#endregion
|
|
4607
|
+
//#region src/markup/parse.ts
|
|
1121
4608
|
/**
|
|
1122
|
-
*
|
|
1123
|
-
*
|
|
1124
|
-
*
|
|
1125
|
-
* sigil is not followed by a word character (`{$(…)}`) is code, kept
|
|
1126
|
-
* verbatim: not resolved, and not decoded like text.
|
|
4609
|
+
* Passage markup parser: the Peggy grammar (spindle.peggy) with Spindle's
|
|
4610
|
+
* hooks plugged in. It builds the AST directly and reports malformed markup
|
|
4611
|
+
* as a MarkupError carrying its line and column.
|
|
1127
4612
|
*/
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
}
|
|
1146
|
-
if (text) parts.push({ text });
|
|
1147
|
-
text = "";
|
|
1148
|
-
const block = template.slice(i, end);
|
|
1149
|
-
parts.push(/^.\w/.test(block) ? { expr: block } : { verbatim: `{${block}}` });
|
|
1150
|
-
i = end + 1;
|
|
4613
|
+
/** Macros whose body is JavaScript source, kept verbatim. */
|
|
4614
|
+
var RAW_BODY_MACROS = new Set(["do"]);
|
|
4615
|
+
var defaultHooks = {
|
|
4616
|
+
...defaultCodeEnd,
|
|
4617
|
+
isBlock: isBlockMacro,
|
|
4618
|
+
isRaw: (name) => RAW_BODY_MACROS.has(name),
|
|
4619
|
+
isCodeAttribute
|
|
4620
|
+
};
|
|
4621
|
+
/** Malformed markup, with where it starts (1-based line and column). */
|
|
4622
|
+
var MarkupError = class extends Error {
|
|
4623
|
+
constructor(reason, offset, line, column) {
|
|
4624
|
+
super(`${reason} (line ${line}, column ${column})`);
|
|
4625
|
+
this.reason = reason;
|
|
4626
|
+
this.offset = offset;
|
|
4627
|
+
this.line = line;
|
|
4628
|
+
this.column = column;
|
|
4629
|
+
this.name = "MarkupError";
|
|
1151
4630
|
}
|
|
1152
|
-
if (text) parts.push({ text });
|
|
1153
|
-
return parts;
|
|
1154
|
-
}
|
|
1155
|
-
//#endregion
|
|
1156
|
-
//#region src/markup/tokenizer.ts
|
|
1157
|
-
/** Variable sigils: story ($), temporary (_), local (@), transient (%). */
|
|
1158
|
-
var SIGIL_SCOPES = {
|
|
1159
|
-
$: "variable",
|
|
1160
|
-
_: "temporary",
|
|
1161
|
-
"@": "local",
|
|
1162
|
-
"%": "transient"
|
|
1163
4631
|
};
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
4632
|
+
/** 1-based line and column of `offset` in `text`. */
|
|
4633
|
+
function lineColumn(text, offset) {
|
|
4634
|
+
let line = 1;
|
|
4635
|
+
let lineStart = 0;
|
|
4636
|
+
for (let i = text.indexOf("\n"); i !== -1 && i < offset;) {
|
|
4637
|
+
line++;
|
|
4638
|
+
lineStart = i + 1;
|
|
4639
|
+
i = text.indexOf("\n", lineStart);
|
|
4640
|
+
}
|
|
4641
|
+
return {
|
|
4642
|
+
line,
|
|
4643
|
+
column: offset - lineStart + 1
|
|
4644
|
+
};
|
|
4645
|
+
}
|
|
4646
|
+
function run(source, startRule, options) {
|
|
4647
|
+
const hooks = options.hooks ? {
|
|
4648
|
+
...defaultHooks,
|
|
4649
|
+
...options.hooks
|
|
4650
|
+
} : defaultHooks;
|
|
4651
|
+
try {
|
|
4652
|
+
return peg$parse(source, {
|
|
4653
|
+
startRule,
|
|
4654
|
+
text: options.text === true,
|
|
4655
|
+
hooks
|
|
4656
|
+
});
|
|
4657
|
+
} catch (err) {
|
|
4658
|
+
const location = err.location;
|
|
4659
|
+
if (err instanceof Error && err.name === "SyntaxError" && location) {
|
|
4660
|
+
const { offset } = location.start;
|
|
4661
|
+
const { line, column } = lineColumn(source, offset);
|
|
4662
|
+
throw new MarkupError(err.message, offset, line, column);
|
|
4663
|
+
}
|
|
4664
|
+
throw err;
|
|
4665
|
+
}
|
|
1175
4666
|
}
|
|
1176
|
-
/** Tag name must start with a letter (covers standard and custom elements). */
|
|
1177
|
-
var VALID_TAG_START = /[a-zA-Z]/;
|
|
1178
|
-
/** HTML void elements: never have children or a closing tag. */
|
|
1179
|
-
var HTML_VOID_TAGS = new Set([
|
|
1180
|
-
"area",
|
|
1181
|
-
"base",
|
|
1182
|
-
"br",
|
|
1183
|
-
"col",
|
|
1184
|
-
"embed",
|
|
1185
|
-
"hr",
|
|
1186
|
-
"img",
|
|
1187
|
-
"input",
|
|
1188
|
-
"link",
|
|
1189
|
-
"meta",
|
|
1190
|
-
"param",
|
|
1191
|
-
"source",
|
|
1192
|
-
"track",
|
|
1193
|
-
"wbr"
|
|
1194
|
-
]);
|
|
1195
4667
|
/**
|
|
1196
|
-
*
|
|
1197
|
-
*
|
|
1198
|
-
* expression (quotes, digits, `[`, `-`) are left out, because braces around
|
|
1199
|
-
* them are common as literal text (JSON, regex quantifiers, `{[[link]]}`).
|
|
4668
|
+
* Parse markup into its AST: macros with their bodies and branches, HTML
|
|
4669
|
+
* elements with their children. Throws a MarkupError for malformed markup.
|
|
1200
4670
|
*/
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
4671
|
+
function parseMarkup(source, options = {}) {
|
|
4672
|
+
return run(source, "Markup", options);
|
|
4673
|
+
}
|
|
1204
4674
|
/**
|
|
1205
|
-
*
|
|
1206
|
-
*
|
|
4675
|
+
* The flat tokens of markup, without nesting, so unclosed or mismatched
|
|
4676
|
+
* macros and elements are no error here. Throws a MarkupError for a
|
|
4677
|
+
* malformed tag, such as an unclosed `{`, `[[` or attribute value.
|
|
1207
4678
|
*/
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
4679
|
+
function tokenizeMarkup(source, options = {}) {
|
|
4680
|
+
return run(source, "Tokens", options);
|
|
4681
|
+
}
|
|
4682
|
+
//#endregion
|
|
4683
|
+
//#region src/utils/parse-delay.ts
|
|
1213
4684
|
/**
|
|
1214
|
-
* Parse a
|
|
1215
|
-
* Supports:
|
|
4685
|
+
* Parse a delay string into milliseconds.
|
|
4686
|
+
* Supports: "2s" → 2000, "500ms" → 500, bare number → ms
|
|
1216
4687
|
*/
|
|
1217
|
-
function
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
const after = inner.slice(idx + separator.length).trim();
|
|
1223
|
-
return targetFirst ? {
|
|
1224
|
-
display: after,
|
|
1225
|
-
target: before
|
|
1226
|
-
} : {
|
|
1227
|
-
display: before,
|
|
1228
|
-
target: after
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
const trimmed = inner.trim();
|
|
1232
|
-
return {
|
|
1233
|
-
display: trimmed,
|
|
1234
|
-
target: trimmed
|
|
1235
|
-
};
|
|
4688
|
+
function parseDelay(str) {
|
|
4689
|
+
const trimmed = str.trim();
|
|
4690
|
+
if (trimmed.endsWith("ms")) return parseFloat(trimmed.slice(0, -2));
|
|
4691
|
+
if (trimmed.endsWith("s")) return parseFloat(trimmed.slice(0, -1)) * 1e3;
|
|
4692
|
+
return parseFloat(trimmed);
|
|
1236
4693
|
}
|
|
4694
|
+
//#endregion
|
|
4695
|
+
//#region src/components/macros/arg-utils.ts
|
|
1237
4696
|
/**
|
|
1238
|
-
*
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
4697
|
+
* Shared helpers for macros that split or read their raw argument text by
|
|
4698
|
+
* hand. Their lexical model is the expression lexer's (`js-lexer.ts`):
|
|
4699
|
+
* string, template and regex literals and comments are opaque (a backslash
|
|
4700
|
+
* inside a literal escapes the character after it, and `${…}` parts of a
|
|
4701
|
+
* template are code), `/` opens a regex only where an operand is expected,
|
|
4702
|
+
* and `(`/`[`/`{` nest.
|
|
1242
4703
|
*/
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
};
|
|
1253
|
-
return {
|
|
1254
|
-
name: rest.slice(0, spaceIdx),
|
|
1255
|
-
rawArgs: rest.slice(spaceIdx + 1).trim(),
|
|
1256
|
-
isClose
|
|
1257
|
-
};
|
|
4704
|
+
/** True for a whitespace character. */
|
|
4705
|
+
function isWhitespace(ch) {
|
|
4706
|
+
return /\s/.test(ch);
|
|
4707
|
+
}
|
|
4708
|
+
function isOpener(ch) {
|
|
4709
|
+
return ch === "(" || ch === "[" || ch === "{";
|
|
4710
|
+
}
|
|
4711
|
+
function isCloser(ch) {
|
|
4712
|
+
return ch === ")" || ch === "]" || ch === "}";
|
|
1258
4713
|
}
|
|
1259
4714
|
/**
|
|
1260
|
-
*
|
|
1261
|
-
*
|
|
1262
|
-
*
|
|
1263
|
-
* left out if empty), and the position after them: `startIdx` if there are
|
|
1264
|
-
* none.
|
|
4715
|
+
* Undo the escapes allowed in a literal quoted macro argument: `\"`, `\'`
|
|
4716
|
+
* and `\\` become `"`, `'` and `\`. Other backslash sequences (`\n`, `\d`)
|
|
4717
|
+
* are kept as written, so code and regex text inside the string survive.
|
|
1265
4718
|
*/
|
|
1266
|
-
function
|
|
1267
|
-
|
|
1268
|
-
let id = "";
|
|
1269
|
-
let i = startIdx;
|
|
1270
|
-
while (i < input.length && (input[i] === "." || input[i] === "#")) {
|
|
1271
|
-
const prefix = input[i];
|
|
1272
|
-
i++;
|
|
1273
|
-
let name = "";
|
|
1274
|
-
while (i < input.length) if (/[a-zA-Z0-9_-]/.test(input[i])) {
|
|
1275
|
-
name += input[i];
|
|
1276
|
-
i++;
|
|
1277
|
-
} else if (input[i] === "{" && isSigil(input[i + 1])) {
|
|
1278
|
-
const braceStart = i;
|
|
1279
|
-
i += 2;
|
|
1280
|
-
while (i < input.length && /[\w.]/.test(input[i])) i++;
|
|
1281
|
-
if (i < input.length && input[i] === "}") {
|
|
1282
|
-
i++;
|
|
1283
|
-
name += input.slice(braceStart, i);
|
|
1284
|
-
} else {
|
|
1285
|
-
i = braceStart;
|
|
1286
|
-
break;
|
|
1287
|
-
}
|
|
1288
|
-
} else break;
|
|
1289
|
-
if (name) if (prefix === ".") classes.push(name);
|
|
1290
|
-
else id = name;
|
|
1291
|
-
}
|
|
1292
|
-
if (i > startIdx && input[i] === " ") i++;
|
|
1293
|
-
return {
|
|
1294
|
-
selectors: withSelectors({}, {
|
|
1295
|
-
className: classes.join(" "),
|
|
1296
|
-
id
|
|
1297
|
-
}),
|
|
1298
|
-
end: i
|
|
1299
|
-
};
|
|
4719
|
+
function unescapeQuoted(body) {
|
|
4720
|
+
return body.replace(/\\(["'\\])/g, "$1");
|
|
1300
4721
|
}
|
|
1301
4722
|
/**
|
|
1302
|
-
*
|
|
1303
|
-
* Returns
|
|
4723
|
+
* Read the `"…"` or `'…'` string whose opening quote is at `start`.
|
|
4724
|
+
* Returns its unescaped value and the index just past the closing quote, or
|
|
4725
|
+
* `null` if there is no such quote at `start` or the string is unterminated.
|
|
1304
4726
|
*/
|
|
1305
|
-
function
|
|
1306
|
-
const
|
|
1307
|
-
|
|
4727
|
+
function readQuoted(src, start) {
|
|
4728
|
+
const quote = src[start];
|
|
4729
|
+
if (quote !== "\"" && quote !== "'") return null;
|
|
4730
|
+
const { end, closed } = scanStringLiteral(src, start);
|
|
4731
|
+
if (!closed) return null;
|
|
1308
4732
|
return {
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
const lower = name.toLowerCase();
|
|
1312
|
-
if (seen.has(lower)) return;
|
|
1313
|
-
seen.add(lower);
|
|
1314
|
-
Object.defineProperty(attributes, name, {
|
|
1315
|
-
value,
|
|
1316
|
-
enumerable: true,
|
|
1317
|
-
writable: true,
|
|
1318
|
-
configurable: true
|
|
1319
|
-
});
|
|
1320
|
-
})
|
|
4733
|
+
value: unescapeQuoted(src.slice(start + 1, end - 1)),
|
|
4734
|
+
end
|
|
1321
4735
|
};
|
|
1322
4736
|
}
|
|
1323
4737
|
/**
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
* Where the attributes end depends only on where an attribute starts, so
|
|
1328
|
-
* without `add` the result is recorded for every attribute start passed (in
|
|
1329
|
-
* `memo.tag`) and a recorded one is used instead of scanning on. An unquoted
|
|
1330
|
-
* value takes in a `<`, so in `<a x=<a x=<a x=…` each opener's scan would
|
|
1331
|
-
* otherwise run over all the openers after it, taking quadratic time. A tag
|
|
1332
|
-
* whose attributes end in its `>` is consumed, so collecting the attributes
|
|
1333
|
-
* of those (with `add`, unrecorded) reads each character once.
|
|
4738
|
+
* The unescaped value of `src` when it is exactly one `"…"` or `'…'` string
|
|
4739
|
+
* (as with `readQuoted`), otherwise `null`.
|
|
1334
4740
|
*/
|
|
1335
|
-
function
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1338
|
-
while (j < input.length && /\s/.test(input[j])) j++;
|
|
1339
|
-
if (!add) {
|
|
1340
|
-
const known = memo.tag.get(j);
|
|
1341
|
-
if (known !== void 0) {
|
|
1342
|
-
j = known;
|
|
1343
|
-
break;
|
|
1344
|
-
}
|
|
1345
|
-
passed.push(j);
|
|
1346
|
-
}
|
|
1347
|
-
if (j >= input.length || input[j] === ">" || input[j] === "/" && input[j + 1] === ">") break;
|
|
1348
|
-
const attrStart = j;
|
|
1349
|
-
while (j < input.length && /[a-zA-Z0-9_\-:@]/.test(input[j])) j++;
|
|
1350
|
-
const attrName = input.slice(attrStart, j);
|
|
1351
|
-
if (!attrName) break;
|
|
1352
|
-
let eqIdx = j;
|
|
1353
|
-
while (eqIdx < input.length && /\s/.test(input[eqIdx])) eqIdx++;
|
|
1354
|
-
if (input[eqIdx] === "=") {
|
|
1355
|
-
j = eqIdx + 1;
|
|
1356
|
-
while (j < input.length && /\s/.test(input[j])) j++;
|
|
1357
|
-
if (input[j] === "\"" || input[j] === "'") {
|
|
1358
|
-
const quote = input[j];
|
|
1359
|
-
j++;
|
|
1360
|
-
const valStart = j;
|
|
1361
|
-
j = scanQuotedValue(input, j, quote, isCodeAttribute(attrName), memo);
|
|
1362
|
-
add?.(attrName, input.slice(valStart, j));
|
|
1363
|
-
if (j < input.length) j++;
|
|
1364
|
-
} else {
|
|
1365
|
-
const valStart = j;
|
|
1366
|
-
const run = memo.unquoted;
|
|
1367
|
-
if (j < run.from || j > run.to) {
|
|
1368
|
-
run.from = j;
|
|
1369
|
-
while (j < input.length && /[^\s>]/.test(input[j])) j++;
|
|
1370
|
-
run.to = j;
|
|
1371
|
-
}
|
|
1372
|
-
j = run.to;
|
|
1373
|
-
add?.(attrName, input.slice(valStart, j));
|
|
1374
|
-
}
|
|
1375
|
-
} else add?.(attrName, "");
|
|
1376
|
-
}
|
|
1377
|
-
for (const at of passed) memo.tag.set(at, j);
|
|
1378
|
-
return j;
|
|
4741
|
+
function readWholeQuoted(src) {
|
|
4742
|
+
const quoted = readQuoted(src, 0);
|
|
4743
|
+
return quoted && quoted.end === src.length ? quoted.value : null;
|
|
1379
4744
|
}
|
|
1380
4745
|
/**
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
* (`isCodeAttribute`): only `{` and a sigil open a reference, other braces
|
|
1385
|
-
* and backslashes are text, as `splitSigilTemplate` reads them.
|
|
1386
|
-
*
|
|
1387
|
-
* The value reads the same from just past an interpolation, however the scan
|
|
1388
|
-
* got there, so the end is recorded there (in `memo.value`), and a recorded
|
|
1389
|
-
* one is used. An unclosed value that skips interpolations to the end of
|
|
1390
|
-
* the input (`<a x="}<a x={<a x="}…`) is then read once, not once per tag.
|
|
4746
|
+
* Strip an optional quote from each end of an unquoted-or-loosely-quoted
|
|
4747
|
+
* argument (`"Red`, `Red'`), leaving at least one character. This is the
|
|
4748
|
+
* lenient fallback for labels that are not one well-formed quoted string.
|
|
1391
4749
|
*/
|
|
1392
|
-
function
|
|
1393
|
-
|
|
1394
|
-
const passed = [];
|
|
1395
|
-
let checkpoint = true;
|
|
1396
|
-
while (j < input.length) {
|
|
1397
|
-
if (checkpoint) {
|
|
1398
|
-
const known = memo.value.get(j * 4 + variant);
|
|
1399
|
-
if (known !== void 0) {
|
|
1400
|
-
j = known;
|
|
1401
|
-
break;
|
|
1402
|
-
}
|
|
1403
|
-
passed.push(j * 4 + variant);
|
|
1404
|
-
checkpoint = false;
|
|
1405
|
-
}
|
|
1406
|
-
if (!code && input[j] === "\\") {
|
|
1407
|
-
let k = j + 1;
|
|
1408
|
-
while (input[k] === "\\") k++;
|
|
1409
|
-
j = (input[k] === "{" || input[k] === "}") && (k - j) % 2 === 1 ? k + 1 : k;
|
|
1410
|
-
continue;
|
|
1411
|
-
}
|
|
1412
|
-
if (input[j] === "{") {
|
|
1413
|
-
const closeIdx = !code ? scanBlockClose(input, j, memo) : isSigil(input[j + 1]) ? scanBalancedBrace(input, j + 1, memo) : -1;
|
|
1414
|
-
if (closeIdx !== -1) {
|
|
1415
|
-
j = closeIdx + 1;
|
|
1416
|
-
checkpoint = true;
|
|
1417
|
-
continue;
|
|
1418
|
-
}
|
|
1419
|
-
} else if (input[j] === quote) break;
|
|
1420
|
-
j++;
|
|
1421
|
-
}
|
|
1422
|
-
for (const at of passed) memo.value.set(at, j);
|
|
1423
|
-
return j;
|
|
4750
|
+
function stripLooseQuotes(src) {
|
|
4751
|
+
return /^["']?(.+?)["']?$/s.exec(src)?.[1] ?? src;
|
|
1424
4752
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
4753
|
+
/** An operator character, or an operator keyword, at the end of code. */
|
|
4754
|
+
var TRAILING_OPERATOR_RE = /(?:[-+*/%&|^!~=<>?:,.]|(?:^|[^\w$@.])(?:typeof|void|new|delete|in|instanceof|await|yield))$/;
|
|
4755
|
+
/**
|
|
4756
|
+
* Whether `src` ends with an operator that still needs an operand (`$a +`,
|
|
4757
|
+
* `$a+`, `$x ==`, `typeof`), so it cannot be a complete value on its own.
|
|
4758
|
+
* Only code counts: the closing `/` of a regex literal is not division, a
|
|
4759
|
+
* variable reference (`$a`, `%name`, ...) is an operand, trailing comments are skipped,
|
|
4760
|
+
* and a postfix `++` or `--` completes its operand.
|
|
4761
|
+
*/
|
|
4762
|
+
function endsWithOperator(src) {
|
|
4763
|
+
let end = -1;
|
|
4764
|
+
lexJs(src, {
|
|
4765
|
+
code(ch, i, nesting) {
|
|
4766
|
+
if (nesting === 0 && !isWhitespace(ch)) end = i + 1;
|
|
1435
4767
|
},
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
4768
|
+
literal(text, _i, nesting) {
|
|
4769
|
+
const comment = text.startsWith("//") || text.startsWith("/*");
|
|
4770
|
+
if (nesting === 0 && !comment) end = -1;
|
|
1439
4771
|
},
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
4772
|
+
variable(_sigil, _name, _i, nesting) {
|
|
4773
|
+
if (nesting === 0) end = -1;
|
|
4774
|
+
}
|
|
4775
|
+
});
|
|
4776
|
+
if (end < 0) return false;
|
|
4777
|
+
const code = src.slice(0, end);
|
|
4778
|
+
if (/(?:\+\+|--)$/.test(code)) return false;
|
|
4779
|
+
return TRAILING_OPERATOR_RE.test(code);
|
|
1445
4780
|
}
|
|
1446
4781
|
/**
|
|
1447
|
-
*
|
|
1448
|
-
*
|
|
1449
|
-
*
|
|
1450
|
-
* counts — not one in a string, template or regex literal or a comment —
|
|
1451
|
-
* and `/` after an operand divides.
|
|
1452
|
-
*
|
|
1453
|
-
* Text that is not well-formed JavaScript (an apostrophe, an unterminated
|
|
1454
|
-
* literal or comment, unbalanced brackets) is scanned leniently instead, as
|
|
1455
|
-
* prose-like macro arguments are: braces count except inside string and
|
|
1456
|
-
* template literals, and a quote that can't start a string (apostrophe,
|
|
1457
|
-
* escaped, not closed on its line) is text.
|
|
1458
|
-
*
|
|
1459
|
-
* Returns the index of the closing } or -1 if there is none. Pass the same
|
|
1460
|
-
* memo to repeated scans of one input to share their work.
|
|
4782
|
+
* Indices of the characters in `src` that satisfy `isSeparator` and sit at
|
|
4783
|
+
* depth 0: in code outside string, template and regex literals and comments,
|
|
4784
|
+
* and outside `()`, `[]` and `{}` pairs.
|
|
1461
4785
|
*/
|
|
1462
|
-
function
|
|
1463
|
-
|
|
4786
|
+
function topLevelIndices(src, isSeparator) {
|
|
4787
|
+
const indices = [];
|
|
4788
|
+
let depth = 0;
|
|
4789
|
+
lexJs(src, { code(ch, i, nesting) {
|
|
4790
|
+
if (nesting > 0) return;
|
|
4791
|
+
if (isOpener(ch)) depth++;
|
|
4792
|
+
else if (isCloser(ch)) depth--;
|
|
4793
|
+
else if (depth === 0 && isSeparator(ch)) indices.push(i);
|
|
4794
|
+
} });
|
|
4795
|
+
return indices;
|
|
1464
4796
|
}
|
|
4797
|
+
//#endregion
|
|
4798
|
+
//#region src/components/macros/macro-args.ts
|
|
1465
4799
|
/**
|
|
1466
|
-
*
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1469
|
-
*
|
|
4800
|
+
* The macro argument layer: reads a macro's raw argument text into the
|
|
4801
|
+
* parameters its definition declares (see ParameterDef), so every macro
|
|
4802
|
+
* splits and unquotes its arguments the same way. defineMacro() passes the
|
|
4803
|
+
* result to the macro as `ctx.args`.
|
|
4804
|
+
*
|
|
4805
|
+
* Arguments are read in groups, split at `separator` parameters. A group's
|
|
4806
|
+
* `flag` parameters are taken off its start or end first. Its last
|
|
4807
|
+
* `expression` or `text` parameter (without one, its last parameter) reads
|
|
4808
|
+
* the text the others leave; each parameter before it reads one term from
|
|
4809
|
+
* the start, and each after it one term from the end. Terms are separated by
|
|
4810
|
+
* whitespace outside literals and brackets (see arg-utils.ts), and a term
|
|
4811
|
+
* that follows an operator belongs to the expression before it. A parameter
|
|
4812
|
+
* with nothing to read is unset (a flag or separator is false, options are
|
|
4813
|
+
* empty).
|
|
1470
4814
|
*/
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
4815
|
+
/** The terms of `src`: the runs of text between its depth-0 whitespace. */
|
|
4816
|
+
function terms(src) {
|
|
4817
|
+
const spans = [];
|
|
4818
|
+
let start = 0;
|
|
4819
|
+
for (const i of [...topLevelIndices(src, isWhitespace), src.length]) {
|
|
4820
|
+
if (i > start) spans.push([start, i]);
|
|
4821
|
+
start = i + 1;
|
|
1478
4822
|
}
|
|
1479
|
-
return
|
|
4823
|
+
return spans;
|
|
1480
4824
|
}
|
|
4825
|
+
var slice = (src, [start, end]) => src.slice(start, end);
|
|
1481
4826
|
/**
|
|
1482
|
-
*
|
|
1483
|
-
*
|
|
1484
|
-
* after its name, an expression (`{$…}`, `{(…)}`, `{!…}`) from its first
|
|
1485
|
-
* character, after any `.class#id` selectors. Any other block is scanned as
|
|
1486
|
-
* code from just past the {. Returns -1 if it is unclosed.
|
|
4827
|
+
* The value of a `text` argument: one quoted string, or the text with any
|
|
4828
|
+
* loose quotes stripped (`"Red` → `Red`).
|
|
1487
4829
|
*/
|
|
1488
|
-
function
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
memo.code.set(lenientStart, end);
|
|
4830
|
+
function readText(src) {
|
|
4831
|
+
return readWholeQuoted(src) ?? stripLooseQuotes(src);
|
|
4832
|
+
}
|
|
4833
|
+
function readValue(param, src) {
|
|
4834
|
+
switch (param.type) {
|
|
4835
|
+
case "string": return readWholeQuoted(src) ?? void 0;
|
|
4836
|
+
case "text": return readText(src);
|
|
4837
|
+
case "names": return src.split(",").map((name) => name.trim());
|
|
4838
|
+
case "delay": return parseDelay(src);
|
|
4839
|
+
case "number": return Number(src);
|
|
4840
|
+
case "options": return readOptions(param.parameters ?? [], src);
|
|
4841
|
+
default: return src;
|
|
1501
4842
|
}
|
|
1502
|
-
return end;
|
|
1503
4843
|
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
let i = from;
|
|
1515
|
-
while (i < input.length) if (input[i] === "[" && input[i + 1] === "[") {
|
|
1516
|
-
i += 2;
|
|
1517
|
-
const inner = memo.link.get(i);
|
|
1518
|
-
if (inner === void 0) opens.push(i);
|
|
1519
|
-
else if (inner === -1) break;
|
|
1520
|
-
else i = inner + 2;
|
|
1521
|
-
} else if (input[i] === "]" && input[i + 1] === "]") {
|
|
1522
|
-
memo.link.set(opens.pop(), i);
|
|
1523
|
-
if (!opens.length) return i;
|
|
1524
|
-
i += 2;
|
|
1525
|
-
} else i++;
|
|
1526
|
-
for (const open of opens) memo.link.set(open, -1);
|
|
1527
|
-
return -1;
|
|
4844
|
+
function unset(param) {
|
|
4845
|
+
if (param.type === "flag" || param.type === "separator") return false;
|
|
4846
|
+
return param.type === "options" ? {} : void 0;
|
|
4847
|
+
}
|
|
4848
|
+
var WORD_RE = /\w+/y;
|
|
4849
|
+
var DIGITS_RE = /\d+/y;
|
|
4850
|
+
/** Match the sticky regex `re` at `pos`, returning the matched text. */
|
|
4851
|
+
function matchAt(re, src, pos) {
|
|
4852
|
+
re.lastIndex = pos;
|
|
4853
|
+
return re.exec(src)?.[0] ?? null;
|
|
1528
4854
|
}
|
|
1529
4855
|
/**
|
|
1530
|
-
*
|
|
1531
|
-
*
|
|
1532
|
-
*
|
|
4856
|
+
* Read keyword options (`goto "X" priority 5 once`). A keyword takes the
|
|
4857
|
+
* quoted string or digit run after it as its value; keywords that aren't
|
|
4858
|
+
* declared, and their values, are skipped.
|
|
1533
4859
|
*/
|
|
1534
|
-
function
|
|
1535
|
-
const
|
|
1536
|
-
let
|
|
1537
|
-
while (
|
|
1538
|
-
const
|
|
1539
|
-
if (
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
4860
|
+
function readOptions(params, src) {
|
|
4861
|
+
const options = {};
|
|
4862
|
+
let i = 0;
|
|
4863
|
+
while (i < src.length) {
|
|
4864
|
+
const key = matchAt(WORD_RE, src, i);
|
|
4865
|
+
if (!key) {
|
|
4866
|
+
i = readQuoted(src, i)?.end ?? i + 1;
|
|
4867
|
+
continue;
|
|
4868
|
+
}
|
|
4869
|
+
i += key.length;
|
|
4870
|
+
let val;
|
|
4871
|
+
let j = i;
|
|
4872
|
+
while (j < src.length && isWhitespace(src[j])) j++;
|
|
4873
|
+
if (j > i) {
|
|
4874
|
+
const quoted = readQuoted(src, j);
|
|
4875
|
+
const digits = quoted ? null : matchAt(DIGITS_RE, src, j);
|
|
4876
|
+
if (quoted) {
|
|
4877
|
+
val = quoted.value;
|
|
4878
|
+
i = quoted.end;
|
|
4879
|
+
} else if (digits) {
|
|
4880
|
+
val = digits;
|
|
4881
|
+
i = j + digits.length;
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
const param = params.find((p) => p.name === key);
|
|
4885
|
+
if (param?.type === "flag") options[key] = true;
|
|
4886
|
+
else if (param?.type === "number") options[key] = Number(val ?? 0);
|
|
4887
|
+
else if (param) options[key] = val;
|
|
1543
4888
|
}
|
|
1544
|
-
return
|
|
4889
|
+
return options;
|
|
1545
4890
|
}
|
|
4891
|
+
/** `inline %name` reads a transient variable; `inline % 2` is modulo. */
|
|
4892
|
+
var LEADING_OPERATOR_RE = /^(?:[-+*/&|^=<>?:,.]|%(?![A-Za-z_]))/;
|
|
1546
4893
|
/**
|
|
1547
|
-
*
|
|
1548
|
-
*
|
|
4894
|
+
* The rest of `src` without the flag `word` as its last or first term, or
|
|
4895
|
+
* `null` if it has no such flag. Next to a binary operator the word is an
|
|
4896
|
+
* operand (`"a" + inline`), not a flag; the closing `/` of a regex literal
|
|
4897
|
+
* is not one.
|
|
1549
4898
|
*/
|
|
1550
|
-
|
|
4899
|
+
function takeFlag(src, word) {
|
|
4900
|
+
const spans = terms(src);
|
|
4901
|
+
if (spans.length < 2) return null;
|
|
4902
|
+
if (slice(src, spans[spans.length - 1]) === word) {
|
|
4903
|
+
const rest = src.slice(0, spans[spans.length - 2][1]);
|
|
4904
|
+
if (!endsWithOperator(rest)) return rest;
|
|
4905
|
+
}
|
|
4906
|
+
if (slice(src, spans[0]) === word) {
|
|
4907
|
+
const rest = src.slice(spans[1][0]);
|
|
4908
|
+
if (!LEADING_OPERATOR_RE.test(rest)) return rest;
|
|
4909
|
+
}
|
|
4910
|
+
return null;
|
|
4911
|
+
}
|
|
1551
4912
|
/**
|
|
1552
|
-
*
|
|
1553
|
-
*
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
* Returns the index of the closing } or -1 if unbalanced.
|
|
1557
|
-
*
|
|
1558
|
-
* Template literals and their ${…} parts are scans on a stack, not
|
|
1559
|
-
* recursive calls, so deep nesting can't overflow the call stack. How the
|
|
1560
|
-
* text reads depends only on where a scan is, so a scan passing a point —
|
|
1561
|
-
* just past a {, a string or a template literal — goes on as a scan
|
|
1562
|
-
* starting there would: its result there is recorded too, and a recorded
|
|
1563
|
-
* result is used instead of scanning on. Scans from many starts in one
|
|
1564
|
-
* input then take about linear time.
|
|
4913
|
+
* Where the separator `word` splits `src`, as the end of the text before it
|
|
4914
|
+
* and the start of the text after it, or `null` if it doesn't. A word is a
|
|
4915
|
+
* term with terms on both sides; `=` is an assignment at depth 0, not part
|
|
4916
|
+
* of `==` or `!=`.
|
|
1565
4917
|
*/
|
|
1566
|
-
function
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
}];
|
|
1574
|
-
for (;;) {
|
|
1575
|
-
const scan = stack[stack.length - 1];
|
|
1576
|
-
let end;
|
|
1577
|
-
if (scan.template) {
|
|
1578
|
-
let point = true;
|
|
1579
|
-
while (end === void 0 && i < input.length) {
|
|
1580
|
-
if (point) {
|
|
1581
|
-
const known = memo.templateText.get(i);
|
|
1582
|
-
if (known !== void 0) {
|
|
1583
|
-
end = known;
|
|
1584
|
-
break;
|
|
1585
|
-
}
|
|
1586
|
-
scan.passed.push(i);
|
|
1587
|
-
point = false;
|
|
1588
|
-
}
|
|
1589
|
-
const c = input[i];
|
|
1590
|
-
if (c === "\\") {
|
|
1591
|
-
i += 2;
|
|
1592
|
-
point = true;
|
|
1593
|
-
} else if (c === "`") end = i + 1;
|
|
1594
|
-
else if (c === "$" && input[i + 1] === "{") {
|
|
1595
|
-
const inner = memo.brace.get(i + 2);
|
|
1596
|
-
if (inner === void 0) break;
|
|
1597
|
-
if (inner === -1) end = -1;
|
|
1598
|
-
else {
|
|
1599
|
-
i = inner + 1;
|
|
1600
|
-
point = true;
|
|
1601
|
-
}
|
|
1602
|
-
} else i++;
|
|
1603
|
-
}
|
|
1604
|
-
if (end === void 0 && i < input.length) {
|
|
1605
|
-
stack.push({
|
|
1606
|
-
template: false,
|
|
1607
|
-
start: i + 2,
|
|
1608
|
-
levels: [[]]
|
|
1609
|
-
});
|
|
1610
|
-
i += 2;
|
|
1611
|
-
continue;
|
|
1612
|
-
}
|
|
1613
|
-
end ?? (end = -1);
|
|
1614
|
-
} else {
|
|
1615
|
-
const { levels } = scan;
|
|
1616
|
-
/** The } at `close` ends the innermost level. */
|
|
1617
|
-
const closeLevel = (close) => {
|
|
1618
|
-
for (const at of levels.pop()) memo.brace.set(at, close);
|
|
1619
|
-
if (!levels.length) end = close;
|
|
1620
|
-
};
|
|
1621
|
-
while (end === void 0 && i < input.length) {
|
|
1622
|
-
const c = input[i];
|
|
1623
|
-
let at = -1;
|
|
1624
|
-
if (c === "{") {
|
|
1625
|
-
levels.push([]);
|
|
1626
|
-
at = ++i;
|
|
1627
|
-
} else if (c === "}") closeLevel(i++);
|
|
1628
|
-
else if ((c === "\"" || c === "'") && !(i > 0 && NON_STRING_QUOTE_PREFIX.test(input[i - 1]))) {
|
|
1629
|
-
const close = skipQuoted(input, i);
|
|
1630
|
-
if (close === -1) i++;
|
|
1631
|
-
else at = i = close;
|
|
1632
|
-
} else if (c === "`") {
|
|
1633
|
-
const close = memo.template.get(i);
|
|
1634
|
-
if (close === void 0) break;
|
|
1635
|
-
if (close === -1) i++;
|
|
1636
|
-
else at = i = close;
|
|
1637
|
-
} else i++;
|
|
1638
|
-
if (at === -1) continue;
|
|
1639
|
-
const known = memo.brace.get(at);
|
|
1640
|
-
if (known === void 0) levels[levels.length - 1].push(at);
|
|
1641
|
-
else if (known === -1) i = input.length;
|
|
1642
|
-
else {
|
|
1643
|
-
closeLevel(known);
|
|
1644
|
-
i = known + 1;
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
if (end === void 0 && i < input.length) {
|
|
1648
|
-
stack.push({
|
|
1649
|
-
template: true,
|
|
1650
|
-
start: i,
|
|
1651
|
-
levels: [],
|
|
1652
|
-
passed: []
|
|
1653
|
-
});
|
|
1654
|
-
i++;
|
|
4918
|
+
function findSeparator(src, word) {
|
|
4919
|
+
if (word === "=") {
|
|
4920
|
+
const indices = topLevelIndices(src, (ch) => ch === "=");
|
|
4921
|
+
for (let k = 0; k < indices.length; k++) {
|
|
4922
|
+
const i = indices[k];
|
|
4923
|
+
if (src[i + 1] === "=") {
|
|
4924
|
+
k++;
|
|
1655
4925
|
continue;
|
|
1656
4926
|
}
|
|
1657
|
-
if (
|
|
1658
|
-
end = -1;
|
|
1659
|
-
for (const level of levels) for (const at of level) memo.brace.set(at, -1);
|
|
1660
|
-
}
|
|
4927
|
+
if (src[i - 1] !== "!") return [i, i + 1];
|
|
1661
4928
|
}
|
|
1662
|
-
|
|
1663
|
-
(scan.template ? memo.template : memo.brace).set(scan.start, end);
|
|
1664
|
-
for (const at of scan.passed ?? []) memo.templateText.set(at, end);
|
|
1665
|
-
const parent = stack[stack.length - 1];
|
|
1666
|
-
if (!parent) return end;
|
|
1667
|
-
if (parent.template) i = end === -1 ? input.length : end + 1;
|
|
1668
|
-
else i = end === -1 ? scan.start + 1 : end;
|
|
4929
|
+
return null;
|
|
1669
4930
|
}
|
|
4931
|
+
const spans = terms(src);
|
|
4932
|
+
for (let k = 1; k < spans.length - 1; k++) if (slice(src, spans[k]) === word) return [spans[k - 1][1], spans[k + 1][0]];
|
|
4933
|
+
return null;
|
|
1670
4934
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
let i = 0;
|
|
1680
|
-
let textStart = 0;
|
|
1681
|
-
/** Push a text token for the text not yet tokenized before `end`. */
|
|
1682
|
-
function flushText(end) {
|
|
1683
|
-
if (end > textStart) {
|
|
1684
|
-
tokens.push({
|
|
1685
|
-
type: "text",
|
|
1686
|
-
value: input.slice(textStart, end),
|
|
1687
|
-
start: textStart,
|
|
1688
|
-
end
|
|
1689
|
-
});
|
|
1690
|
-
textStart = end;
|
|
1691
|
-
}
|
|
4935
|
+
var takesRest = (param) => param.type === void 0 || param.type === "expression" || param.type === "text";
|
|
4936
|
+
/** Read the parameters of one group from `src` (`null`: no text) into `args`. */
|
|
4937
|
+
function readGroup(params, src, args) {
|
|
4938
|
+
let text = src?.trim() ?? "";
|
|
4939
|
+
for (const flag of params.filter((p) => p.type === "flag")) {
|
|
4940
|
+
const rest = src === null ? null : takeFlag(text, flag.name);
|
|
4941
|
+
args[flag.name] = rest !== null;
|
|
4942
|
+
text = rest ?? text;
|
|
1692
4943
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
4944
|
+
const positional = params.filter((p) => p.type !== "flag");
|
|
4945
|
+
if (positional.length === 0) return;
|
|
4946
|
+
const lastText = positional.findIndex((p, i) => takesRest(p) && !positional.slice(i + 1).some(takesRest));
|
|
4947
|
+
const restIndex = lastText < 0 ? positional.length - 1 : lastText;
|
|
4948
|
+
const read = (param, value) => value === "" ? unset(param) : readValue(param, value);
|
|
4949
|
+
if (positional.length === 1) {
|
|
4950
|
+
args[positional[0].name] = read(positional[0], text);
|
|
4951
|
+
return;
|
|
1697
4952
|
}
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
*/
|
|
1707
|
-
function consumeRawBody(name, isClose) {
|
|
1708
|
-
const lower = name.toLowerCase();
|
|
1709
|
-
if (isClose || !RAW_BODY_MACROS.has(lower)) return;
|
|
1710
|
-
const closer = `\\{/${lower}\\s*\\}`;
|
|
1711
|
-
let last = memo.rawClose.get(lower);
|
|
1712
|
-
if (!last || i < last.from || last.at >= 0 && i > last.at) {
|
|
1713
|
-
const firstRe = new RegExp(closer, "gi");
|
|
1714
|
-
firstRe.lastIndex = i;
|
|
1715
|
-
last = {
|
|
1716
|
-
from: i,
|
|
1717
|
-
at: firstRe.exec(input)?.index ?? -1
|
|
1718
|
-
};
|
|
1719
|
-
memo.rawClose.set(lower, last);
|
|
1720
|
-
}
|
|
1721
|
-
const first = last.at;
|
|
1722
|
-
if (first === -1) return;
|
|
1723
|
-
const atRe = new RegExp(closer, "iy");
|
|
1724
|
-
const closerAt = (k) => {
|
|
1725
|
-
atRe.lastIndex = k;
|
|
1726
|
-
return atRe.test(input);
|
|
1727
|
-
};
|
|
1728
|
-
let closeStart = findCodeEnd(input, i, {
|
|
1729
|
-
goal: "statements",
|
|
1730
|
-
stop: closerAt,
|
|
1731
|
-
stopKey: lower,
|
|
1732
|
-
cache: memo.js
|
|
1733
|
-
});
|
|
1734
|
-
if (closeStart === -1) closeStart = first;
|
|
1735
|
-
atRe.lastIndex = closeStart;
|
|
1736
|
-
const closeEnd = closeStart + atRe.exec(input)[0].length;
|
|
1737
|
-
flushText(closeStart);
|
|
1738
|
-
emit({
|
|
1739
|
-
type: "macro",
|
|
1740
|
-
...parseMacroContent(input.slice(closeStart + 1, closeEnd - 1)),
|
|
1741
|
-
start: closeStart,
|
|
1742
|
-
end: closeEnd
|
|
1743
|
-
});
|
|
4953
|
+
const spans = terms(text);
|
|
4954
|
+
let from = 0;
|
|
4955
|
+
let to = spans.length;
|
|
4956
|
+
for (const param of positional.slice(0, restIndex)) args[param.name] = from < to ? read(param, slice(text, spans[from++])) : unset(param);
|
|
4957
|
+
for (const param of positional.slice(restIndex + 1).reverse()) {
|
|
4958
|
+
const value = from < to && !endsWithOperator(text.slice(0, spans[to - 1][0])) ? read(param, slice(text, spans[to - 1])) : void 0;
|
|
4959
|
+
args[param.name] = value ?? unset(param);
|
|
4960
|
+
if (value !== void 0) to--;
|
|
1744
4961
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
4962
|
+
const rest = positional[restIndex];
|
|
4963
|
+
args[rest.name] = from < to ? read(rest, text.slice(spans[from][0], spans[to - 1][1])) : unset(rest);
|
|
4964
|
+
}
|
|
4965
|
+
/** Read `rawArgs` into the declared `parameters` (see above). */
|
|
4966
|
+
function parseMacroArgs(rawArgs, parameters) {
|
|
4967
|
+
const args = {};
|
|
4968
|
+
let rest = rawArgs.trim();
|
|
4969
|
+
let groupStart = 0;
|
|
4970
|
+
parameters.forEach((separator, i) => {
|
|
4971
|
+
if (separator.type !== "separator") return;
|
|
4972
|
+
const at = rest === null ? null : findSeparator(rest, separator.name);
|
|
4973
|
+
args[separator.name] = at !== null;
|
|
4974
|
+
const before = at ? rest.slice(0, at[0]) : rest;
|
|
4975
|
+
readGroup(parameters.slice(groupStart, i), before, args);
|
|
4976
|
+
rest = at ? rest.slice(at[1]) : null;
|
|
4977
|
+
groupStart = i + 1;
|
|
4978
|
+
});
|
|
4979
|
+
readGroup(parameters.slice(groupStart), rest, args);
|
|
4980
|
+
return args;
|
|
4981
|
+
}
|
|
4982
|
+
//#endregion
|
|
4983
|
+
//#region src/widgets/widget-def.ts
|
|
4984
|
+
/**
|
|
4985
|
+
* Reading widget definitions without rendering anything: the `{widget}`
|
|
4986
|
+
* macro, startup and markup validation (also in tooling) share these.
|
|
4987
|
+
*/
|
|
4988
|
+
/** A {widget} definition's name, then its `@` parameters. */
|
|
4989
|
+
var WIDGET_PARAMETERS = [{
|
|
4990
|
+
name: "name",
|
|
4991
|
+
type: "text",
|
|
4992
|
+
required: true
|
|
4993
|
+
}, {
|
|
4994
|
+
name: "parameters",
|
|
4995
|
+
type: "expression"
|
|
4996
|
+
}];
|
|
4997
|
+
/**
|
|
4998
|
+
* The widget a {widget} definition's arguments declare: its name and its
|
|
4999
|
+
* parameters, the words after it that start with `@` (docs/widgets.md).
|
|
5000
|
+
* Other words, such as `$name`, are not parameters.
|
|
5001
|
+
*/
|
|
5002
|
+
function widgetDef({ name = "", parameters = "" }) {
|
|
5003
|
+
return {
|
|
5004
|
+
name,
|
|
5005
|
+
params: parameters.split(/\s+/).filter((word) => word.startsWith("@"))
|
|
5006
|
+
};
|
|
5007
|
+
}
|
|
5008
|
+
/** Read the arguments of a {widget} definition (see widgetDef). */
|
|
5009
|
+
function parseWidgetDef(rawArgs) {
|
|
5010
|
+
return widgetDef(parseMacroArgs(rawArgs, WIDGET_PARAMETERS));
|
|
5011
|
+
}
|
|
5012
|
+
var BLOCK_WIDGET = /\{widget\s+["']?(\w+)["']?[^}]*\}([\s\S]*?)\{\/widget\}/g;
|
|
5013
|
+
/**
|
|
5014
|
+
* The names of the block widgets (those whose body renders `{@children}`)
|
|
5015
|
+
* that StoryInit and the passages tagged `widget` define. They must be
|
|
5016
|
+
* known as block macros before any passage is parsed, so that passages
|
|
5017
|
+
* invoking them nest their content whatever the passage order.
|
|
5018
|
+
*/
|
|
5019
|
+
function blockWidgetNames(passages) {
|
|
5020
|
+
const names = [];
|
|
5021
|
+
for (const passage of passages) {
|
|
5022
|
+
if (passage.name !== "StoryInit" && !passage.tags?.includes("widget")) continue;
|
|
5023
|
+
for (const match of passage.content.matchAll(BLOCK_WIDGET)) if (/\{@children\}/.test(match[2])) names.push(match[1]);
|
|
1761
5024
|
}
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
5025
|
+
return names;
|
|
5026
|
+
}
|
|
5027
|
+
//#endregion
|
|
5028
|
+
//#region src/markup/validate.ts
|
|
5029
|
+
/**
|
|
5030
|
+
* Markup validation: parse every passage when the story starts and report
|
|
5031
|
+
* malformed markup and unknown macros with the passage, line and column
|
|
5032
|
+
* they are at, instead of failing when the passage renders. Tooling runs it
|
|
5033
|
+
* too (see src/tooling.ts).
|
|
5034
|
+
*/
|
|
5035
|
+
/** Passages that hold no markup. */
|
|
5036
|
+
var NOT_MARKUP = new Set(["StoryVariables", "StoryTransients"]);
|
|
5037
|
+
var NOT_MARKUP_TAGS = ["script", "stylesheet"];
|
|
5038
|
+
/** Branch macros, which their parent macro renders. */
|
|
5039
|
+
var BRANCH_MACROS = new Set([
|
|
5040
|
+
"elseif",
|
|
5041
|
+
"else",
|
|
5042
|
+
"case",
|
|
5043
|
+
"default",
|
|
5044
|
+
"next"
|
|
5045
|
+
]);
|
|
5046
|
+
/** A diagnostic as one line of text. */
|
|
5047
|
+
function formatDiagnostic(d) {
|
|
5048
|
+
const source = d.file ? ` (${d.file}${d.fileLine ? `:${d.fileLine}` : ""})` : "";
|
|
5049
|
+
return `Passage "${d.passage}", line ${d.line}, column ${d.column}${source}: ${d.message}`;
|
|
5050
|
+
}
|
|
5051
|
+
/** Edit distance, for "did you mean" suggestions. */
|
|
5052
|
+
function distance(a, b) {
|
|
5053
|
+
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
5054
|
+
for (let i = 1; i <= a.length; i++) {
|
|
5055
|
+
const row = [i];
|
|
5056
|
+
for (let j = 1; j <= b.length; j++) row[j] = Math.min(prev[j] + 1, row[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
5057
|
+
prev = row;
|
|
1780
5058
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
end: closeIdx + 1
|
|
1795
|
-
}, selectors);
|
|
1796
|
-
emit(token);
|
|
1797
|
-
consumeRawBody(token.name, token.isClose);
|
|
1798
|
-
return true;
|
|
5059
|
+
return prev[b.length];
|
|
5060
|
+
}
|
|
5061
|
+
/** " Did you mean {name}?" for the closest known name, if one is close. */
|
|
5062
|
+
function suggestion(name, names) {
|
|
5063
|
+
const lower = name.toLowerCase();
|
|
5064
|
+
let best = "";
|
|
5065
|
+
let bestDistance = Math.max(2, Math.floor(lower.length / 3)) + 1;
|
|
5066
|
+
for (const candidate of names) {
|
|
5067
|
+
const d = distance(lower, candidate.toLowerCase());
|
|
5068
|
+
if (d < bestDistance) {
|
|
5069
|
+
best = candidate;
|
|
5070
|
+
bestDistance = d;
|
|
5071
|
+
}
|
|
1799
5072
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
continue;
|
|
1828
|
-
}
|
|
1829
|
-
i = k;
|
|
1830
|
-
continue;
|
|
5073
|
+
return best ? ` Did you mean {${best}}?` : "";
|
|
5074
|
+
}
|
|
5075
|
+
/** The name of the widget a `{widget}` with these arguments defines. */
|
|
5076
|
+
function widgetName(rawArgs) {
|
|
5077
|
+
try {
|
|
5078
|
+
return parseWidgetDef(rawArgs).name.toLowerCase() || void 0;
|
|
5079
|
+
} catch {
|
|
5080
|
+
return;
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
/** Validate the markup of every passage. */
|
|
5084
|
+
function validateMarkup(passages, options) {
|
|
5085
|
+
const diagnostics = [];
|
|
5086
|
+
const hooks = options.isBlockMacro ? { isBlock: options.isBlockMacro } : void 0;
|
|
5087
|
+
const report = (passage, offset, message) => {
|
|
5088
|
+
const { line, column } = lineColumn(passage.content, offset);
|
|
5089
|
+
const d = {
|
|
5090
|
+
passage: passage.name,
|
|
5091
|
+
line,
|
|
5092
|
+
column,
|
|
5093
|
+
message
|
|
5094
|
+
};
|
|
5095
|
+
const file = passage.metadata?.["data-source-file"];
|
|
5096
|
+
if (file) {
|
|
5097
|
+
d.file = file;
|
|
5098
|
+
const header = Number(passage.metadata?.["data-source-line"]);
|
|
5099
|
+
if (header) d.fileLine = header + line;
|
|
1831
5100
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
5101
|
+
diagnostics.push(d);
|
|
5102
|
+
};
|
|
5103
|
+
const parsed = [];
|
|
5104
|
+
const widgets = /* @__PURE__ */ new Set();
|
|
5105
|
+
for (const passage of passages) {
|
|
5106
|
+
if (NOT_MARKUP.has(passage.name)) continue;
|
|
5107
|
+
if (passage.tags?.some((tag) => NOT_MARKUP_TAGS.includes(tag))) continue;
|
|
5108
|
+
const reported = !options.only || options.only(passage);
|
|
5109
|
+
try {
|
|
5110
|
+
const tokens = tokenizeMarkup(passage.content);
|
|
5111
|
+
for (const token of tokens) {
|
|
5112
|
+
if (token.type !== "macro" || token.isClose) continue;
|
|
5113
|
+
if (token.name.toLowerCase() !== "widget") continue;
|
|
5114
|
+
const name = widgetName(token.rawArgs);
|
|
5115
|
+
if (name) widgets.add(name);
|
|
1840
5116
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
continue;
|
|
5117
|
+
if (!reported) continue;
|
|
5118
|
+
parseMarkup(passage.content, { hooks });
|
|
5119
|
+
parsed.push([passage, tokens]);
|
|
5120
|
+
} catch (err) {
|
|
5121
|
+
if (!(err instanceof MarkupError)) throw err;
|
|
5122
|
+
if (reported) report(passage, err.offset, err.reason);
|
|
1848
5123
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
} else if (EXPRESSION_START.has(c)) {
|
|
1859
|
-
if (pushExpression(at, start, selectors)) continue;
|
|
1860
|
-
} else if (c !== void 0 && (/[a-zA-Z]/.test(c) || c === "/" && !prefixed)) {
|
|
1861
|
-
flushText(start);
|
|
1862
|
-
if (pushMacro(at, start, selectors)) continue;
|
|
1863
|
-
}
|
|
1864
|
-
i = start + 1;
|
|
1865
|
-
continue;
|
|
5124
|
+
}
|
|
5125
|
+
const names = [...options.macroNames ?? [], ...widgets];
|
|
5126
|
+
/** Report the unknown macros among `tokens`, which start at `base`. */
|
|
5127
|
+
const checkMacros = (passage, tokens, base, where) => {
|
|
5128
|
+
for (const token of tokens) {
|
|
5129
|
+
if (token.type !== "macro" || token.isClose) continue;
|
|
5130
|
+
const lower = token.name.toLowerCase();
|
|
5131
|
+
if (BRANCH_MACROS.has(lower) || widgets.has(lower) || options.isKnownMacro(lower)) continue;
|
|
5132
|
+
report(passage, base + token.start, `${where}Unknown macro {${token.name}}.${suggestion(token.name, names)}`);
|
|
1866
5133
|
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
if (
|
|
1872
|
-
const
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
if (HTML_VOID_TAGS.has(tagLower)) {
|
|
1882
|
-
i = textStart = j;
|
|
1883
|
-
continue;
|
|
1884
|
-
}
|
|
1885
|
-
emit({
|
|
1886
|
-
type: "html",
|
|
1887
|
-
tag,
|
|
1888
|
-
attributes: {},
|
|
1889
|
-
isClose: true,
|
|
1890
|
-
isSelfClose: false,
|
|
1891
|
-
start,
|
|
1892
|
-
end: j
|
|
1893
|
-
});
|
|
1894
|
-
continue;
|
|
1895
|
-
}
|
|
1896
|
-
} else {
|
|
1897
|
-
const attrsStart = j;
|
|
1898
|
-
j = scanAttributes(input, attrsStart, memo);
|
|
1899
|
-
let isSelfClose = HTML_VOID_TAGS.has(tagLower);
|
|
1900
|
-
if (input[j] === "/") {
|
|
1901
|
-
isSelfClose = true;
|
|
1902
|
-
j++;
|
|
1903
|
-
}
|
|
1904
|
-
if (input[j] === ">") {
|
|
1905
|
-
j++;
|
|
1906
|
-
flushText(start);
|
|
1907
|
-
emit({
|
|
1908
|
-
type: "html",
|
|
1909
|
-
tag,
|
|
1910
|
-
attributes: parseHtmlAttributes(input, attrsStart, memo).attributes,
|
|
1911
|
-
isClose: false,
|
|
1912
|
-
isSelfClose,
|
|
1913
|
-
start,
|
|
1914
|
-
end: j
|
|
5134
|
+
};
|
|
5135
|
+
for (const [passage, tokens] of parsed) {
|
|
5136
|
+
checkMacros(passage, tokens, 0, "");
|
|
5137
|
+
for (const token of tokens) {
|
|
5138
|
+
if (token.type !== "html") continue;
|
|
5139
|
+
for (const [attr, value] of Object.entries(token.attributes)) {
|
|
5140
|
+
if (isCodeAttribute(attr) || !value.includes("{")) continue;
|
|
5141
|
+
const found = passage.content.indexOf(value, token.start);
|
|
5142
|
+
const at = found === -1 ? token.start : found;
|
|
5143
|
+
const where = `In the ${attr} attribute of <${token.tag}>: `;
|
|
5144
|
+
try {
|
|
5145
|
+
parseMarkup(value, {
|
|
5146
|
+
text: true,
|
|
5147
|
+
hooks
|
|
1915
5148
|
});
|
|
1916
|
-
|
|
5149
|
+
checkMacros(passage, tokenizeMarkup(value, { text: true }), at, where);
|
|
5150
|
+
} catch (err) {
|
|
5151
|
+
if (!(err instanceof MarkupError)) throw err;
|
|
5152
|
+
report(passage, found === -1 ? at : at + err.offset, where + err.reason);
|
|
1917
5153
|
}
|
|
1918
5154
|
}
|
|
1919
|
-
i++;
|
|
1920
|
-
continue;
|
|
1921
5155
|
}
|
|
1922
|
-
i++;
|
|
1923
5156
|
}
|
|
1924
|
-
|
|
1925
|
-
return tokens;
|
|
5157
|
+
return diagnostics;
|
|
1926
5158
|
}
|
|
1927
5159
|
//#endregion
|
|
1928
5160
|
//#region src/utils/error-message.ts
|
|
@@ -1973,22 +5205,11 @@ function declarationRegex(sigil) {
|
|
|
1973
5205
|
const escaped = sigil.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1974
5206
|
return new RegExp(`^${escaped}(\\w+)\\s*=\\s*(.+)$`);
|
|
1975
5207
|
}
|
|
1976
|
-
/** A `$name` reference with its dot path, at a `$` the lexer found. */
|
|
1977
|
-
var VAR_PATH_RE = /\$(\w+(?:\.\w+)*)/y;
|
|
1978
|
-
/** Quoted first argument of an input macro naming a story variable. */
|
|
1979
|
-
var QUOTED_VAR_ARG_RE = /^["']\$(\w+(?:\.\w+)*)["']?$/;
|
|
1980
|
-
var FOR_LOCAL_RE = /\{for\s+@(\w+)(?:\s*,\s*@(\w+))?\s+of\b/g;
|
|
1981
5208
|
var VALID_VAR_TYPES = new Set([
|
|
1982
5209
|
"number",
|
|
1983
5210
|
"string",
|
|
1984
5211
|
"boolean"
|
|
1985
5212
|
]);
|
|
1986
|
-
/** Boxed sample values whose members a primitive of each type can access. */
|
|
1987
|
-
var PRIMITIVE_SAMPLES = {
|
|
1988
|
-
string: Object(""),
|
|
1989
|
-
number: Object(0),
|
|
1990
|
-
boolean: Object(false)
|
|
1991
|
-
};
|
|
1992
5213
|
function inferSchema(value) {
|
|
1993
5214
|
if (Array.isArray(value)) return { type: "array" };
|
|
1994
5215
|
if (value !== null && typeof value === "object") {
|
|
@@ -2039,186 +5260,34 @@ function parseStoryVariables(content, sigil = "$") {
|
|
|
2039
5260
|
}
|
|
2040
5261
|
return schema;
|
|
2041
5262
|
}
|
|
5263
|
+
//#endregion
|
|
5264
|
+
//#region src/tooling.ts
|
|
2042
5265
|
/**
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
*
|
|
2046
|
-
|
|
2047
|
-
function extractForLocals(content) {
|
|
2048
|
-
const locals = /* @__PURE__ */ new Set();
|
|
2049
|
-
let match;
|
|
2050
|
-
FOR_LOCAL_RE.lastIndex = 0;
|
|
2051
|
-
while ((match = FOR_LOCAL_RE.exec(content)) !== null) {
|
|
2052
|
-
locals.add(match[1]);
|
|
2053
|
-
if (match[2]) locals.add(match[2]);
|
|
2054
|
-
}
|
|
2055
|
-
return locals;
|
|
2056
|
-
}
|
|
2057
|
-
/**
|
|
2058
|
-
* Validate a single variable reference path (e.g. "player.health") against
|
|
2059
|
-
* the schema. Returns an error message or null if valid.
|
|
2060
|
-
*/
|
|
2061
|
-
function validateRef(ref, schema, forLocals) {
|
|
2062
|
-
const parts = ref.split(".");
|
|
2063
|
-
const rootName = parts[0];
|
|
2064
|
-
const nameError = variableNameError(rootName, "$" + rootName);
|
|
2065
|
-
if (nameError) return nameError;
|
|
2066
|
-
if (forLocals.has(rootName)) return null;
|
|
2067
|
-
const rootSchema = schema.get(rootName);
|
|
2068
|
-
if (!rootSchema) return `Undeclared variable: $${ref}`;
|
|
2069
|
-
let current = rootSchema;
|
|
2070
|
-
for (let i = 1; i < parts.length; i++) {
|
|
2071
|
-
const part = parts[i];
|
|
2072
|
-
if (current.type === "array") return null;
|
|
2073
|
-
const sample = PRIMITIVE_SAMPLES[current.type];
|
|
2074
|
-
if (sample && part in sample) {
|
|
2075
|
-
const memberType = typeof sample[part];
|
|
2076
|
-
if (!VALID_VAR_TYPES.has(memberType)) return null;
|
|
2077
|
-
current = { type: memberType };
|
|
2078
|
-
continue;
|
|
2079
|
-
}
|
|
2080
|
-
if (current.type !== "object" || !current.fields) return `Cannot access field "${part}" on $${parts.slice(0, i).join(".")} (type: ${current.type})`;
|
|
2081
|
-
const fieldSchema = current.fields.get(part);
|
|
2082
|
-
if (!fieldSchema) return null;
|
|
2083
|
-
current = fieldSchema;
|
|
2084
|
-
}
|
|
2085
|
-
return null;
|
|
2086
|
-
}
|
|
2087
|
-
/**
|
|
2088
|
-
* Built-in input macros whose first argument names the bound story variable,
|
|
2089
|
-
* quoted or not (e.g. `{textbox "$name"}`).
|
|
2090
|
-
*/
|
|
2091
|
-
var BUILTIN_STORE_VAR_MACROS = [
|
|
2092
|
-
"checkbox",
|
|
2093
|
-
"cycle",
|
|
2094
|
-
"listbox",
|
|
2095
|
-
"numberbox",
|
|
2096
|
-
"radiobutton",
|
|
2097
|
-
"textarea",
|
|
2098
|
-
"textbox"
|
|
2099
|
-
];
|
|
2100
|
-
var NO_STORE_VAR_MACROS = /* @__PURE__ */ new Set();
|
|
2101
|
-
/**
|
|
2102
|
-
* Scan the value of a code attribute (`onclick`, see isCodeAttribute) for
|
|
2103
|
-
* the `{$…}` references resolved in it; its other braces are code.
|
|
2104
|
-
*/
|
|
2105
|
-
function scanSigilReferences(value, onRef) {
|
|
2106
|
-
for (const part of splitSigilTemplate(value)) if ("expr" in part) scanCode(part.expr, onRef);
|
|
2107
|
-
}
|
|
2108
|
-
/**
|
|
2109
|
-
* Scan literal text (string contents, HTML attribute values) for the markup
|
|
2110
|
-
* that labels and HTML attributes evaluate at runtime: `{$…}` displays,
|
|
2111
|
-
* expressions and macros, read as in passage text. A bare `$word` in
|
|
2112
|
-
* literal text is not a reference.
|
|
2113
|
-
*/
|
|
2114
|
-
function scanInterpolations(text, onRef, storeVarMacros = NO_STORE_VAR_MACROS) {
|
|
2115
|
-
if (!text.includes("{")) return;
|
|
2116
|
-
collectTokenRefs(text, tokenize(text, { text: true }), storeVarMacros, onRef);
|
|
2117
|
-
}
|
|
2118
|
-
/**
|
|
2119
|
-
* Report `$var` references in JavaScript code, lexed as the expression
|
|
2120
|
-
* engine lexes it (`lexJs`): references in code, but none inside string or
|
|
2121
|
-
* regex literals or comments, nor property names (`a.$b`, `{ $b: 1 }`).
|
|
2122
|
-
* The text of string and template literals is scanned for the markup that
|
|
2123
|
-
* labels evaluate (`{$…}`); the `${…}` parts of template literals are code.
|
|
2124
|
-
*/
|
|
2125
|
-
function scanCode(code, onRef, goal = "expression") {
|
|
2126
|
-
/** Open template literals: their text so far, null in an interpolation. */
|
|
2127
|
-
const templates = [];
|
|
2128
|
-
lexJs(code, {
|
|
2129
|
-
variable(sigil, _name, index) {
|
|
2130
|
-
if (sigil !== "$") return;
|
|
2131
|
-
VAR_PATH_RE.lastIndex = index;
|
|
2132
|
-
onRef(VAR_PATH_RE.exec(code)[1]);
|
|
2133
|
-
},
|
|
2134
|
-
literal(text, _index, nesting) {
|
|
2135
|
-
const template = templates[templates.length - 1];
|
|
2136
|
-
if (template?.nesting === nesting) if (template.text === null) template.text = "";
|
|
2137
|
-
else if (text === "`" || text === "${") {
|
|
2138
|
-
scanInterpolations(template.text, onRef);
|
|
2139
|
-
if (text === "`") templates.pop();
|
|
2140
|
-
else template.text = null;
|
|
2141
|
-
} else template.text += text;
|
|
2142
|
-
else if (text === "`") templates.push({
|
|
2143
|
-
nesting,
|
|
2144
|
-
text: ""
|
|
2145
|
-
});
|
|
2146
|
-
else if (text[0] === "\"" || text[0] === "'") {
|
|
2147
|
-
const { closed } = scanStringLiteral(text, 0);
|
|
2148
|
-
scanInterpolations(text.slice(1, closed ? -1 : void 0), onRef);
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
}, goal);
|
|
2152
|
-
for (const t of templates) if (t.text) scanInterpolations(t.text, onRef);
|
|
2153
|
-
}
|
|
2154
|
-
/**
|
|
2155
|
-
* Report the `$var` references a passage evaluates at runtime: `{$var}`
|
|
2156
|
-
* displays, `{$expr}` expressions, macro arguments and `{do}` bodies (as
|
|
2157
|
-
* code), quoted variable names bound by input macros, and `{$…}`
|
|
2158
|
-
* interpolations in HTML attributes. Prose is literal text and not scanned.
|
|
5266
|
+
* What the tooling entry point (`@rohal12/spindle/tooling`) bundles as
|
|
5267
|
+
* dist/pkg/story-variables.js: the StoryVariables parser and the markup
|
|
5268
|
+
* validator, with no Preact or DOM dependencies. pkg/tooling.js re-exports
|
|
5269
|
+
* them, binding the validator to its macro metadata.
|
|
2159
5270
|
*/
|
|
2160
|
-
function collectPassageRefs(content, storeVarMacros, onRef) {
|
|
2161
|
-
collectTokenRefs(content, tokenize(content), storeVarMacros, onRef);
|
|
2162
|
-
}
|
|
2163
|
-
/** Report the `$var` references in the tokens of `content`. */
|
|
2164
|
-
function collectTokenRefs(content, tokens, storeVarMacros, onRef) {
|
|
2165
|
-
for (let t = 0; t < tokens.length; t++) {
|
|
2166
|
-
const token = tokens[t];
|
|
2167
|
-
if (token.type === "variable") {
|
|
2168
|
-
if (token.scope === "variable" && token.name) onRef(token.name);
|
|
2169
|
-
} else if (token.type === "expression") scanCode(token.expression, onRef);
|
|
2170
|
-
else if (token.type === "html") for (const [name, value] of Object.entries(token.attributes)) if (isCodeAttribute(name)) scanSigilReferences(value, onRef);
|
|
2171
|
-
else scanInterpolations(value, onRef, storeVarMacros);
|
|
2172
|
-
else if (token.type === "macro" && !token.isClose) {
|
|
2173
|
-
scanCode(token.rawArgs, onRef);
|
|
2174
|
-
if (storeVarMacros.has(token.name.toLowerCase())) {
|
|
2175
|
-
const first = token.rawArgs.trim().split(/\s+/)[0] ?? "";
|
|
2176
|
-
const quoted = QUOTED_VAR_ARG_RE.exec(first);
|
|
2177
|
-
if (quoted) onRef(quoted[1]);
|
|
2178
|
-
}
|
|
2179
|
-
if (token.name === "do") {
|
|
2180
|
-
let close = t + 1;
|
|
2181
|
-
while (close < tokens.length) {
|
|
2182
|
-
const c = tokens[close];
|
|
2183
|
-
if (c.type === "macro" && c.isClose && c.name === "do") break;
|
|
2184
|
-
close++;
|
|
2185
|
-
}
|
|
2186
|
-
if (close < tokens.length) {
|
|
2187
|
-
scanCode(content.slice(token.end, tokens[close].start), onRef, "statements");
|
|
2188
|
-
t = close;
|
|
2189
|
-
}
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
5271
|
/**
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2197
|
-
*
|
|
2198
|
-
* `storeVarMacros` lists the input macros whose first argument names a bound
|
|
2199
|
-
* variable; it defaults to the built-in ones.
|
|
5272
|
+
* Validate the markup of a story's passages as Spindle does when the story
|
|
5273
|
+
* starts, against the given macros (built-in and user-defined): malformed
|
|
5274
|
+
* markup and unknown macros, with their passage, line and column.
|
|
2200
5275
|
*/
|
|
2201
|
-
function
|
|
2202
|
-
const
|
|
2203
|
-
const
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
const
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
});
|
|
5276
|
+
function validateStoryMarkup(passages, macros) {
|
|
5277
|
+
const list = [...passages];
|
|
5278
|
+
const known = /* @__PURE__ */ new Set();
|
|
5279
|
+
const blocks = new Set(blockWidgetNames(list).map((n) => n.toLowerCase()));
|
|
5280
|
+
for (const macro of macros) {
|
|
5281
|
+
const name = macro.name.toLowerCase();
|
|
5282
|
+
known.add(name);
|
|
5283
|
+
for (const sub of macro.subMacros) known.add(sub.toLowerCase());
|
|
5284
|
+
if (macro.block) blocks.add(name);
|
|
2211
5285
|
}
|
|
2212
|
-
return
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
*/
|
|
2218
|
-
function extractDefaults(schema) {
|
|
2219
|
-
const defaults = createNamespace();
|
|
2220
|
-
for (const [name, varSchema] of schema) defaults[name] = varSchema.default;
|
|
2221
|
-
return defaults;
|
|
5286
|
+
return validateMarkup(list, {
|
|
5287
|
+
isKnownMacro: (name) => known.has(name),
|
|
5288
|
+
macroNames: known,
|
|
5289
|
+
isBlockMacro: (name) => blocks.has(name.toLowerCase()) || isBlockMacro(name)
|
|
5290
|
+
});
|
|
2222
5291
|
}
|
|
2223
5292
|
//#endregion
|
|
2224
|
-
export {
|
|
5293
|
+
export { formatDiagnostic, parseStoryVariables, validateStoryMarkup };
|