@the_dissidents/libemmm 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -23,23 +23,34 @@ var NodeType = /* @__PURE__ */ ((NodeType2) => {
23
23
  NodeType2[NodeType2["Interpolation"] = 8] = "Interpolation";
24
24
  return NodeType2;
25
25
  })(NodeType || {});
26
- var ModifierFlags = /* @__PURE__ */ ((ModifierFlags2) => {
27
- ModifierFlags2[ModifierFlags2["Normal"] = 0] = "Normal";
28
- ModifierFlags2[ModifierFlags2["Preformatted"] = 1] = "Preformatted";
29
- ModifierFlags2[ModifierFlags2["Marker"] = 2] = "Marker";
30
- return ModifierFlags2;
31
- })(ModifierFlags || {});
26
+ var ModifierSlotType = /* @__PURE__ */ ((ModifierSlotType2) => {
27
+ ModifierSlotType2[ModifierSlotType2["Normal"] = 0] = "Normal";
28
+ ModifierSlotType2[ModifierSlotType2["Preformatted"] = 1] = "Preformatted";
29
+ ModifierSlotType2[ModifierSlotType2["None"] = 2] = "None";
30
+ return ModifierSlotType2;
31
+ })(ModifierSlotType || {});
32
32
  var ModifierBase = class {
33
- constructor(name, flags = 0 /* Normal */, args) {
33
+ constructor(name, slotType = 0 /* Normal */, args) {
34
34
  this.name = name;
35
- this.flags = flags;
35
+ this.slotType = slotType;
36
36
  if (args) Object.assign(this, args);
37
37
  }
38
+ roleHint;
39
+ /**
40
+ * If true, any modifier encountered in the content of it will *not* be expanded, *unless* that modifier is `alwaysTryExpand`.
41
+ */
38
42
  delayContentExpansion = false;
43
+ /**
44
+ * If true, such a modifier will always be expanded whenever it is encountered, *even if* contained in a modifier with `delayContentExpansion`.
45
+ */
39
46
  alwaysTryExpand = false;
47
+ /** Called before the modifier's content is parsed. */
40
48
  beforeParseContent;
49
+ /** Called after the modifier's content is parsed. */
41
50
  afterParseContent;
51
+ /** Called before reparsing of the expansion. */
42
52
  beforeProcessExpansion;
53
+ /** Called before reparsing of the expansion. */
43
54
  afterProcessExpansion;
44
55
  prepareExpand;
45
56
  expand;
@@ -59,195 +70,469 @@ var ArgumentInterpolatorDefinition = class {
59
70
  alwaysTryExpand = false;
60
71
  expand;
61
72
  };
62
- var ParseContext = class {
63
- constructor(config, variables = /* @__PURE__ */ new Map()) {
64
- this.config = config;
65
- this.variables = variables;
66
- config.initializers.forEach((x) => x(this));
73
+
74
+ // src/util.ts
75
+ var NameManager = class _NameManager {
76
+ array = [];
77
+ data = /* @__PURE__ */ new Map();
78
+ constructor(from) {
79
+ if (from === void 0) return;
80
+ if (from instanceof _NameManager) {
81
+ this.array = [...from.array];
82
+ this.data = new Map(from.data);
83
+ } else {
84
+ const array = [...from];
85
+ assert((from instanceof Set ? from : new Set(array)).size == array.length);
86
+ this.array = array.map((x) => ({ k: x.name, v: x }));
87
+ this.array.sort((a, b) => b.k.length - a.k.length);
88
+ this.data = new Map(array.map((x) => [x.name, x]));
89
+ }
67
90
  }
68
- data = {};
69
- init(key, obj) {
70
- assert(!(key in this.data));
71
- this.data[key] = obj;
91
+ toArray() {
92
+ return this.array.map(({ v }) => v);
72
93
  }
73
- set(key, obj) {
74
- assert(key in this.data);
75
- this.data[key] = obj;
94
+ toSet() {
95
+ return new Set(this.toArray());
76
96
  }
77
- get(key) {
78
- assert(key in this.data);
79
- return this.data[key];
97
+ get(name) {
98
+ return this.data.get(name);
80
99
  }
81
- };
82
- var Document = class {
83
- constructor(root, context, messages) {
84
- this.root = root;
85
- this.context = context;
86
- this.messages = messages;
100
+ has(name) {
101
+ return this.data.has(name);
87
102
  }
88
- debugPrint(source) {
89
- return debugDumpDocument(this, source);
103
+ remove(name) {
104
+ let i = this.data.get(name);
105
+ assert(i !== void 0);
106
+ this.data.delete(name);
107
+ this.array.splice(this.array.findIndex((x) => x.k == name), 1);
108
+ }
109
+ add(...elems) {
110
+ for (const elem of elems) {
111
+ assert(!this.has(elem.name));
112
+ this.data.set(elem.name, elem);
113
+ const len = elem.name.length;
114
+ let i = 0;
115
+ while (i < this.array.length && this.array[i].k.length > len) i++;
116
+ this.array.splice(i, 0, { k: elem.name, v: elem });
117
+ }
118
+ }
119
+ find(predicate) {
120
+ const result = this.array.find((x) => predicate(x.v));
121
+ return result ? result.v : void 0;
90
122
  }
91
123
  };
92
- var Configuration = class {
93
- initializers = [];
94
- blockModifiers;
95
- inlineModifiers;
96
- systemModifiers;
97
- argumentInterpolators;
98
- reparseDepthLimit = 10;
99
- constructor(from) {
100
- this.blockModifiers = new NameManager(from?.blockModifiers);
101
- this.inlineModifiers = new NameManager(from?.inlineModifiers);
102
- this.systemModifiers = new NameManager(from?.systemModifiers);
103
- this.argumentInterpolators = new NameManager(from?.argumentInterpolators);
104
- if (from) {
105
- this.initializers = [...from.initializers];
106
- this.reparseDepthLimit = from.reparseDepthLimit;
124
+ function assert(x) {
125
+ if (!!!x) {
126
+ let error = new Error("assertion failed");
127
+ console.log(error.stack);
128
+ throw error;
129
+ }
130
+ }
131
+ function linePositions(src) {
132
+ let result = [0];
133
+ [...src].forEach((x, i) => {
134
+ if (x == "\n") result.push(i + 1);
135
+ });
136
+ result.push(Infinity);
137
+ return result;
138
+ }
139
+ var cloneArgument = (arg, options) => ({
140
+ location: clonePosition(arg.location, options),
141
+ content: arg.content.map((ent) => {
142
+ switch (ent.type) {
143
+ case 3 /* Text */:
144
+ case 4 /* Escaped */:
145
+ return structuredClone(ent);
146
+ case 8 /* Interpolation */:
147
+ return {
148
+ type: ent.type,
149
+ location: clonePosition(arg.location, options),
150
+ definition: ent.definition,
151
+ argument: cloneArgument(ent.argument, options),
152
+ expansion: ent.expansion
153
+ };
154
+ default:
155
+ return debug.never(ent);
107
156
  }
157
+ })
158
+ });
159
+ function clonePosition(pos, options) {
160
+ let base = options.newLocation ?? pos;
161
+ return {
162
+ start: base.start,
163
+ end: base.end,
164
+ actualEnd: base.actualEnd,
165
+ original: options.newLocation ? pos : pos.original,
166
+ source: base.source
167
+ };
168
+ }
169
+ function cloneNode(node, options = {}) {
170
+ switch (node.type) {
171
+ case 7 /* BlockModifier */:
172
+ case 6 /* InlineModifier */:
173
+ case 5 /* SystemModifier */:
174
+ return {
175
+ location: clonePosition(node.location, options),
176
+ type: node.type,
177
+ mod: node.mod,
178
+ state: options.withState ? node.state : void 0,
179
+ head: structuredClone(node.head),
180
+ arguments: node.arguments.map((x) => cloneArgument(x, options)),
181
+ content: node.content.map((x) => cloneNode(x, options)),
182
+ expansion: node.expansion ? cloneNodes(node.expansion, options) : void 0
183
+ };
184
+ case 0 /* Root */:
185
+ return {
186
+ type: node.type,
187
+ source: node.source,
188
+ content: node.content.map((x) => cloneNode(x, options))
189
+ };
190
+ case 1 /* Paragraph */:
191
+ return {
192
+ type: node.type,
193
+ location: clonePosition(node.location, options),
194
+ content: node.content.map((x) => cloneNode(x, options))
195
+ };
196
+ case 2 /* Preformatted */:
197
+ case 3 /* Text */:
198
+ case 4 /* Escaped */:
199
+ return structuredClone(node);
200
+ default:
201
+ return debug.never(node);
202
+ }
203
+ }
204
+ function cloneNodes(nodes, options = {}) {
205
+ return nodes.map((x) => cloneNode(x, options));
206
+ }
207
+ function stripNode(...nodes) {
208
+ return nodes.flatMap((node) => {
209
+ switch (node.type) {
210
+ case 2 /* Preformatted */:
211
+ case 3 /* Text */:
212
+ case 4 /* Escaped */:
213
+ return [node];
214
+ case 7 /* BlockModifier */:
215
+ case 6 /* InlineModifier */:
216
+ if (node.expansion !== void 0)
217
+ return node.expansion.flatMap((x) => stripNode(x));
218
+ // else fallthrough!
219
+ case 1 /* Paragraph */:
220
+ case 0 /* Root */:
221
+ node.content = node.content.flatMap((x) => stripNode(x));
222
+ return [node];
223
+ case 5 /* SystemModifier */:
224
+ return [];
225
+ default:
226
+ return debug.never(node);
227
+ }
228
+ });
229
+ }
230
+
231
+ // src/debug.ts
232
+ var DebugLevel = /* @__PURE__ */ ((DebugLevel3) => {
233
+ DebugLevel3[DebugLevel3["Trace"] = 0] = "Trace";
234
+ DebugLevel3[DebugLevel3["Info"] = 1] = "Info";
235
+ DebugLevel3[DebugLevel3["Warning"] = 2] = "Warning";
236
+ DebugLevel3[DebugLevel3["Error"] = 3] = "Error";
237
+ DebugLevel3[DebugLevel3["None"] = 4] = "None";
238
+ return DebugLevel3;
239
+ })(DebugLevel || {});
240
+ var debug = {
241
+ level: 1 /* Info */,
242
+ trace(arg0, ...args) {
243
+ if (this.level > 0 /* Trace */) return;
244
+ if (typeof arg0 == "function") arg0 = arg0();
245
+ console.info("TRACE", arg0, ...args);
246
+ },
247
+ info(arg0, ...args) {
248
+ if (this.level > 1 /* Info */) return;
249
+ if (typeof arg0 == "function") arg0 = arg0();
250
+ console.info(" INFO", arg0, ...args);
251
+ },
252
+ warning(arg0, ...args) {
253
+ if (this.level > 2 /* Warning */) return;
254
+ if (typeof arg0 == "function") arg0 = arg0();
255
+ console.warn(" WARN", arg0, ...args);
256
+ },
257
+ error(arg0, ...args) {
258
+ if (this.level > 3 /* Error */) return;
259
+ if (typeof arg0 == "function") arg0 = arg0();
260
+ console.error("ERROR", arg0, ...args);
261
+ },
262
+ never(_) {
263
+ assert(false);
108
264
  }
109
265
  };
110
266
 
267
+ // src/scanner.ts
268
+ var SimpleScanner = class {
269
+ constructor(src, source = { name: "<input>" }) {
270
+ this.src = src;
271
+ this.source = source;
272
+ }
273
+ pos = 0;
274
+ position() {
275
+ return this.pos;
276
+ }
277
+ isEOF() {
278
+ return this.pos >= this.src.length;
279
+ }
280
+ peek(str) {
281
+ assert(str !== "");
282
+ let next = this.pos + str.length;
283
+ if (next > this.src.length) return false;
284
+ return this.src.slice(this.pos, this.pos + str.length) == str;
285
+ }
286
+ acceptChar() {
287
+ if (this.isEOF()) throw new RangeError("EOF");
288
+ let char = this.src[this.pos];
289
+ this.pos++;
290
+ return char;
291
+ }
292
+ accept(str) {
293
+ if (!this.peek(str)) return false;
294
+ this.pos += str.length;
295
+ return true;
296
+ }
297
+ acceptWhitespaceChar() {
298
+ if (this.isEOF()) return null;
299
+ let char = this.src[this.pos];
300
+ if (!" ".includes(char)) return null;
301
+ this.pos++;
302
+ return char;
303
+ }
304
+ };
305
+
306
+ // src/debug-print.ts
307
+ var debugPrint = {
308
+ blockModifier: (x) => `[.${x.name}] (${ModifierSlotType[x.slotType]})`,
309
+ inlineModifier: (x) => `[/${x.name}] (${ModifierSlotType[x.slotType]})`,
310
+ inlineShorthand: (x) => x.name + x.parts.map((x2, i) => ` .. <arg${i}> .. ${x2}`).join("") + (x.mod.slotType == 2 /* None */ ? "" : ` .. <slot> .. ${x.postfix ?? "<no postfix>"}`),
311
+ blockShorthand: (x) => x.name + x.parts.map((x2, i) => ` .. <arg${i}> .. ${x2}`).join("") + (x.mod.slotType == 2 /* None */ ? "" : ` .. <slot> .. ${x.postfix ?? "<no postfix>"}`),
312
+ argument: (arg) => arg.content.map(debugPrintArgEntity).join(""),
313
+ node: (...nodes) => nodes.map((x) => debugPrintNode(x)).join("\n"),
314
+ message: (m, source, descriptor) => debugPrintMsg(m, descriptor, source),
315
+ document: debugDumpDocument
316
+ };
317
+ function debugPrintArgEntity(node) {
318
+ switch (node.type) {
319
+ case 3 /* Text */:
320
+ return node.content;
321
+ case 4 /* Escaped */:
322
+ return `<Escaped:${node.content}>`;
323
+ case 8 /* Interpolation */:
324
+ return `<Interp:${node.definition.name}-${node.definition.postfix}:${debugPrint.argument(node.argument)}${node.expansion ? `=${node.expansion}` : ""}>`;
325
+ default:
326
+ return debug.never(node);
327
+ }
328
+ }
329
+ function debugPrintNode(node, prefix = "") {
330
+ function debugPrintNodes(content, prefix2 = "") {
331
+ let dumps = content.map((x) => debugPrintNode(x, prefix2 + " ")).filter((x) => x.length > 0);
332
+ if (dumps.length == 0) return "";
333
+ return dumps.map((x) => `${prefix2} ${x}`).join("\n");
334
+ }
335
+ let result = `<${NodeType[node.type]}@${node.location.start}`;
336
+ switch (node.type) {
337
+ case 1 /* Paragraph */:
338
+ const content = debugPrintNodes(node.content, prefix);
339
+ if (content.length > 0)
340
+ result += `>
341
+ ${content}
342
+ ${prefix}</${NodeType[node.type]}@${node.location.end}>`;
343
+ else result += `-${node.location.end} />`;
344
+ break;
345
+ case 4 /* Escaped */:
346
+ result += `>
347
+ ${prefix} ${node.content}
348
+ ${prefix}</${NodeType[node.type]}@${node.location.end}>`;
349
+ break;
350
+ case 2 /* Preformatted */:
351
+ result += `>
352
+ ${prefix} ${node.content.text}
353
+ ${prefix}</${NodeType[node.type]}@${node.location.end}>`;
354
+ break;
355
+ case 6 /* InlineModifier */:
356
+ case 7 /* BlockModifier */:
357
+ case 5 /* SystemModifier */:
358
+ const args = node.arguments.map((x, i) => `
359
+ ${prefix} (${i})@${x.location.start}-${x.location.end}=${debugPrint.argument(x)}`).join("");
360
+ if (node.content.length > 0) {
361
+ result += ` id=${node.mod.name}${args}>
362
+ ` + debugPrintNodes(node.content, prefix) + `
363
+ ${prefix}</${NodeType[node.type]}@${node.location.end}>`;
364
+ } else result += `-${node.location.end} id=${node.mod.name}${args} />`;
365
+ if (node.expansion) {
366
+ const content2 = debugPrintNodes(node.expansion, prefix);
367
+ if (content2.length > 0)
368
+ result += `
369
+ ${prefix}<expansion>
370
+ ${content2}
371
+ ${prefix}</expansion>`;
372
+ else if (node.type != 5 /* SystemModifier */)
373
+ result += `
374
+ ${prefix}<expansion />`;
375
+ }
376
+ break;
377
+ case 3 /* Text */:
378
+ return node.content;
379
+ default:
380
+ return debug.never(node);
381
+ }
382
+ return result;
383
+ }
384
+ function debugPrintMsg(m, descriptor, source) {
385
+ let pos = (pos2) => `@${pos2}`;
386
+ if (source) {
387
+ const lines = linePositions(source);
388
+ pos = (pos2) => {
389
+ let line = -1, linepos = 0;
390
+ for (let i = 1; i < lines.length; i++) {
391
+ if (lines[i] > pos2) {
392
+ line = i;
393
+ linepos = lines[i - 1];
394
+ break;
395
+ }
396
+ }
397
+ return `l${line}c${pos2 - linepos + 1}`;
398
+ };
399
+ }
400
+ let loc = m.location;
401
+ let result = `at ${pos(loc.start)}-${pos(loc.end)}: ${MessageSeverity[m.severity]}[${m.code}]: ${m.info}`;
402
+ if (descriptor && m.location.source !== descriptor) {
403
+ result += `
404
+ warning: source descriptor mismatch: ${m.location.source.name}`;
405
+ }
406
+ while (loc = loc.original) {
407
+ let d = loc.source !== m.location.source ? `(in ${loc.source.name}) ` : "";
408
+ result += `
409
+ ---> original at: ${d}${pos(loc.start)}-${pos(loc.end)}`;
410
+ }
411
+ return result;
412
+ }
413
+ function debugDumpDocument(doc, source) {
414
+ let root = debugPrint.node(...doc.root.content);
415
+ let msgs = doc.messages.map((x) => debugPrintMsg(x, doc.root.source, source)).join("\n");
416
+ if (msgs.length > 0) msgs += "\n";
417
+ return `Document: ${doc.root.source.name}
418
+ ${msgs}${root}`;
419
+ }
420
+
111
421
  // src/messages.ts
112
422
  var messages_exports = {};
113
423
  __export(messages_exports, {
114
424
  ArgumentCountMismatchMessage: () => ArgumentCountMismatchMessage,
115
425
  CannotExpandArgumentMessage: () => CannotExpandArgumentMessage,
116
- CannotPopNotationMessage: () => CannotPopNotationMessage,
426
+ CannotUseModuleInSelfMessage: () => CannotUseModuleInSelfMessage,
117
427
  ContentShouldBeOnNewlineMessage: () => ContentShouldBeOnNewlineMessage,
428
+ EitherNormalOrPreMessage: () => EitherNormalOrPreMessage,
429
+ EntityNotAllowedMessage: () => EntityNotAllowedMessage,
118
430
  ExpectedMessage: () => ExpectedMessage,
119
- InlineDefinitonInvalidEntityMessage: () => InlineDefinitonInvalidEntityMessage,
120
431
  InvalidArgumentMessage: () => InvalidArgumentMessage,
432
+ MultipleBlocksNotPermittedMessage: () => MultipleBlocksNotPermittedMessage,
121
433
  NameAlreadyDefinedMessage: () => NameAlreadyDefinedMessage,
122
434
  NewBlockShouldBeOnNewlineMessage: () => NewBlockShouldBeOnNewlineMessage,
435
+ NoNestedModuleMessage: () => NoNestedModuleMessage,
436
+ OnlySimpleParagraphsPermittedMessage: () => OnlySimpleParagraphsPermittedMessage,
437
+ OverwriteDefinitionsMessage: () => OverwriteDefinitionsMessage,
438
+ OverwriteSpecialVariableMessage: () => OverwriteSpecialVariableMessage,
123
439
  ReachedRecursionLimitMessage: () => ReachedRecursionLimitMessage,
124
- ReferredMessage: () => ReferredMessage,
125
440
  SlotUsedOutsideDefinitionMessage: () => SlotUsedOutsideDefinitionMessage,
126
441
  UnclosedInlineModifierMessage: () => UnclosedInlineModifierMessage,
127
442
  UndefinedVariableMessage: () => UndefinedVariableMessage,
128
443
  UnknownModifierMessage: () => UnknownModifierMessage,
129
444
  UnnecessaryNewlineMessage: () => UnnecessaryNewlineMessage
130
445
  });
131
- var ReferredMessage = class {
132
- constructor(original, position, length) {
133
- this.original = original;
134
- this.position = position;
135
- this.length = length;
136
- }
137
- get severity() {
138
- return this.original.severity;
139
- }
140
- get info() {
141
- return this.original.info;
142
- }
143
- get code() {
144
- return this.original.code;
145
- }
146
- fixes = [];
147
- };
148
446
  var AddThingMessage = class {
149
- constructor(code, severity, position, length, info, fixstr, what) {
447
+ constructor(code, severity, location, info) {
150
448
  this.code = code;
151
449
  this.severity = severity;
152
- this.position = position;
153
- this.length = length;
450
+ this.location = location;
154
451
  this.info = info;
155
- this.fixstr = fixstr;
156
- this.what = what;
157
- }
158
- get fixes() {
159
- let [pos, what, fixstr] = [this.position, this.what, this.fixstr];
160
- return [{
161
- get info() {
162
- return fixstr;
163
- },
164
- apply(src, cursor) {
165
- let newCursor = cursor < pos ? cursor : cursor + what.length;
166
- return [src.substring(0, pos) + what + src.substring(pos), newCursor];
167
- }
168
- }];
169
452
  }
453
+ // get fixes(): readonly FixSuggestion[] {
454
+ // let [start, what, fixstr] = [this.location.start, this.what, this.fixstr];
455
+ // return [{
456
+ // get info() { return fixstr; },
457
+ // apply(src: string, cursor: number) {
458
+ // let newCursor = (cursor < start)
459
+ // ? cursor
460
+ // : cursor + what.length;
461
+ // return [src.substring(0, start) + what + src.substring(start), newCursor];
462
+ // }
463
+ // }];
464
+ // }
170
465
  };
171
466
  var RemoveThingMessage = class {
172
- constructor(code, severity, position, length, info, fixstr) {
467
+ constructor(code, severity, location, info) {
173
468
  this.code = code;
174
469
  this.severity = severity;
175
- this.position = position;
176
- this.length = length;
470
+ this.location = location;
177
471
  this.info = info;
178
- this.fixstr = fixstr;
179
- }
180
- get fixes() {
181
- let [pos, len, fixstr] = [this.position, this.length, this.fixstr];
182
- return [{
183
- get info() {
184
- return fixstr;
185
- },
186
- apply(src, cursor) {
187
- let newCursor = cursor < pos + len && cursor >= pos ? pos : cursor - len;
188
- return [src.substring(0, pos) + src.substring(pos + len), newCursor];
189
- }
190
- }];
191
472
  }
473
+ // get fixes(): readonly FixSuggestion[] {
474
+ // let [start, end, fixstr] = [this.start, this.end, this.fixstr];
475
+ // return [{
476
+ // get info() { return fixstr; },
477
+ // apply(src: string, cursor: number) {
478
+ // let newCursor = (cursor < end && cursor >= start)
479
+ // ? start
480
+ // : cursor; // Removing text, cursor shouldn't shift if it's outside the removed range
481
+ // return [src.substring(0, start) + src.substring(end), newCursor];
482
+ // }
483
+ // }];
484
+ // }
192
485
  };
193
486
  var ExpectedMessage = class {
194
- constructor(position, what) {
195
- this.position = position;
487
+ constructor(location, what) {
488
+ this.location = location;
196
489
  this.what = what;
490
+ assert(location.end == location.start);
197
491
  }
198
492
  code = 1;
199
493
  severity = 2 /* Error */;
200
- get length() {
201
- return 0;
202
- }
203
494
  get info() {
204
495
  return `expected '${this.what}'`;
205
496
  }
206
- get fixes() {
207
- return [];
208
- }
209
497
  };
210
498
  var UnknownModifierMessage = class {
211
- constructor(position, length, what) {
212
- this.position = position;
213
- this.length = length;
499
+ constructor(location, what) {
500
+ this.location = location;
214
501
  this.what = what;
215
502
  }
216
503
  code = 2;
217
504
  severity = 2 /* Error */;
218
- get info() {
219
- return `unknown modifier '${this.what}'; did you forget to escape it?`;
220
- }
221
- get fixes() {
222
- let [pos, len] = [this.position, this.length];
223
- return [{
224
- get info() {
225
- return "this is not a modifier -- escape it";
226
- },
227
- apply(src, cursor) {
228
- let newCursor = cursor < pos ? cursor : cursor + 1;
229
- return [src.substring(0, pos) + "\\" + src.substring(pos), newCursor];
230
- }
231
- }];
505
+ get info() {
506
+ return `unknown modifier '${this.what}'; did you forget to escape it?`;
232
507
  }
508
+ // get fixes(): readonly FixSuggestion[] {
509
+ // let [start, end] = [this.start, this.end];
510
+ // return [{
511
+ // get info() { return 'this is not a modifier -- escape it'; },
512
+ // apply(src: string, cursor: number) {
513
+ // let newCursor = (cursor < start)
514
+ // ? cursor
515
+ // : cursor + 1;
516
+ // return [src.substring(0, start) + '\\' + src.substring(start), newCursor];
517
+ // }
518
+ // }];
519
+ // }
233
520
  };
234
521
  var UnclosedInlineModifierMessage = class {
235
- constructor(position, what) {
236
- this.position = position;
522
+ constructor(location, what) {
523
+ this.location = location;
237
524
  this.what = what;
525
+ assert(location.end == location.start);
238
526
  }
239
527
  code = 3;
240
528
  severity = 2 /* Error */;
241
- length = 0;
242
- fixes = [];
243
529
  get info() {
244
530
  return `unclosed inline modifier ${this.what}'`;
245
531
  }
246
532
  };
247
533
  var ArgumentCountMismatchMessage = class {
248
- constructor(position, length, min, max) {
249
- this.position = position;
250
- this.length = length;
534
+ constructor(location, min, max) {
535
+ this.location = location;
251
536
  if (min !== void 0) {
252
537
  if (max == min) this.msg = `: ${min} expected`;
253
538
  else if (max !== void 0) this.msg = `: ${min} to ${max} expected`;
@@ -259,449 +544,247 @@ var ArgumentCountMismatchMessage = class {
259
544
  msg = "";
260
545
  code = 4;
261
546
  severity = 2 /* Error */;
262
- fixes = [];
263
547
  get info() {
264
548
  return `argument count mismatch` + this.msg;
265
549
  }
266
550
  };
267
551
  var CannotExpandArgumentMessage = class {
268
- constructor(position, length, what) {
269
- this.position = position;
270
- this.length = length;
552
+ constructor(location, what) {
553
+ this.location = location;
271
554
  this.what = what;
272
555
  }
273
556
  code = 5;
274
557
  severity = 2 /* Error */;
275
- fixes = [];
276
558
  get info() {
277
559
  return `failed to expand argument` + (this.what === void 0 ? "" : `: ${this.what}`);
278
560
  }
279
561
  };
280
562
  var InvalidArgumentMessage = class {
281
- constructor(position, length, what) {
282
- this.position = position;
283
- this.length = length;
563
+ constructor(location, what) {
564
+ this.location = location;
284
565
  this.what = what;
285
566
  }
286
567
  code = 6;
287
568
  severity = 2 /* Error */;
288
- fixes = [];
289
569
  get info() {
290
570
  return `invalid argument` + (this.what === void 0 ? "" : `: ${this.what}`);
291
571
  }
292
572
  };
293
- var InlineDefinitonInvalidEntityMessage = class {
294
- constructor(position, length) {
295
- this.position = position;
296
- this.length = length;
573
+ var EntityNotAllowedMessage = class {
574
+ constructor(location, what) {
575
+ this.location = location;
576
+ this.what = what;
297
577
  }
298
578
  code = 7;
299
579
  severity = 2 /* Error */;
300
- fixes = [];
301
580
  get info() {
302
- return `Invalid entity in inline modifier definition`;
581
+ return "This entity is not allowed here" + (this.what ? `: ${this.what}` : "");
303
582
  }
304
583
  };
305
584
  var ReachedRecursionLimitMessage = class {
306
- constructor(position, length, limit, what) {
307
- this.position = position;
308
- this.length = length;
585
+ constructor(location, limit, what) {
586
+ this.location = location;
309
587
  this.limit = limit;
310
588
  this.what = what;
311
589
  }
312
590
  code = 8;
313
591
  severity = 2 /* Error */;
314
- fixes = [];
315
592
  get info() {
316
593
  return `Reached recursion limit ${this.limit} when expanding ${this.what}`;
317
594
  }
318
595
  };
319
596
  var SlotUsedOutsideDefinitionMessage = class {
320
- constructor(position, length) {
321
- this.position = position;
322
- this.length = length;
597
+ constructor(location) {
598
+ this.location = location;
323
599
  }
324
600
  code = 9;
325
601
  severity = 2 /* Error */;
326
- fixes = [];
327
602
  get info() {
328
603
  return `slot used outside a definition`;
329
604
  }
330
605
  };
331
- var CannotPopNotationMessage = class {
332
- constructor(position, length) {
333
- this.position = position;
334
- this.length = length;
606
+ var NoNestedModuleMessage = class {
607
+ constructor(location) {
608
+ this.location = location;
335
609
  }
336
610
  code = 10;
337
611
  severity = 2 /* Error */;
338
- fixes = [];
339
612
  get info() {
340
- return `cannot pop notation`;
613
+ return `nested module definitions not allowed`;
614
+ }
615
+ };
616
+ var CannotUseModuleInSelfMessage = class {
617
+ constructor(location) {
618
+ this.location = location;
619
+ }
620
+ code = 11;
621
+ severity = 2 /* Error */;
622
+ get info() {
623
+ return `cannot use the same module inside its definition`;
624
+ }
625
+ };
626
+ var EitherNormalOrPreMessage = class {
627
+ constructor(location) {
628
+ this.location = location;
629
+ }
630
+ code = 12;
631
+ severity = 2 /* Error */;
632
+ get info() {
633
+ return `a definition cannot be at once normal and preformatted`;
634
+ }
635
+ };
636
+ var MultipleBlocksNotPermittedMessage = class {
637
+ constructor(location) {
638
+ this.location = location;
639
+ }
640
+ code = 13;
641
+ severity = 2 /* Error */;
642
+ get info() {
643
+ return `multiple blocks are not permitted here`;
644
+ }
645
+ };
646
+ var OnlySimpleParagraphsPermittedMessage = class {
647
+ constructor(location) {
648
+ this.location = location;
649
+ }
650
+ code = 14;
651
+ severity = 2 /* Error */;
652
+ get info() {
653
+ return `Only simple paragraphs are permitted here`;
341
654
  }
342
655
  };
343
656
  var UnnecessaryNewlineMessage = class extends RemoveThingMessage {
344
- constructor(pos, len) {
657
+ constructor(location) {
345
658
  super(
346
659
  1,
347
660
  1 /* Warning */,
348
- pos,
349
- len,
350
- "more than one newlines have the same effect as one",
351
- "remove the redundant newlines"
661
+ location,
662
+ "more than one newlines have the same effect as one"
352
663
  );
353
664
  }
354
665
  };
355
666
  var NewBlockShouldBeOnNewlineMessage = class extends AddThingMessage {
356
- constructor(pos) {
667
+ constructor(location) {
357
668
  super(
358
669
  2,
359
670
  1 /* Warning */,
360
- pos,
361
- 0,
362
- "a new block should begin in a new line to avoid confusion",
363
- "add a line break",
364
- "\n"
671
+ location,
672
+ "a new block should begin in a new line to avoid confusion"
365
673
  );
366
674
  }
367
675
  };
368
676
  var ContentShouldBeOnNewlineMessage = class extends AddThingMessage {
369
- constructor(pos) {
677
+ constructor(location) {
370
678
  super(
371
679
  3,
372
680
  1 /* Warning */,
373
- pos,
374
- 0,
375
- "the content should begin in a new line to avoid confusion",
376
- "add a line break",
377
- "\n"
681
+ location,
682
+ "the content should begin in a new line to avoid confusion"
378
683
  );
379
684
  }
380
685
  };
381
686
  var NameAlreadyDefinedMessage = class {
382
- constructor(position, length, what) {
383
- this.position = position;
384
- this.length = length;
687
+ constructor(location, what) {
688
+ this.location = location;
385
689
  this.what = what;
386
690
  }
387
691
  code = 4;
388
692
  severity = 1 /* Warning */;
389
- fixes = [];
390
693
  get info() {
391
694
  return `name is already defined, will overwrite: ${this.what}`;
392
695
  }
393
696
  };
394
697
  var UndefinedVariableMessage = class {
395
- constructor(position, length, what) {
396
- this.position = position;
397
- this.length = length;
698
+ constructor(location, what) {
699
+ this.location = location;
398
700
  this.what = what;
399
701
  }
400
702
  code = 5;
401
703
  severity = 1 /* Warning */;
402
- fixes = [];
403
704
  get info() {
404
705
  return `variable is undefined, will expand to empty string: ${this.what}`;
405
706
  }
406
707
  };
407
-
408
- // src/util.ts
409
- var NameManager = class _NameManager {
410
- array = [];
411
- data = /* @__PURE__ */ new Map();
412
- constructor(from) {
413
- if (from === void 0) return;
414
- if (from instanceof _NameManager) {
415
- this.array = [...from.array];
416
- this.data = new Map(from.data);
417
- } else {
418
- assert(Array.isArray(from));
419
- this.array = from.map((x) => ({ k: x.name, v: x }));
420
- this.array.sort((a, b) => b.k.length - a.k.length);
421
- this.data = new Map(from.map((x) => [x.name, x]));
422
- }
423
- }
424
- toArray() {
425
- return this.array.map(({ v }) => v);
426
- }
427
- get(name) {
428
- return this.data.get(name);
429
- }
430
- has(name) {
431
- return this.data.has(name);
432
- }
433
- remove(name) {
434
- let i = this.data.get(name);
435
- assert(i !== void 0);
436
- this.data.delete(name);
437
- this.array.splice(this.array.findIndex((x) => x.k == name), 1);
438
- }
439
- add(...elems) {
440
- for (const elem of elems) {
441
- assert(!this.has(elem.name));
442
- this.data.set(elem.name, elem);
443
- const len = elem.name.length;
444
- let i = 0;
445
- while (i < this.array.length && this.array[i].k.length > len) i++;
446
- this.array.splice(i, 0, { k: elem.name, v: elem });
447
- }
708
+ var OverwriteDefinitionsMessage = class {
709
+ constructor(location, what) {
710
+ this.location = location;
711
+ this.what = what;
448
712
  }
449
- find(predicate) {
450
- const result = this.array.find((x) => predicate(x.v));
451
- return result ? result.v : void 0;
713
+ code = 6;
714
+ severity = 1 /* Warning */;
715
+ get info() {
716
+ return `using this module will overwrite: ${this.what}`;
452
717
  }
453
718
  };
454
- function assert(x) {
455
- if (!!!x) {
456
- let error = new Error("assertion failed");
457
- console.log(error.stack);
458
- throw error;
459
- }
460
- }
461
- function has(v, f) {
462
- return (v & f) === f;
463
- }
464
- function linePositions(src) {
465
- let result = [0];
466
- [...src].forEach((x, i) => {
467
- if (x == "\n") result.push(i + 1);
468
- });
469
- result.push(Infinity);
470
- return result;
471
- }
472
- var cloneArgument = (arg) => ({
473
- start: arg.start,
474
- end: arg.end,
475
- content: arg.content.map((ent) => {
476
- switch (ent.type) {
477
- case 3 /* Text */:
478
- case 4 /* Escaped */:
479
- return structuredClone(ent);
480
- case 8 /* Interpolation */:
481
- return {
482
- type: ent.type,
483
- start: ent.start,
484
- end: ent.end,
485
- definition: ent.definition,
486
- argument: cloneArgument(ent.argument),
487
- expansion: ent.expansion
488
- };
489
- default:
490
- return debug.never(ent);
491
- }
492
- })
493
- });
494
- function cloneNode(node, referring) {
495
- switch (node.type) {
496
- case 7 /* BlockModifier */:
497
- case 6 /* InlineModifier */:
498
- case 5 /* SystemModifier */:
499
- return {
500
- start: node.start,
501
- end: node.end,
502
- type: node.type,
503
- mod: node.mod,
504
- state: void 0,
505
- head: structuredClone(node.head),
506
- arguments: node.arguments.map(cloneArgument),
507
- content: node.content.map((x) => cloneNode(x, referring)),
508
- expansion: node.expansion ? cloneNodes(node.expansion) : void 0
509
- };
510
- case 0 /* Root */:
511
- case 1 /* Paragraph */:
512
- return {
513
- type: node.type,
514
- start: node.start,
515
- end: node.end,
516
- content: node.content.map((x) => cloneNode(x))
517
- };
518
- case 2 /* Preformatted */:
519
- case 3 /* Text */:
520
- case 4 /* Escaped */:
521
- return structuredClone(node);
522
- default:
523
- return debug.never(node);
524
- }
525
- }
526
- function cloneNodes(nodes) {
527
- return nodes.map((x) => cloneNode(x));
528
- }
529
- function debugPrintArgEntity(node) {
530
- switch (node.type) {
531
- case 3 /* Text */:
532
- return node.content;
533
- case 4 /* Escaped */:
534
- return `<Escaped:${node.content}>`;
535
- case 8 /* Interpolation */:
536
- return `<Interp:${node.definition.name}-${node.definition.postfix}:${debugPrintArgument(node.argument)}${node.expansion ? `=${node.expansion}` : ""}>`;
537
- default:
538
- return debug.never(node);
539
- }
540
- }
541
- function debugPrintArgument(arg) {
542
- return arg.content.map(debugPrintArgEntity).join("");
543
- }
544
- function debugPrintNode(node, prefix = "") {
545
- let result = `<${NodeType[node.type]}@${node.start}`;
546
- switch (node.type) {
547
- case 0 /* Root */:
548
- case 1 /* Paragraph */:
549
- const content = debugPrintNodes(node.content, prefix);
550
- if (content.length > 0)
551
- result += `>
552
- ${content}
553
- ${prefix}</${NodeType[node.type]}@${node.end}>`;
554
- else result += `-${node.end} />`;
555
- break;
556
- case 4 /* Escaped */:
557
- case 2 /* Preformatted */:
558
- result += `>
559
- ${prefix} ${node.content}
560
- ${prefix}</${NodeType[node.type]}@${node.end}>`;
561
- break;
562
- case 6 /* InlineModifier */:
563
- case 7 /* BlockModifier */:
564
- case 5 /* SystemModifier */:
565
- const args = node.arguments.map((x, i) => `
566
- ${prefix} (${i})@${x.start}-${x.end}=${debugPrintArgument(x)}`).join("");
567
- if (node.content.length > 0) {
568
- result += ` id=${node.mod.name}${args}>
569
- ` + debugPrintNodes(node.content, prefix) + `
570
- ${prefix}</${NodeType[node.type]}@${node.end}>`;
571
- } else result += `-${node.end} id=${node.mod.name}${args} />`;
572
- if (node.expansion) {
573
- const content2 = debugPrintNodes(node.expansion, prefix);
574
- if (content2.length > 0)
575
- result += `
576
- ${prefix}<expansion>
577
- ${content2}
578
- ${prefix}</expansion>`;
579
- else if (node.type != 5 /* SystemModifier */)
580
- result += `
581
- ${prefix}<expansion />`;
582
- }
583
- break;
584
- case 3 /* Text */:
585
- return node.content;
586
- default:
587
- return debug.never(node);
588
- }
589
- return result;
590
- }
591
- function debugPrintNodes(content, prefix = "") {
592
- let dumps = content.map((x) => debugPrintNode(x, prefix + " ")).filter((x) => x.length > 0);
593
- if (dumps.length == 0) return "";
594
- return dumps.map((x) => `${prefix} ${x}`).join("\n");
595
- }
596
- function debugDumpDocument(doc, source) {
597
- const lines = linePositions(source);
598
- function pos2lc(pos) {
599
- let line = -1, linepos = 0;
600
- for (let i = 1; i < lines.length; i++) {
601
- if (lines[i] > pos) {
602
- line = i;
603
- linepos = lines[i - 1];
604
- break;
605
- }
606
- }
607
- return `l${line}c${pos - linepos + 1}`;
719
+ var OverwriteSpecialVariableMessage = class {
720
+ constructor(location, varname, previous) {
721
+ this.location = location;
722
+ this.varname = varname;
723
+ this.previous = previous;
608
724
  }
609
- function dumpMsg(m) {
610
- let result = `at ${pos2lc(m.position)}, len ${m.length}: ${MessageSeverity[m.severity]}[${m.code}]: ${m.info}`;
611
- while (m instanceof ReferredMessage) {
612
- m = m.original;
613
- result += `
614
- ---> original at: ${pos2lc(m.position)}, len ${m.length}`;
615
- }
616
- return result;
617
- }
618
- let root = debugPrintNode(doc.root);
619
- let msgs = doc.messages.map(dumpMsg).join("\n");
620
- if (msgs.length > 0) msgs += "\n";
621
- return `${msgs}${root}`;
622
- }
623
-
624
- // src/debug.ts
625
- var DebugLevel = /* @__PURE__ */ ((DebugLevel3) => {
626
- DebugLevel3[DebugLevel3["Trace"] = 0] = "Trace";
627
- DebugLevel3[DebugLevel3["Info"] = 1] = "Info";
628
- DebugLevel3[DebugLevel3["Warning"] = 2] = "Warning";
629
- DebugLevel3[DebugLevel3["Error"] = 3] = "Error";
630
- DebugLevel3[DebugLevel3["None"] = 4] = "None";
631
- return DebugLevel3;
632
- })(DebugLevel || {});
633
- var debug = {
634
- level: 1 /* Info */,
635
- trace(arg0, ...args) {
636
- if (this.level > 0 /* Trace */) return;
637
- if (typeof arg0 == "function") arg0 = arg0();
638
- console.info("TRACE", arg0, ...args);
639
- },
640
- info(arg0, ...args) {
641
- if (this.level > 1 /* Info */) return;
642
- if (typeof arg0 == "function") arg0 = arg0();
643
- console.info(" INFO", arg0, ...args);
644
- },
645
- warning(arg0, ...args) {
646
- if (this.level > 2 /* Warning */) return;
647
- if (typeof arg0 == "function") arg0 = arg0();
648
- console.warn(" WARN", arg0, ...args);
649
- },
650
- error(arg0, ...args) {
651
- if (this.level > 3 /* Error */) return;
652
- if (typeof arg0 == "function") arg0 = arg0();
653
- console.error("ERROR", arg0, ...args);
654
- },
655
- never(_) {
656
- assert(false);
725
+ code = 6;
726
+ severity = 1 /* Warning */;
727
+ get info() {
728
+ return `${this.varname} is already defined (as "${this.previous}"), will be overwritten`;
657
729
  }
658
730
  };
659
731
 
660
- // src/front.ts
661
- var SimpleScanner = class {
662
- constructor(src) {
663
- this.src = src;
664
- }
665
- pos = 0;
666
- position() {
667
- return this.pos;
668
- }
669
- isEOF() {
670
- return this.pos >= this.src.length;
732
+ // src/parser-config.ts
733
+ var ParseContext = class {
734
+ constructor(config2, variables = /* @__PURE__ */ new Map()) {
735
+ this.config = config2;
736
+ this.variables = variables;
737
+ config2.initializers.forEach((x) => x(this));
671
738
  }
672
- peek(str) {
673
- let next = this.pos + str.length;
674
- if (next > this.src.length) return false;
675
- return this.src.slice(this.pos, this.pos + str.length) == str;
739
+ data = {};
740
+ init(key, obj) {
741
+ assert(!(key in this.data));
742
+ this.data[key] = obj;
676
743
  }
677
- acceptChar() {
678
- if (this.isEOF()) throw new RangeError("EOF");
679
- let char = this.src[this.pos];
680
- this.pos++;
681
- return char;
744
+ set(key, obj) {
745
+ assert(key in this.data);
746
+ this.data[key] = obj;
682
747
  }
683
- accept(str) {
684
- if (!this.peek(str)) return false;
685
- this.pos += str.length;
686
- return true;
748
+ get(key) {
749
+ assert(key in this.data);
750
+ return this.data[key];
687
751
  }
688
- acceptWhitespaceChar() {
689
- if (this.isEOF()) return null;
690
- let char = this.src[this.pos];
691
- if (!" ".includes(char)) return null;
692
- this.pos++;
693
- return char;
752
+ };
753
+ var Document = class _Document {
754
+ constructor(root, context, messages) {
755
+ this.root = root;
756
+ this.context = context;
757
+ this.messages = messages;
694
758
  }
695
- acceptUntil(str) {
696
- let start = this.pos;
697
- while (!this.isEOF()) {
698
- if (this.peek(str)) {
699
- let result = this.src.slice(start, this.pos);
700
- return result;
701
- }
702
- this.pos++;
703
- }
704
- return null;
759
+ toStripped() {
760
+ let doc = new _Document(
761
+ stripNode(cloneNode(this.root, { withState: true }))[0],
762
+ this.context,
763
+ this.messages
764
+ );
765
+ return doc;
766
+ }
767
+ };
768
+ var Configuration = class _Configuration {
769
+ initializers = [];
770
+ blockModifiers = new NameManager();
771
+ inlineModifiers = new NameManager();
772
+ systemModifiers = new NameManager();
773
+ argumentInterpolators = new NameManager();
774
+ blockShorthands = new NameManager();
775
+ inlineShorthands = new NameManager();
776
+ reparseDepthLimit = 10;
777
+ static from(from) {
778
+ let config2 = new _Configuration();
779
+ config2.initializers = [...from.initializers];
780
+ config2.reparseDepthLimit = from.reparseDepthLimit;
781
+ config2.blockModifiers = new NameManager(from.blockModifiers);
782
+ config2.inlineModifiers = new NameManager(from.inlineModifiers);
783
+ config2.systemModifiers = new NameManager(from.systemModifiers);
784
+ config2.argumentInterpolators = new NameManager(from.argumentInterpolators);
785
+ config2.blockShorthands = new NameManager(from.blockShorthands);
786
+ config2.inlineShorthands = new NameManager(from.inlineShorthands);
787
+ return config2;
705
788
  }
706
789
  };
707
790
 
@@ -722,31 +805,20 @@ var UnknownModifier = {
722
805
  var EmitEnvironment = class {
723
806
  constructor(scanner) {
724
807
  this.scanner = scanner;
808
+ this.root = { type: 0 /* Root */, source: scanner.source, content: [] };
725
809
  }
726
- root = { type: 0 /* Root */, start: 0, end: -1, content: [] };
810
+ root;
727
811
  messages = [];
728
- blockStack = [this.root];
812
+ blockStack = [];
729
813
  inlineStack = [];
730
- referringStack = [];
731
814
  message(...m) {
732
- const referringReverse = [...this.referringStack].reverse();
733
815
  for (let msg of m) {
734
- for (const range of referringReverse)
735
- msg = new ReferredMessage(msg, range.start, range.end - range.start);
736
816
  this.messages.push(msg);
737
817
  debug.trace("issued msg", msg.code, msg.info);
738
818
  }
739
819
  }
740
- pushReferring(start, end) {
741
- this.referringStack.push({ start, end });
742
- }
743
- popReferring() {
744
- assert(this.referringStack.length > 0);
745
- this.referringStack.pop();
746
- }
747
820
  addBlockNode(n) {
748
- assert(this.blockStack.length > 0);
749
- this.blockStack.at(-1).content.push(n);
821
+ (this.blockStack.at(-1) ?? this.root).content.push(n);
750
822
  return n;
751
823
  }
752
824
  addInlineNode(n) {
@@ -760,11 +832,14 @@ var EmitEnvironment = class {
760
832
  const last = content.at(-1);
761
833
  if (last?.type == 3 /* Text */) {
762
834
  last.content += str;
763
- last.end = this.scanner.position();
835
+ last.location.end = this.scanner.position();
764
836
  } else content.push({
765
837
  type: 3 /* Text */,
766
- start: this.scanner.position() - str.length,
767
- end: this.scanner.position(),
838
+ location: {
839
+ source: this.scanner.source,
840
+ start: this.scanner.position() - str.length,
841
+ end: this.scanner.position()
842
+ },
768
843
  content: str
769
844
  });
770
845
  }
@@ -773,9 +848,9 @@ var EmitEnvironment = class {
773
848
  this.blockStack.push(block);
774
849
  }
775
850
  endBlock() {
776
- assert(this.blockStack.length >= 2);
851
+ assert(this.blockStack.length > 0);
777
852
  const node = this.blockStack.pop();
778
- node.end = this.scanner.position();
853
+ node.location.end = this.scanner.position();
779
854
  }
780
855
  startInline(n) {
781
856
  if (n.type == 1 /* Paragraph */) this.addBlockNode(n);
@@ -785,19 +860,32 @@ var EmitEnvironment = class {
785
860
  endInline() {
786
861
  assert(this.inlineStack.length > 0);
787
862
  const node = this.inlineStack.pop();
788
- node.end = this.scanner.position();
863
+ node.location.end = this.scanner.position();
789
864
  }
790
865
  };
791
866
  var Parser = class {
792
- constructor(scanner, config) {
867
+ constructor(scanner, cxt) {
793
868
  this.scanner = scanner;
869
+ this.cxt = cxt;
794
870
  this.emit = new EmitEnvironment(scanner);
795
- this.cxt = new ParseContext(config);
796
871
  }
797
872
  emit;
798
- cxt;
799
873
  delayDepth = 0;
800
874
  groupDepth = 0;
875
+ #loc(to) {
876
+ return {
877
+ source: this.scanner.source,
878
+ start: this.scanner.position(),
879
+ end: to ?? this.scanner.position()
880
+ };
881
+ }
882
+ #locFrom(from, to) {
883
+ return {
884
+ source: this.scanner.source,
885
+ start: from,
886
+ end: to ?? this.scanner.position()
887
+ };
888
+ }
801
889
  #defs(type) {
802
890
  switch (type) {
803
891
  case 5 /* SystemModifier */:
@@ -897,30 +985,23 @@ var Parser = class {
897
985
  node.expansion = node.mod.expand(node, this.cxt, immediate);
898
986
  if (!node.expansion) {
899
987
  return true;
900
- } else if (node.expansion.length > 0) {
901
- debug.trace(`${this.delayDepth > 0 ? "early " : ""}expanding:`, node.mod.name);
902
- debug.trace(() => "-->\n" + debugPrintNodes(node.expansion, " "));
903
- } else {
904
- debug.trace(`${this.delayDepth > 0 ? "early " : ""}expanding:`, node.mod.name);
905
988
  }
989
+ debug.trace(`${this.delayDepth > 0 ? "early " : ""}expanding:`, node.mod.name);
990
+ if (node.expansion.length > 0)
991
+ debug.trace(() => "-->\n" + debugPrint.node(...node.expansion));
906
992
  }
907
993
  const expansion = node.expansion ?? node.content;
908
994
  if (expansion.length == 0) return true;
909
995
  if (node.mod.beforeProcessExpansion)
910
996
  this.emit.message(...node.mod.beforeProcessExpansion(node, this.cxt, immediate));
911
- this.emit.pushReferring(node.start, node.end);
912
997
  let ok = this.#reparse(expansion, depth);
913
- this.emit.popReferring();
914
998
  if (node.mod.afterProcessExpansion)
915
999
  this.emit.message(...node.mod.afterProcessExpansion(node, this.cxt, immediate));
916
1000
  if (!ok && depth == 0) {
917
1001
  const limit = this.cxt.config.reparseDepthLimit;
918
- this.emit.message(new ReachedRecursionLimitMessage(
919
- node.start,
920
- node.end - node.start,
921
- limit,
922
- node.mod.name
923
- ));
1002
+ this.emit.message(
1003
+ new ReachedRecursionLimitMessage(node.location, limit, node.mod.name)
1004
+ );
924
1005
  }
925
1006
  return ok;
926
1007
  }
@@ -928,15 +1009,18 @@ var Parser = class {
928
1009
  this.DOCUMENT();
929
1010
  return new Document(this.emit.root, this.cxt, this.emit.messages);
930
1011
  }
1012
+ WHITESPACES() {
1013
+ while (this.scanner.acceptWhitespaceChar() !== null) {
1014
+ }
1015
+ }
931
1016
  WHITESPACES_OR_NEWLINES() {
932
1017
  while (this.scanner.acceptWhitespaceChar() !== null || this.scanner.accept("\n")) {
933
1018
  }
934
1019
  }
935
1020
  SHOULD_BE_A_NEWLINE() {
936
- while (this.scanner.acceptWhitespaceChar() !== null) {
937
- }
1021
+ this.WHITESPACES();
938
1022
  if (!this.scanner.accept("\n")) this.emit.message(
939
- new ContentShouldBeOnNewlineMessage(this.scanner.position())
1023
+ new ContentShouldBeOnNewlineMessage(this.#loc())
940
1024
  );
941
1025
  }
942
1026
  // TODO: this is awkward and doesn't emit messages in the most appropriate way
@@ -952,7 +1036,7 @@ var Parser = class {
952
1036
  }
953
1037
  const end = this.scanner.position();
954
1038
  if (nlines > n) this.emit.message(
955
- new UnnecessaryNewlineMessage(start, end - start)
1039
+ new UnnecessaryNewlineMessage(this.#locFrom(start, end))
956
1040
  );
957
1041
  }
958
1042
  DOCUMENT() {
@@ -972,6 +1056,8 @@ var Parser = class {
972
1056
  this.MODIFIER(5 /* SystemModifier */);
973
1057
  return;
974
1058
  }
1059
+ const short = this.cxt.config.blockShorthands.find((x) => this.scanner.accept(x.name));
1060
+ if (short) return this.SHORTHAND(7 /* BlockModifier */, short);
975
1061
  this.MAYBE_GROUPED_PARAGRAPH();
976
1062
  }
977
1063
  MODIFIER(type) {
@@ -992,71 +1078,29 @@ var Parser = class {
992
1078
  name += this.scanner.acceptChar();
993
1079
  }
994
1080
  this.emit.message(
995
- new UnknownModifierMessage(posStart, this.scanner.position() - posStart, name)
1081
+ new UnknownModifierMessage(this.#locFrom(posStart), name)
996
1082
  );
997
1083
  }
998
1084
  const args = this.ARGUMENTS();
999
1085
  debug.trace(`PARSE ${NodeType[type]}:`, mod.name);
1000
1086
  const endsign = this.scanner.accept(MODIFIER_END_SIGN);
1001
- const flagMarker = has(mod.flags, 2 /* Marker */);
1002
- const isMarker = flagMarker || endsign;
1087
+ const flagMarker = mod.slotType == 2 /* None */;
1003
1088
  if (!this.scanner.accept(MODIFIER_CLOSE_SIGN))
1004
- this.emit.message(new ExpectedMessage(
1005
- this.scanner.position(),
1006
- MODIFIER_CLOSE_SIGN
1007
- ));
1089
+ this.emit.message(
1090
+ new ExpectedMessage(this.#loc(), MODIFIER_CLOSE_SIGN)
1091
+ );
1008
1092
  const headEnd = this.scanner.position();
1009
1093
  const node = {
1010
1094
  type,
1011
1095
  mod,
1012
- head: { start: posStart, end: headEnd },
1096
+ head: this.#locFrom(posStart, headEnd),
1097
+ location: this.#locFrom(posStart, headEnd),
1013
1098
  arguments: args,
1014
- start: posStart,
1015
- end: headEnd,
1016
1099
  content: [],
1017
1100
  expansion: void 0
1018
1101
  };
1019
- this.#expandArguments(node);
1020
- const immediate = this.delayDepth == 0;
1021
- if (node.mod.beforeParseContent)
1022
- this.emit.message(...node.mod.beforeParseContent(node, this.cxt, immediate));
1023
- if (node.mod.delayContentExpansion) this.delayDepth++;
1024
- let ok = true;
1025
- if (isMarker) {
1026
- if (type === 6 /* InlineModifier */) this.emit.addInlineNode(node);
1027
- else this.emit.addBlockNode(node);
1028
- } else if (type == 6 /* InlineModifier */) {
1029
- this.emit.startInline(node);
1030
- const entity = has(mod.flags, 1 /* Preformatted */) ? this.PREFORMATTED_INLINE_ENTITY.bind(this) : this.INLINE_ENTITY.bind(this);
1031
- while (true) {
1032
- if (this.scanner.accept(MODIFIER_INLINE_END_TAG)) break;
1033
- if (this.scanner.isEOF() || !(ok = entity())) {
1034
- this.emit.message(new UnclosedInlineModifierMessage(
1035
- this.scanner.position(),
1036
- mod.name
1037
- ));
1038
- break;
1039
- }
1040
- }
1041
- this.emit.endInline();
1042
- } else {
1043
- this.emit.startBlock(node);
1044
- this.WARN_IF_MORE_NEWLINES_THAN(1);
1045
- if (!this.scanner.isEOF()) {
1046
- if (has(mod.flags, 1 /* Preformatted */))
1047
- this.PRE_PARAGRAPH();
1048
- else
1049
- this.BLOCK_ENTITY();
1050
- }
1051
- this.emit.endBlock();
1052
- }
1053
- const last = node.content.at(-1);
1054
- node.actualEnd = last?.actualEnd ?? last?.end;
1055
- if (node.mod.delayContentExpansion) this.delayDepth--;
1056
- if (node.mod.afterParseContent)
1057
- this.emit.message(...node.mod.afterParseContent(node, this.cxt, immediate));
1058
- this.#expand(node);
1059
- return ok;
1102
+ const isMarker = flagMarker || endsign;
1103
+ return this.MODIFIER_BODY(type, node, MODIFIER_INLINE_END_TAG, isMarker);
1060
1104
  }
1061
1105
  // also handles "grouped" (delimited) pre-paragraphs
1062
1106
  PRE_PARAGRAPH() {
@@ -1075,10 +1119,9 @@ var Parser = class {
1075
1119
  white += char;
1076
1120
  if (grouped && this.scanner.accept(GROUP_END) || !grouped && this.scanner.accept("\n")) break;
1077
1121
  if (this.scanner.isEOF()) {
1078
- if (grouped) this.emit.message(new ExpectedMessage(
1079
- this.scanner.position(),
1080
- GROUP_END
1081
- ));
1122
+ if (grouped) this.emit.message(
1123
+ new ExpectedMessage(this.#loc(), GROUP_END)
1124
+ );
1082
1125
  break;
1083
1126
  }
1084
1127
  string += white;
@@ -1089,8 +1132,7 @@ var Parser = class {
1089
1132
  }
1090
1133
  const node = {
1091
1134
  type: 2 /* Preformatted */,
1092
- start: posStart,
1093
- end: this.scanner.position(),
1135
+ location: this.#locFrom(posStart),
1094
1136
  content: {
1095
1137
  start: posContentStart,
1096
1138
  end: posContentEnd,
@@ -1113,54 +1155,128 @@ var Parser = class {
1113
1155
  this.BLOCK_ENTITY();
1114
1156
  this.WARN_IF_MORE_NEWLINES_THAN(1);
1115
1157
  }
1116
- this.emit.message(new ExpectedMessage(
1117
- this.scanner.position(),
1118
- GROUP_END
1119
- ));
1158
+ this.emit.message(
1159
+ new ExpectedMessage(this.#loc(), GROUP_END)
1160
+ );
1120
1161
  } else {
1121
1162
  this.PARAGRAPH();
1122
1163
  }
1123
1164
  }
1165
+ #trimNode(node) {
1166
+ if (node.content.length == 0) return;
1167
+ let first = node.content[0];
1168
+ let last = node.content.at(-1);
1169
+ if (first.type == 3 /* Text */)
1170
+ first.content = first.content.trimStart();
1171
+ if (last.type == 3 /* Text */)
1172
+ last.content = last.content.trimEnd();
1173
+ }
1124
1174
  PARAGRAPH() {
1125
1175
  assert(!this.scanner.isEOF());
1126
1176
  const node = {
1127
1177
  type: 1 /* Paragraph */,
1128
- start: this.scanner.position(),
1129
- end: -1,
1178
+ location: this.#loc(),
1130
1179
  content: []
1131
1180
  };
1132
- debug.trace("PARSE para");
1133
1181
  this.emit.startInline(node);
1134
1182
  while (!this.scanner.isEOF() && this.INLINE_ENTITY()) {
1135
1183
  }
1136
1184
  this.emit.endInline();
1137
1185
  const last = node.content.at(-1);
1138
- node.actualEnd = last?.actualEnd ?? last?.end;
1139
- debug.trace("PARSE para end");
1186
+ node.location.actualEnd = last?.location.actualEnd ?? last?.location.end;
1187
+ this.#trimNode(node);
1188
+ }
1189
+ // returns false if breaking out of paragraph
1190
+ SHORTHAND(type, d) {
1191
+ const posStart = this.scanner.position() - d.name.length;
1192
+ let args = [];
1193
+ for (const part of d.parts) {
1194
+ let [arg, ok] = this.ARGUMENT_CONTENT(part, ["\n\n"]);
1195
+ if (!ok) {
1196
+ this.emit.message(new ExpectedMessage(this.#loc(), part));
1197
+ return false;
1198
+ }
1199
+ args.push(arg);
1200
+ }
1201
+ const headEnd = this.scanner.position();
1202
+ const node = {
1203
+ type,
1204
+ mod: d.mod,
1205
+ head: this.#locFrom(posStart, headEnd),
1206
+ location: this.#locFrom(posStart, headEnd),
1207
+ arguments: args,
1208
+ content: [],
1209
+ expansion: void 0
1210
+ };
1211
+ const isMarker = node.mod.slotType == 2 /* None */;
1212
+ return this.MODIFIER_BODY(type, node, d.postfix, isMarker);
1213
+ }
1214
+ MODIFIER_BODY(type, node, postfix, isMarker) {
1215
+ this.#expandArguments(node);
1216
+ const immediate = this.delayDepth == 0;
1217
+ if (node.mod.beforeParseContent)
1218
+ this.emit.message(...node.mod.beforeParseContent(node, this.cxt, immediate));
1219
+ if (node.mod.delayContentExpansion) this.delayDepth++;
1220
+ let ok = true;
1221
+ if (isMarker) {
1222
+ if (type === 6 /* InlineModifier */) this.emit.addInlineNode(node);
1223
+ else this.emit.addBlockNode(node);
1224
+ } else if (type == 6 /* InlineModifier */) {
1225
+ node = node;
1226
+ this.emit.startInline(node);
1227
+ const pre = node.mod.slotType == 1 /* Preformatted */;
1228
+ const entity = pre ? this.PREFORMATTED_INLINE_ENTITY.bind(this) : this.INLINE_ENTITY.bind(this);
1229
+ while (true) {
1230
+ if (postfix && this.scanner.accept(postfix)) break;
1231
+ if (this.scanner.isEOF() || !(ok = entity())) {
1232
+ if (postfix) this.emit.message(
1233
+ new ExpectedMessage(this.#loc(), postfix)
1234
+ );
1235
+ break;
1236
+ }
1237
+ }
1238
+ this.emit.endInline();
1239
+ if (!pre && node.content.length > 0) {
1240
+ this.#trimNode(node);
1241
+ }
1242
+ } else {
1243
+ this.emit.startBlock(node);
1244
+ this.WARN_IF_MORE_NEWLINES_THAN(1);
1245
+ if (!this.scanner.isEOF()) {
1246
+ if (node.mod.slotType == 1 /* Preformatted */)
1247
+ this.PRE_PARAGRAPH();
1248
+ else
1249
+ this.BLOCK_ENTITY();
1250
+ }
1251
+ this.emit.endBlock();
1252
+ }
1253
+ const last = node.content.at(-1);
1254
+ node.location.actualEnd = last?.location.actualEnd ?? last?.location.end;
1255
+ if (node.mod.delayContentExpansion) this.delayDepth--;
1256
+ if (node.mod.afterParseContent)
1257
+ this.emit.message(...node.mod.afterParseContent(node, this.cxt, immediate));
1258
+ this.#expand(node);
1259
+ return ok;
1140
1260
  }
1141
1261
  // returns false if breaking out of paragraph
1142
1262
  INLINE_ENTITY() {
1143
1263
  assert(!this.scanner.isEOF());
1144
- if (this.scanner.peek(MODIFIER_BLOCK_OPEN)) {
1145
- this.emit.message(new NewBlockShouldBeOnNewlineMessage(this.scanner.position()));
1146
- return false;
1147
- }
1148
- if (this.scanner.peek(MODIFIER_INLINE_OPEN)) {
1264
+ if (this.scanner.peek(MODIFIER_INLINE_OPEN))
1149
1265
  return this.MODIFIER(6 /* InlineModifier */);
1150
- }
1151
- if (this.scanner.peek(MODIFIER_SYSTEM_OPEN)) {
1266
+ if (this.scanner.peek(MODIFIER_SYSTEM_OPEN))
1152
1267
  return false;
1153
- }
1268
+ const short = this.cxt.config.inlineShorthands.find((x) => this.scanner.accept(x.name));
1269
+ if (short) return this.SHORTHAND(6 /* InlineModifier */, short);
1154
1270
  if (this.scanner.accept("\\")) {
1155
1271
  if (this.scanner.isEOF()) {
1156
1272
  this.emit.addString("\\");
1157
1273
  return true;
1158
1274
  }
1275
+ const start = this.scanner.position();
1159
1276
  const node = {
1160
1277
  type: 4 /* Escaped */,
1161
- start: this.scanner.position() - 1,
1162
1278
  content: this.scanner.acceptChar(),
1163
- end: this.scanner.position()
1279
+ location: this.#locFrom(start - 1)
1164
1280
  };
1165
1281
  this.emit.addInlineNode(node);
1166
1282
  return true;
@@ -1171,9 +1287,8 @@ var Parser = class {
1171
1287
  PREFORMATTED_INLINE_ENTITY() {
1172
1288
  assert(!this.scanner.isEOF());
1173
1289
  if (this.scanner.accept("\n")) {
1174
- while (this.scanner.acceptWhitespaceChar() !== null) {
1175
- }
1176
- if (this.scanner.peek(MODIFIER_BLOCK_OPEN) || this.scanner.peek(MODIFIER_SYSTEM_OPEN) || this.scanner.peek(GROUP_END) && this.groupDepth > 0 || this.scanner.isEOF()) return false;
1290
+ this.WHITESPACES();
1291
+ if (this.scanner.peek(MODIFIER_BLOCK_OPEN) || this.scanner.peek(MODIFIER_SYSTEM_OPEN) || this.cxt.config.blockShorthands.find((x) => this.scanner.peek(x.name)) || this.scanner.peek(GROUP_END) && this.groupDepth > 0 || this.scanner.isEOF()) return false;
1177
1292
  if (this.scanner.accept("\n")) {
1178
1293
  this.WARN_IF_MORE_NEWLINES_THAN(0);
1179
1294
  return false;
@@ -1184,7 +1299,8 @@ var Parser = class {
1184
1299
  this.emit.addString(this.scanner.acceptChar());
1185
1300
  return true;
1186
1301
  }
1187
- ARGUMENT_CONTENT(end) {
1302
+ // returns argument and isOk
1303
+ ARGUMENT_CONTENT(end = void 0, close = [MODIFIER_END_SIGN, MODIFIER_CLOSE_SIGN]) {
1188
1304
  let ok = true;
1189
1305
  const content = [];
1190
1306
  const posStart = this.scanner.position();
@@ -1193,25 +1309,22 @@ var Parser = class {
1193
1309
  const last = content.at(-1);
1194
1310
  if (last?.type == 3 /* Text */) {
1195
1311
  last.content += s;
1196
- last.end += s.length;
1312
+ last.location.end += s.length;
1197
1313
  } else {
1198
1314
  const end2 = this.scanner.position();
1199
1315
  content.push({
1200
1316
  type: 3 /* Text */,
1201
- end: end2,
1202
- start: end2 - s.length,
1317
+ location: this.#locFrom(end2 - s.length),
1203
1318
  content: s
1204
1319
  });
1205
1320
  }
1206
1321
  };
1207
1322
  while (true) {
1208
- if (end !== void 0 && this.scanner.accept(end))
1323
+ if (end && this.scanner.accept(end))
1209
1324
  break;
1210
- if (this.scanner.accept(":")) {
1211
- ok = end === void 0;
1325
+ if (end === void 0 && this.scanner.accept(":"))
1212
1326
  break;
1213
- }
1214
- if (this.scanner.peek(MODIFIER_END_SIGN) || this.scanner.peek(MODIFIER_CLOSE_SIGN) || this.scanner.isEOF()) {
1327
+ if (close.find((x) => this.scanner.peek(x)) || this.scanner.isEOF()) {
1215
1328
  ok = false;
1216
1329
  break;
1217
1330
  }
@@ -1225,8 +1338,7 @@ var Parser = class {
1225
1338
  content.push({
1226
1339
  type: 4 /* Escaped */,
1227
1340
  content: this.scanner.acceptChar(),
1228
- start: posEnd - 1,
1229
- end: posEnd + 1
1341
+ location: this.#locFrom(posEnd - 1)
1230
1342
  });
1231
1343
  continue;
1232
1344
  }
@@ -1241,11 +1353,10 @@ var Parser = class {
1241
1353
  type: 8 /* Interpolation */,
1242
1354
  definition: result,
1243
1355
  argument: inner,
1244
- start: beforeInterp,
1245
- end: posEnd
1356
+ location: this.#locFrom(beforeInterp)
1246
1357
  });
1247
1358
  if (!ok2) {
1248
- this.emit.message(new ExpectedMessage(posEnd, result.postfix));
1359
+ this.emit.message(new ExpectedMessage(this.#loc(), result.postfix));
1249
1360
  ok = false;
1250
1361
  break;
1251
1362
  }
@@ -1255,8 +1366,7 @@ var Parser = class {
1255
1366
  }
1256
1367
  }
1257
1368
  return [{
1258
- start: posStart,
1259
- end: posEnd,
1369
+ location: this.#locFrom(posStart, posEnd),
1260
1370
  content
1261
1371
  }, ok];
1262
1372
  }
@@ -1277,24 +1387,171 @@ var Parser = class {
1277
1387
  return list;
1278
1388
  }
1279
1389
  };
1280
- function parse(scanner, config) {
1281
- return new Parser(scanner, config).parse();
1390
+ function parse(scanner, cxt) {
1391
+ return new Parser(scanner, cxt).parse();
1282
1392
  }
1283
1393
 
1394
+ // src/renderer.ts
1395
+ var RenderContext = class {
1396
+ constructor(config2, parseContext, state) {
1397
+ this.config = config2;
1398
+ this.parseContext = parseContext;
1399
+ this.state = state;
1400
+ }
1401
+ renderEntity(node) {
1402
+ switch (node.type) {
1403
+ case 1 /* Paragraph */:
1404
+ return this.config.paragraphRenderer?.(node, this);
1405
+ case 2 /* Preformatted */:
1406
+ case 3 /* Text */:
1407
+ case 4 /* Escaped */:
1408
+ return this.config.textRenderer?.(node, this);
1409
+ case 6 /* InlineModifier */:
1410
+ let ir = this.config.inlineRenderers.get(node.mod);
1411
+ if (ir) return ir(node, this);
1412
+ return this.config.undefinedInlineRenderer?.(node, this);
1413
+ case 7 /* BlockModifier */:
1414
+ let br = this.config.blockRenderers.get(node.mod);
1415
+ if (br) return br(node, this);
1416
+ return this.config.undefinedBlockRenderer?.(node, this);
1417
+ case 5 /* SystemModifier */:
1418
+ return void 0;
1419
+ default:
1420
+ return debug.never(node);
1421
+ }
1422
+ }
1423
+ };
1424
+ var RenderConfiguration = class _RenderConfiguration {
1425
+ constructor(options, postprocessor) {
1426
+ this.options = options;
1427
+ this.postprocessor = postprocessor;
1428
+ }
1429
+ paragraphRenderer;
1430
+ textRenderer;
1431
+ undefinedBlockRenderer;
1432
+ undefinedInlineRenderer;
1433
+ blockRenderers = /* @__PURE__ */ new Map();
1434
+ inlineRenderers = /* @__PURE__ */ new Map();
1435
+ render(doc, state) {
1436
+ let cxt = new RenderContext(this, doc.context, state);
1437
+ let results = doc.toStripped().root.content.map((x) => cxt.renderEntity(x)).filter((x) => x !== void 0);
1438
+ return this.postprocessor(results, cxt);
1439
+ }
1440
+ addBlockRenderer(...rs) {
1441
+ rs.forEach(([x, y]) => this.blockRenderers.set(x, y));
1442
+ }
1443
+ addInlineRenderer(...rs) {
1444
+ rs.forEach(([x, y]) => this.inlineRenderers.set(x, y));
1445
+ }
1446
+ static from(from) {
1447
+ let config2 = new _RenderConfiguration(from.options, from.postprocessor);
1448
+ config2.paragraphRenderer = from.paragraphRenderer;
1449
+ config2.textRenderer = from.textRenderer;
1450
+ config2.undefinedBlockRenderer = from.undefinedBlockRenderer;
1451
+ config2.undefinedInlineRenderer = from.undefinedInlineRenderer;
1452
+ config2.inlineRenderers = new Map(from.inlineRenderers);
1453
+ config2.blockRenderers = new Map(from.blockRenderers);
1454
+ return config2;
1455
+ }
1456
+ };
1457
+
1284
1458
  // src/modifier-helper.ts
1285
1459
  function checkArgumentLength(node, min, max = min) {
1286
1460
  if (min !== void 0 && node.arguments.length < min || max !== void 0 && node.arguments.length > max) {
1287
- return [new ArgumentCountMismatchMessage(node.head.start, node.head.end - node.head.start, min, max)];
1461
+ return [new ArgumentCountMismatchMessage({
1462
+ source: node.location.source,
1463
+ start: node.head.start,
1464
+ end: node.head.end
1465
+ }, min, max)];
1288
1466
  }
1289
1467
  return null;
1290
1468
  }
1291
1469
  function checkArguments(node, min, max = min) {
1292
1470
  const arg = node.arguments.find((x) => x.expansion === void 0);
1293
1471
  if (arg !== void 0) {
1294
- return [new CannotExpandArgumentMessage(arg.start, arg.end - arg.start)];
1472
+ return [new CannotExpandArgumentMessage(arg.location)];
1295
1473
  }
1296
1474
  return checkArgumentLength(node, min, max);
1297
1475
  }
1476
+ function onlyPermitPlaintextParagraph(node) {
1477
+ function checkInline(ents) {
1478
+ let result = "";
1479
+ for (const ent of ents) {
1480
+ switch (ent.type) {
1481
+ case 3 /* Text */:
1482
+ case 4 /* Escaped */:
1483
+ result += ent.content;
1484
+ break;
1485
+ case 5 /* SystemModifier */:
1486
+ break;
1487
+ case 6 /* InlineModifier */:
1488
+ if (!ent.expansion) return [new EntityNotAllowedMessage(
1489
+ ent.location,
1490
+ "it does not expand to plain text"
1491
+ )];
1492
+ let checkInner = checkInline(ent.expansion);
1493
+ if (Array.isArray(checkInner)) return checkInner;
1494
+ result += checkInner;
1495
+ break;
1496
+ default:
1497
+ return debug.never(ent);
1498
+ }
1499
+ }
1500
+ return result;
1501
+ }
1502
+ function check(ent) {
1503
+ if (ent.type == 7 /* BlockModifier */) {
1504
+ if (!ent.expansion) return [new EntityNotAllowedMessage(
1505
+ ent.location,
1506
+ "it does not expand to plain text"
1507
+ )];
1508
+ if (ent.expansion.length == 0) return "";
1509
+ else if (ent.expansion.length > 1) {
1510
+ let last = ent.expansion.at(-1).location;
1511
+ return [new MultipleBlocksNotPermittedMessage({
1512
+ source: last.source,
1513
+ start: ent.expansion[1].location.start,
1514
+ end: last.actualEnd ?? last.end
1515
+ })];
1516
+ }
1517
+ return check(ent.expansion[0]);
1518
+ } else if (ent.type !== 1 /* Paragraph */) {
1519
+ return [new OnlySimpleParagraphsPermittedMessage(ent.location)];
1520
+ }
1521
+ return checkInline(ent.content);
1522
+ }
1523
+ return check(node);
1524
+ }
1525
+ function onlyPermitSimpleParagraphs(node) {
1526
+ function check(nodes) {
1527
+ for (let ent of nodes) {
1528
+ if (ent.type == 7 /* BlockModifier */ && ent.expansion !== void 0) {
1529
+ const cs = check(ent.expansion);
1530
+ if (cs) return cs;
1531
+ } else if (ent.type !== 1 /* Paragraph */) {
1532
+ return [new OnlySimpleParagraphsPermittedMessage(ent.location)];
1533
+ }
1534
+ }
1535
+ return null;
1536
+ }
1537
+ return check(node.content);
1538
+ }
1539
+ function onlyPermitSingleBlock(node) {
1540
+ function check(nodes) {
1541
+ if (nodes.length > 1) {
1542
+ let last = nodes.at(-1).location;
1543
+ return [new MultipleBlocksNotPermittedMessage({
1544
+ source: last.source,
1545
+ start: nodes[1].location.start,
1546
+ end: last.actualEnd ?? last.end
1547
+ })];
1548
+ } else if (nodes.length == 1 && nodes[0].type === 7 /* BlockModifier */ && nodes[0].expansion !== void 0) {
1549
+ return check(nodes[0].expansion);
1550
+ }
1551
+ return null;
1552
+ }
1553
+ return check(node.content);
1554
+ }
1298
1555
 
1299
1556
  // src/builtin/internal.ts
1300
1557
  var builtins = Symbol();
@@ -1302,358 +1559,706 @@ function initParseContext(cxt) {
1302
1559
  cxt.init(builtins, {
1303
1560
  blockSlotDelayedStack: [],
1304
1561
  inlineSlotDelayedStack: [],
1305
- blockSlotData: [],
1306
- inlineSlotData: [],
1307
- notationStack: []
1562
+ blockInstantiationData: [],
1563
+ inlineInstantiationData: [],
1564
+ modules: /* @__PURE__ */ new Map(),
1565
+ usedModules: /* @__PURE__ */ new Set(),
1566
+ insideModule: void 0
1308
1567
  });
1309
1568
  }
1310
- function customModifier(type, name, argNames, slotName, content) {
1311
- debug.info(`registered custom ${type} modifier:`, name);
1312
- debug.info("args:", argNames, `with ${slotName == "" ? "no slot name" : "slot name: " + slotName}`);
1313
- debug.trace(() => "content is\n" + debugPrintNodes(content));
1314
- const mod = type == 7 /* BlockModifier */ ? new BlockModifierDefinition(name, 0 /* Normal */) : new InlineModifierDefinition(name, 0 /* Normal */);
1569
+ function customModifier(type, name, signature, content) {
1570
+ debug.info(`created custom ${NodeType[type]}:`, name);
1571
+ debug.info("args:", signature.args, `with ${signature.slotName === void 0 ? "no slot" : signature.slotName == "" ? "empty slot name" : "slot name: " + signature.slotName}`);
1572
+ debug.trace(() => "content is\n" + debugPrint.node(...content));
1573
+ const flag = signature.slotName === void 0 ? 2 /* None */ : signature.preformatted ? 1 /* Preformatted */ : 0 /* Normal */;
1574
+ const mod = type == 7 /* BlockModifier */ ? new BlockModifierDefinition(name, flag) : new InlineModifierDefinition(name, flag);
1315
1575
  const isInline = type == 6 /* InlineModifier */;
1576
+ if (content.length == 1 && (content[0].type == 7 /* BlockModifier */ || content[0].type == 6 /* InlineModifier */))
1577
+ mod.roleHint = content[0].mod.roleHint;
1316
1578
  mod.delayContentExpansion = true;
1317
1579
  mod.prepareExpand = (node, cxt) => {
1318
- let check = checkArguments(node, argNames.length);
1580
+ let check = checkArguments(node, signature.args.length);
1319
1581
  if (check) return check;
1320
1582
  node.state = {
1321
1583
  ok: true,
1322
- args: new Map(node.arguments.map((x, i) => [argNames[i], x.expansion]))
1584
+ args: new Map(node.arguments.map((x, i) => [signature.args[i], x.expansion]))
1323
1585
  };
1324
1586
  return [];
1325
1587
  };
1326
- mod.expand = (node, cxt) => {
1588
+ mod.expand = (node) => {
1327
1589
  if (!node.state?.ok) return [];
1328
- const contentClone = cloneNodes(content);
1590
+ const contentClone = cloneNodes(content, { newLocation: node.location });
1329
1591
  return contentClone;
1330
1592
  };
1331
1593
  mod.beforeProcessExpansion = (node, cxt) => {
1332
1594
  if (!node.state?.ok) return [];
1333
1595
  const store = cxt.get(builtins);
1334
- const data = isInline ? store.inlineSlotData : store.blockSlotData;
1335
- data.push([slotName, {
1596
+ const data = isInline ? store.inlineInstantiationData : store.blockInstantiationData;
1597
+ data.push({
1598
+ slotName: signature.slotName,
1336
1599
  mod,
1337
1600
  args: node.state.args,
1338
1601
  slotContent: node.content
1339
- }]);
1602
+ });
1340
1603
  debug.trace(
1341
- `pushed ${type} slot data for`,
1604
+ `pushed ${NodeType[type]} slot data for`,
1342
1605
  name,
1343
- slotName == "" ? "(unnamed)" : `= ${slotName}`
1606
+ signature.slotName == "" ? "(unnamed)" : `= ${signature.slotName}`
1344
1607
  );
1345
1608
  return [];
1346
1609
  };
1347
1610
  mod.afterProcessExpansion = (node, cxt) => {
1348
- if (!node.state?.ok) return [];
1611
+ if (!node.state?.ok || signature.slotName === void 0) return [];
1349
1612
  const store = cxt.get(builtins);
1350
- const data = isInline ? store.inlineSlotData : store.blockSlotData;
1613
+ const data = isInline ? store.inlineInstantiationData : store.blockInstantiationData;
1351
1614
  const pop = data.pop();
1352
- assert(pop !== void 0 && pop[0] == slotName);
1615
+ assert(pop !== void 0);
1353
1616
  debug.trace(
1354
- `popped ${type} slot data for`,
1617
+ `popped ${NodeType[type]} slot data for`,
1355
1618
  name,
1356
- slotName == "" ? "(unnamed)" : `= ${slotName}`
1619
+ signature.slotName == "" ? "(unnamed)" : `= ${signature.slotName}`
1357
1620
  );
1358
1621
  return [];
1359
1622
  };
1360
1623
  return mod;
1361
1624
  }
1362
-
1363
- // src/builtin/define-block.ts
1364
- var DefineBlockMod = new SystemModifierDefinition("define-block", 0 /* Normal */, {
1365
- // .define-block:name:args...[:(slot-id)]
1366
- delayContentExpansion: true,
1367
- alwaysTryExpand: true,
1368
- beforeParseContent(node, cxt) {
1369
- const check = checkArgumentLength(node, 1, Infinity);
1370
- if (check) return check;
1371
- const msgs = [];
1372
- const name = node.arguments[0];
1373
- const nameValue = name.expansion;
1374
- let slotName = "";
1375
- if (node.arguments.length > 1) {
1376
- const last = node.arguments.at(-1);
1377
- if (last.expansion)
1378
- slotName = /^\(.+\)$/.test(last.expansion) ? last.expansion.substring(1, last.expansion.length - 1) : "";
1379
- else msgs.push(
1380
- new InvalidArgumentMessage(last.start, last.end - last.start)
1381
- );
1625
+ function makeInlineDefinition(node, msgs) {
1626
+ let lastIsParagraph = false;
1627
+ let concat = [];
1628
+ for (const n of node.content) {
1629
+ switch (n.type) {
1630
+ case 1 /* Paragraph */:
1631
+ if (!lastIsParagraph) {
1632
+ lastIsParagraph = true;
1633
+ concat.push(...n.content);
1634
+ continue;
1635
+ }
1636
+ case 2 /* Preformatted */:
1637
+ case 7 /* BlockModifier */:
1638
+ msgs.push(new EntityNotAllowedMessage(n.location));
1639
+ break;
1640
+ case 5 /* SystemModifier */:
1641
+ lastIsParagraph = false;
1642
+ concat.push(n);
1643
+ break;
1644
+ default:
1645
+ debug.never(n);
1382
1646
  }
1383
- const args = node.arguments.slice(1, slotName !== "" ? node.arguments.length - 1 : void 0).map((x) => {
1384
- if (!x.expansion) msgs.push(
1385
- new InvalidArgumentMessage(x.start, x.end - x.start)
1386
- );
1387
- return x.expansion ?? "";
1388
- });
1389
- node.state = { name: nameValue, slotName, args, msgs };
1390
- const store = cxt.get(builtins);
1391
- store.blockSlotDelayedStack.push(node.state.slotName);
1392
- debug.trace("entering block definition:", node.state.name);
1393
- return [];
1394
- },
1395
- afterParseContent(node, cxt) {
1396
- if (!node.state) return [];
1397
- const store = cxt.get(builtins);
1398
- assert(store.blockSlotDelayedStack.pop() == node.state.slotName);
1399
- debug.trace("leaving block definition", node.state.name);
1400
- return [];
1401
- },
1402
- prepareExpand(node, cxt, immediate) {
1403
- if (!immediate || !node.state) return [];
1404
- const arg = node.arguments[0];
1405
- if (!node.state.name)
1406
- return [new InvalidArgumentMessage(arg.start, arg.end - arg.start)];
1407
- if (cxt.config.blockModifiers.has(node.state.name))
1408
- return [new NameAlreadyDefinedMessage(
1409
- arg.start,
1410
- arg.end - arg.start,
1411
- node.state.name
1412
- )];
1413
- return [];
1414
- },
1415
- expand(node, cxt, immediate) {
1416
- if (!immediate) return void 0;
1417
- if (node.state?.name) {
1418
- if (cxt.config.blockModifiers.has(node.state.name))
1419
- cxt.config.blockModifiers.remove(node.state.name);
1420
- cxt.config.blockModifiers.add(
1421
- customModifier(
1647
+ }
1648
+ return concat;
1649
+ }
1650
+
1651
+ // src/builtin/define-modifier.ts
1652
+ function parseDefineArguments(node, stack) {
1653
+ const check = checkArgumentLength(node, 1, Infinity);
1654
+ if (check) return check;
1655
+ const msgs = [];
1656
+ const name = node.arguments[0];
1657
+ const nameValue = name.expansion;
1658
+ if (nameValue === "" || nameValue?.includes("\n")) return [
1659
+ new InvalidArgumentMessage(name.location, nameValue)
1660
+ ];
1661
+ let slotName = "";
1662
+ if (node.arguments.length > 1) {
1663
+ const last = node.arguments.at(-1);
1664
+ if (last.expansion) {
1665
+ const match = /^\((.*)\)$/.exec(last.expansion);
1666
+ slotName = match ? match[1] : "";
1667
+ } else msgs.push(
1668
+ new InvalidArgumentMessage(last.location)
1669
+ );
1670
+ }
1671
+ const args = node.arguments.slice(1, slotName !== "" ? node.arguments.length - 1 : void 0).map((x) => {
1672
+ if (!x.expansion) msgs.push(
1673
+ new InvalidArgumentMessage(x.location)
1674
+ );
1675
+ return x.expansion ?? "";
1676
+ });
1677
+ let signature = { slotName, args, preformatted: void 0 };
1678
+ node.state = { name: nameValue, signature, msgs };
1679
+ stack.push(signature);
1680
+ return void 0;
1681
+ }
1682
+ var DefineBlockMod = new SystemModifierDefinition(
1683
+ "define-block",
1684
+ 0 /* Normal */,
1685
+ {
1686
+ // .define-block:name:args...[:(slot-id)]
1687
+ delayContentExpansion: true,
1688
+ alwaysTryExpand: true,
1689
+ beforeParseContent(node, cxt) {
1690
+ const store = cxt.get(builtins);
1691
+ const check = parseDefineArguments(node, store.blockSlotDelayedStack);
1692
+ if (check) return check;
1693
+ debug.trace("entering block definition:", node.state.name);
1694
+ return [];
1695
+ },
1696
+ afterParseContent(node, cxt) {
1697
+ if (!node.state) return [];
1698
+ const store = cxt.get(builtins);
1699
+ const pop = store.blockSlotDelayedStack.pop();
1700
+ assert(pop === node.state.signature);
1701
+ debug.trace("leaving block definition", node.state.name);
1702
+ return [];
1703
+ },
1704
+ prepareExpand(node, cxt, immediate) {
1705
+ if (!immediate || !node.state) return [];
1706
+ const arg = node.arguments[0];
1707
+ const msgs = node.state.msgs;
1708
+ if (!node.state.name)
1709
+ msgs.push(new InvalidArgumentMessage(arg.location));
1710
+ else if (cxt.config.blockModifiers.has(node.state.name))
1711
+ msgs.push(new NameAlreadyDefinedMessage(arg.location, node.state.name));
1712
+ return msgs;
1713
+ },
1714
+ expand(node, cxt, immediate) {
1715
+ if (!immediate) return void 0;
1716
+ if (node.state?.name) {
1717
+ if (cxt.config.blockModifiers.has(node.state.name))
1718
+ cxt.config.blockModifiers.remove(node.state.name);
1719
+ cxt.config.blockModifiers.add(customModifier(
1422
1720
  7 /* BlockModifier */,
1423
1721
  node.state.name,
1424
- node.state.args,
1425
- node.state.slotName,
1722
+ node.state.signature,
1426
1723
  node.content
1427
- )
1724
+ ));
1725
+ }
1726
+ return [];
1727
+ }
1728
+ }
1729
+ );
1730
+ var DefineInlineMod = new SystemModifierDefinition(
1731
+ "define-inline",
1732
+ 0 /* Normal */,
1733
+ {
1734
+ // .define-inline name:args...[:(slot-id)]
1735
+ delayContentExpansion: true,
1736
+ alwaysTryExpand: true,
1737
+ beforeParseContent(node, cxt) {
1738
+ const store = cxt.get(builtins);
1739
+ const check = parseDefineArguments(node, store.inlineSlotDelayedStack);
1740
+ if (check) return check;
1741
+ debug.trace("entering inline definition:", node.state.name);
1742
+ return [];
1743
+ },
1744
+ afterParseContent(node, cxt) {
1745
+ if (!node.state) return [];
1746
+ const store = cxt.get(builtins);
1747
+ const pop = store.inlineSlotDelayedStack.pop();
1748
+ assert(pop === node.state.signature);
1749
+ debug.trace("leaving inline definition", node.state.name);
1750
+ return [];
1751
+ },
1752
+ prepareExpand(node, cxt, immediate) {
1753
+ if (!immediate || !node.state) return [];
1754
+ const arg = node.arguments[0];
1755
+ if (!node.state.name)
1756
+ return [new InvalidArgumentMessage(arg.location)];
1757
+ const msgs = node.state.msgs;
1758
+ if (cxt.config.inlineModifiers.has(node.state.name))
1759
+ msgs.push(new NameAlreadyDefinedMessage(arg.location, node.state.name));
1760
+ node.state.definition = makeInlineDefinition(node, msgs);
1761
+ return msgs;
1762
+ },
1763
+ expand(node, cxt, immediate) {
1764
+ if (!immediate) return void 0;
1765
+ if (node.state?.name) {
1766
+ if (cxt.config.inlineModifiers.has(node.state.name))
1767
+ cxt.config.inlineModifiers.remove(node.state.name);
1768
+ cxt.config.inlineModifiers.add(
1769
+ customModifier(
1770
+ 6 /* InlineModifier */,
1771
+ node.state.name,
1772
+ node.state.signature,
1773
+ node.state.definition
1774
+ )
1775
+ );
1776
+ }
1777
+ return [];
1778
+ }
1779
+ }
1780
+ );
1781
+
1782
+ // src/builtin/define-shorthand.ts
1783
+ function parseDefineArguments2(type, node, stack) {
1784
+ const check = checkArguments(node, 1, Infinity);
1785
+ if (check) return check;
1786
+ const msgs = [];
1787
+ const name = node.arguments[0];
1788
+ const nameValue = name.expansion;
1789
+ if (nameValue === "" || nameValue?.includes("\n")) return [
1790
+ new InvalidArgumentMessage(name.location, nameValue)
1791
+ ];
1792
+ let slotName = void 0;
1793
+ let parts = [];
1794
+ let postfix = void 0;
1795
+ let i = 1;
1796
+ while (i < node.arguments.length) {
1797
+ const arg = node.arguments[i];
1798
+ const match = /^\((.*)\)$/.exec(arg.expansion);
1799
+ if (match) {
1800
+ slotName = match[1];
1801
+ i++;
1802
+ if (type == 6 /* InlineModifier */) {
1803
+ if (i < node.arguments.length) {
1804
+ if (node.arguments[i].expansion === "") {
1805
+ msgs.push(new InvalidArgumentMessage(
1806
+ node.arguments[i].location,
1807
+ "postfix"
1808
+ ));
1809
+ } else {
1810
+ postfix = node.arguments[i].expansion;
1811
+ i++;
1812
+ }
1813
+ } else msgs.push(
1814
+ new ArgumentCountMismatchMessage(node.location)
1815
+ );
1816
+ }
1817
+ break;
1818
+ }
1819
+ i++;
1820
+ if (i < node.arguments.length) {
1821
+ const id = arg.expansion;
1822
+ if (id === "") {
1823
+ return [new InvalidArgumentMessage(arg.location, "id")];
1824
+ }
1825
+ const part = node.arguments[i].expansion;
1826
+ if (part === "") {
1827
+ return [new InvalidArgumentMessage(
1828
+ node.arguments[i].location,
1829
+ "part"
1830
+ )];
1831
+ }
1832
+ parts.push([id, part]);
1833
+ i++;
1834
+ } else {
1835
+ msgs.push(new ArgumentCountMismatchMessage(node.location));
1836
+ break;
1837
+ }
1838
+ }
1839
+ if (i == node.arguments.length - 1) {
1840
+ const last = node.arguments[i];
1841
+ if (last.expansion !== "") msgs.push(
1842
+ new InvalidArgumentMessage(last.location, "(must be empty)")
1843
+ );
1844
+ } else if (i < node.arguments.length - 1)
1845
+ msgs.push(new ArgumentCountMismatchMessage(node.location));
1846
+ let signature = { slotName, args: parts.map((x) => x[0]), preformatted: void 0 };
1847
+ node.state = { name: nameValue, signature, parts, postfix, msgs };
1848
+ stack.push(signature);
1849
+ return [];
1850
+ }
1851
+ var DefineBlockShorthandMod = new SystemModifierDefinition(
1852
+ "block-shorthand",
1853
+ 0 /* Normal */,
1854
+ {
1855
+ // -inline-shorthand prefix:arg1:part1:arg2:part2...:(slot):postfix:
1856
+ delayContentExpansion: true,
1857
+ alwaysTryExpand: true,
1858
+ beforeParseContent(node, cxt) {
1859
+ const store = cxt.get(builtins);
1860
+ const check = parseDefineArguments2(
1861
+ 7 /* BlockModifier */,
1862
+ node,
1863
+ store.blockSlotDelayedStack
1864
+ );
1865
+ if (check) return check;
1866
+ debug.trace("entering block shorthand definition", node.state.name);
1867
+ return [];
1868
+ },
1869
+ afterParseContent(node, cxt) {
1870
+ if (!node.state) return [];
1871
+ const store = cxt.get(builtins);
1872
+ const pop = store.blockSlotDelayedStack.pop();
1873
+ assert(pop === node.state.signature);
1874
+ debug.trace("leaving inline shorthand definition", node.state.name);
1875
+ return [];
1876
+ },
1877
+ prepareExpand(node, cxt, immediate) {
1878
+ if (!immediate || !node.state) return [];
1879
+ const arg = node.arguments[0];
1880
+ if (!node.state)
1881
+ return [new InvalidArgumentMessage(arg.location)];
1882
+ const msgs = node.state.msgs;
1883
+ if (cxt.config.blockShorthands.has(node.state.name))
1884
+ msgs.push(new NameAlreadyDefinedMessage(arg.location, node.state.name));
1885
+ return msgs;
1886
+ },
1887
+ expand(node, cxt, immediate) {
1888
+ if (!immediate || !node.state) return void 0;
1889
+ const name = "<block shorthand>";
1890
+ const parts = node.state.parts.map((x) => x[1]);
1891
+ const mod = customModifier(
1892
+ 7 /* BlockModifier */,
1893
+ name,
1894
+ node.state.signature,
1895
+ node.content
1428
1896
  );
1897
+ const shorthand = {
1898
+ name: node.state.name,
1899
+ postfix: node.state.postfix,
1900
+ mod,
1901
+ parts
1902
+ };
1903
+ if (cxt.config.blockShorthands.has(node.state.name))
1904
+ cxt.config.blockShorthands.remove(node.state.name);
1905
+ cxt.config.blockShorthands.add(shorthand);
1906
+ debug.info(() => "created block shorthand: " + debugPrint.blockShorthand(shorthand));
1907
+ return [];
1429
1908
  }
1430
- return [];
1431
1909
  }
1432
- });
1433
-
1434
- // src/builtin/define-inline.ts
1435
- var DefineInlineMod = new SystemModifierDefinition("define-inline", 0 /* Normal */, {
1436
- // .define-inline name:args...[:(slot-id)]
1437
- delayContentExpansion: true,
1438
- alwaysTryExpand: true,
1439
- beforeParseContent(node, cxt) {
1440
- const check = checkArgumentLength(node, 1, Infinity);
1441
- if (check) return check;
1442
- const msgs = [];
1443
- const name = node.arguments[0];
1444
- const nameValue = name.expansion;
1445
- if (nameValue && cxt.config.inlineModifiers.has(nameValue))
1446
- msgs.push(new NameAlreadyDefinedMessage(
1447
- node.start,
1448
- name.end - name.start,
1449
- nameValue
1450
- ));
1451
- let slotName = "";
1452
- if (node.arguments.length > 1) {
1453
- const last = node.arguments.at(-1);
1454
- if (last.expansion)
1455
- slotName = /^\(.+\)$/.test(last.expansion) ? last.expansion.substring(1, last.expansion.length - 1) : "";
1456
- else msgs.push(
1457
- new InvalidArgumentMessage(last.start, last.end - last.start)
1458
- );
1459
- }
1460
- const args = node.arguments.slice(1, slotName !== "" ? node.arguments.length - 1 : void 0).map((x) => {
1461
- if (!x.expansion) msgs.push(
1462
- new InvalidArgumentMessage(x.start, x.end - x.start)
1910
+ );
1911
+ var DefineInlineShorthandMod = new SystemModifierDefinition(
1912
+ "inline-shorthand",
1913
+ 0 /* Normal */,
1914
+ {
1915
+ // -inline-shorthand prefix:arg1:part1:arg2:part2...:(slot):postfix:
1916
+ delayContentExpansion: true,
1917
+ alwaysTryExpand: true,
1918
+ beforeParseContent(node, cxt) {
1919
+ const store = cxt.get(builtins);
1920
+ const check = parseDefineArguments2(
1921
+ 6 /* InlineModifier */,
1922
+ node,
1923
+ store.inlineSlotDelayedStack
1463
1924
  );
1464
- return x.expansion ?? "";
1465
- });
1466
- node.state = { name: nameValue, slotName, args, msgs };
1467
- const store = cxt.get(builtins);
1468
- store.inlineSlotDelayedStack.push(node.state.slotName);
1469
- debug.trace("entering inline definition:", node.state.name);
1470
- return [];
1471
- },
1472
- afterParseContent(node, cxt) {
1473
- if (!node.state) return [];
1474
- const store = cxt.get(builtins);
1475
- assert(store.inlineSlotDelayedStack.pop() == node.state.slotName);
1476
- debug.trace("leaving inline definition", node.state.name);
1477
- return [];
1478
- },
1479
- prepareExpand(node, cxt, immediate) {
1480
- if (!immediate || !node.state) return [];
1481
- const arg = node.arguments[0];
1482
- if (!node.state.name)
1483
- return [new InvalidArgumentMessage(arg.start, arg.end - arg.start)];
1484
- const msgs = [];
1485
- if (cxt.config.inlineModifiers.has(node.state.name))
1486
- msgs.push(new NameAlreadyDefinedMessage(
1487
- arg.start,
1488
- arg.end - arg.start,
1489
- node.state.name
1490
- ));
1491
- let lastIsParagraph = false;
1492
- let concat = [];
1493
- for (const n of node.content) {
1494
- switch (n.type) {
1495
- case 1 /* Paragraph */:
1496
- if (!lastIsParagraph) {
1497
- lastIsParagraph = true;
1498
- concat.push(...n.content);
1499
- continue;
1500
- }
1501
- case 2 /* Preformatted */:
1502
- case 7 /* BlockModifier */:
1503
- msgs.push(new InlineDefinitonInvalidEntityMessage(n.start, n.end - n.start));
1504
- break;
1505
- case 5 /* SystemModifier */:
1506
- lastIsParagraph = false;
1507
- concat.push(n);
1508
- break;
1509
- default:
1510
- debug.never(n);
1511
- }
1512
- }
1513
- node.state.definition = concat;
1514
- return msgs;
1515
- },
1516
- expand(node, cxt, immediate) {
1517
- if (!immediate) return void 0;
1518
- if (node.state?.name) {
1519
- if (cxt.config.inlineModifiers.has(node.state.name))
1520
- cxt.config.inlineModifiers.remove(node.state.name);
1521
- cxt.config.inlineModifiers.add(
1522
- customModifier(
1523
- 6 /* InlineModifier */,
1524
- node.state.name,
1525
- node.state.args,
1526
- node.state.slotName,
1527
- node.state.definition
1528
- )
1925
+ if (check) return check;
1926
+ debug.trace("entering inline shorthand definition", node.state.name);
1927
+ return [];
1928
+ },
1929
+ afterParseContent(node, cxt) {
1930
+ if (!node.state) return [];
1931
+ const store = cxt.get(builtins);
1932
+ const pop = store.inlineSlotDelayedStack.pop();
1933
+ assert(pop === node.state.signature);
1934
+ debug.trace("leaving inline shorthand definition", node.state.name);
1935
+ return [];
1936
+ },
1937
+ prepareExpand(node, cxt, immediate) {
1938
+ if (!immediate || !node.state) return [];
1939
+ const arg = node.arguments[0];
1940
+ if (!node.state)
1941
+ return [new InvalidArgumentMessage(arg.location)];
1942
+ const msgs = node.state.msgs;
1943
+ if (cxt.config.inlineShorthands.has(node.state.name))
1944
+ msgs.push(new NameAlreadyDefinedMessage(arg.location, node.state.name));
1945
+ node.state.definition = makeInlineDefinition(node, msgs);
1946
+ return msgs;
1947
+ },
1948
+ expand(node, cxt, immediate) {
1949
+ if (!immediate || !node.state) return void 0;
1950
+ const name = "<inline shorthand>";
1951
+ const parts = node.state.parts.map((x) => x[1]);
1952
+ const mod = customModifier(
1953
+ 6 /* InlineModifier */,
1954
+ name,
1955
+ node.state.signature,
1956
+ node.state.definition
1529
1957
  );
1958
+ const shorthand = {
1959
+ name: node.state.name,
1960
+ postfix: node.state.postfix,
1961
+ mod,
1962
+ parts
1963
+ };
1964
+ if (cxt.config.inlineShorthands.has(node.state.name))
1965
+ cxt.config.inlineShorthands.remove(node.state.name);
1966
+ cxt.config.inlineShorthands.add(shorthand);
1967
+ debug.info(() => "created inline shorthand: " + debugPrint.inlineShorthand(shorthand));
1968
+ return [];
1530
1969
  }
1531
- return [];
1532
1970
  }
1533
- });
1971
+ );
1534
1972
 
1535
- // src/builtin/pushpop.ts
1536
- var PushNotationMod = new SystemModifierDefinition(
1537
- "push-notation",
1538
- 2 /* Marker */,
1973
+ // src/builtin/module.ts
1974
+ function getDefs(cxt) {
1975
+ const data = cxt.get(builtins);
1976
+ return {
1977
+ usedModules: new Set(data.usedModules),
1978
+ blocks: cxt.config.blockModifiers.toSet(),
1979
+ inlines: cxt.config.inlineModifiers.toSet(),
1980
+ inlineShorthands: cxt.config.inlineShorthands.toSet(),
1981
+ blockShorthands: cxt.config.blockShorthands.toSet()
1982
+ };
1983
+ }
1984
+ function applyDefs(cxt, defs) {
1985
+ const data = cxt.get(builtins);
1986
+ data.usedModules = new Set(defs.usedModules);
1987
+ cxt.config.blockModifiers = new NameManager(defs.blocks);
1988
+ cxt.config.inlineModifiers = new NameManager(defs.inlines);
1989
+ cxt.config.inlineShorthands = new NameManager(defs.inlineShorthands);
1990
+ cxt.config.blockShorthands = new NameManager(defs.blockShorthands);
1991
+ }
1992
+ function add(snew, sold, transform) {
1993
+ let newNames = new Set([...snew].map((x) => x.name));
1994
+ let out = new Set(snew);
1995
+ let overlap = [];
1996
+ for (const x of sold) {
1997
+ if (newNames.has(x.name))
1998
+ overlap.push(x);
1999
+ else
2000
+ out.add(x);
2001
+ }
2002
+ return [out, overlap.map(transform).join(", ")];
2003
+ }
2004
+ function diffDef(cnew, cold) {
2005
+ return {
2006
+ usedModules: cnew.usedModules.difference(cold.usedModules),
2007
+ blocks: cnew.blocks.difference(cold.blocks),
2008
+ inlines: cnew.inlines.difference(cold.inlines),
2009
+ inlineShorthands: cnew.inlineShorthands.difference(cold.inlineShorthands),
2010
+ blockShorthands: cnew.blockShorthands.difference(cold.blockShorthands)
2011
+ };
2012
+ }
2013
+ function addDef(cnew, cold) {
2014
+ let [blocks, s1] = add(cnew.blocks, cold.blocks, debugPrint.blockModifier);
2015
+ let [inlines, s2] = add(cnew.inlines, cold.inlines, debugPrint.inlineModifier);
2016
+ let [inlineShorthands, s3] = add(cnew.inlineShorthands, cold.inlineShorthands, debugPrint.inlineShorthand);
2017
+ let [blockShorthands, s4] = add(cnew.blockShorthands, cold.blockShorthands, debugPrint.blockShorthand);
2018
+ return [
2019
+ {
2020
+ usedModules: cnew.usedModules.union(cold.usedModules),
2021
+ blocks,
2022
+ inlines,
2023
+ inlineShorthands,
2024
+ blockShorthands
2025
+ },
2026
+ (s1 ? s1 + "; " : "") + (s2 ? s2 + "; " : "") + (s3 ? "inline shorthand " + s3 + "; " : "") + (s4 ? "block shorthand " + s4 : "")
2027
+ ];
2028
+ }
2029
+ var ModuleMod = new BlockModifierDefinition(
2030
+ "module",
2031
+ 0 /* Normal */,
1539
2032
  {
1540
- expand(_, cxt) {
2033
+ expand(node) {
2034
+ return [];
2035
+ },
2036
+ beforeParseContent(node, cxt) {
2037
+ const check = checkArguments(node, 1);
2038
+ if (check) return check;
2039
+ const data = cxt.get(builtins);
2040
+ const name = node.arguments[0].expansion;
2041
+ const defs = getDefs(cxt);
2042
+ if (data.insideModule !== void 0) {
2043
+ return [new NoNestedModuleMessage(node.head)];
2044
+ }
2045
+ let msgs = [];
2046
+ node.state = { name, defs };
2047
+ data.insideModule = name;
2048
+ if (data.modules.has(name)) {
2049
+ const [added, msg] = addDef(defs, data.modules.get(name));
2050
+ if (msg) msgs.push(
2051
+ new OverwriteDefinitionsMessage(node.head, msg)
2052
+ );
2053
+ applyDefs(cxt, added);
2054
+ debug.trace("entering defs for module", name, "(earlier data loaded)");
2055
+ } else {
2056
+ debug.trace("entering defs for module", name);
2057
+ }
2058
+ return msgs;
2059
+ },
2060
+ afterParseContent(node, cxt) {
2061
+ if (!node.state) return [];
1541
2062
  const data = cxt.get(builtins);
1542
- data.notationStack.push({
1543
- blocks: cxt.config.blockModifiers.toArray(),
1544
- inlines: cxt.config.inlineModifiers.toArray()
1545
- });
2063
+ data.insideModule = void 0;
2064
+ data.modules.set(
2065
+ node.state.name,
2066
+ diffDef(getDefs(cxt), node.state.defs)
2067
+ );
2068
+ applyDefs(cxt, node.state.defs);
2069
+ debug.trace("exiting defs for module", node.state.name);
1546
2070
  return [];
1547
2071
  }
1548
2072
  }
1549
2073
  );
1550
- var PopNotationMod = new SystemModifierDefinition(
1551
- "pop-notation",
1552
- 2 /* Marker */,
2074
+ var UseSystemMod = new SystemModifierDefinition(
2075
+ "use",
2076
+ 2 /* None */,
1553
2077
  {
1554
2078
  prepareExpand(node, cxt) {
2079
+ const check = checkArguments(node, 1);
2080
+ if (check) return check;
1555
2081
  const data = cxt.get(builtins);
1556
- const result = data.notationStack.pop();
1557
- if (!result) return [
1558
- new CannotPopNotationMessage(node.start, node.end - node.start)
1559
- ];
1560
- cxt.config.blockModifiers = new NameManager(result.blocks);
1561
- cxt.config.inlineModifiers = new NameManager(result.inlines);
2082
+ const name = node.arguments[0];
2083
+ if (!data.modules.has(name.expansion))
2084
+ return [new InvalidArgumentMessage(name.location)];
2085
+ if (data.insideModule === name.expansion)
2086
+ return [new CannotUseModuleInSelfMessage(name.location)];
2087
+ const [added, msg] = addDef(data.modules.get(name.expansion), getDefs(cxt));
2088
+ node.state = added;
2089
+ if (msg)
2090
+ return [new OverwriteDefinitionsMessage(node.head, msg)];
2091
+ return [];
2092
+ },
2093
+ expand(node, cxt) {
2094
+ if (node.state)
2095
+ applyDefs(cxt, node.state);
2096
+ return [];
2097
+ }
2098
+ }
2099
+ );
2100
+ var UseBlockMod = new BlockModifierDefinition(
2101
+ "use",
2102
+ 0 /* Normal */,
2103
+ {
2104
+ beforeParseContent(node, cxt) {
2105
+ const check = checkArguments(node, 1);
2106
+ if (check) return check;
2107
+ const data = cxt.get(builtins);
2108
+ const name = node.arguments[0];
2109
+ if (!data.modules.has(name.expansion))
2110
+ return [new InvalidArgumentMessage(name.location)];
2111
+ if (data.insideModule === name.expansion)
2112
+ return [new CannotUseModuleInSelfMessage(name.location)];
2113
+ const old = getDefs(cxt);
2114
+ const [added, msg] = addDef(data.modules.get(name.expansion), old);
2115
+ applyDefs(cxt, added);
2116
+ node.state = { old };
2117
+ if (msg)
2118
+ return [new OverwriteDefinitionsMessage(node.head, msg)];
1562
2119
  return [];
1563
2120
  },
1564
- expand() {
2121
+ afterParseContent(node, cxt) {
2122
+ if (node.state)
2123
+ applyDefs(cxt, node.state.old);
1565
2124
  return [];
2125
+ },
2126
+ expand(node) {
2127
+ return node.content;
1566
2128
  }
1567
2129
  }
1568
2130
  );
1569
2131
 
1570
2132
  // src/builtin/slot.ts
1571
- function slotModifier(type) {
1572
- const mod = type == 7 /* BlockModifier */ ? new BlockModifierDefinition("slot", 2 /* Marker */) : new InlineModifierDefinition("slot", 2 /* Marker */);
2133
+ function slotModifier(name, type, preformatted, inject) {
2134
+ const mod = type == 7 /* BlockModifier */ ? new BlockModifierDefinition(name, 2 /* None */) : new InlineModifierDefinition(name, 2 /* None */);
1573
2135
  const isInline = type == 6 /* InlineModifier */;
1574
2136
  mod.alwaysTryExpand = true;
1575
2137
  mod.prepareExpand = (node, cxt, immediate) => {
1576
2138
  if (node.state) return [];
1577
- const check = checkArgumentLength(node, 0, 1);
1578
- if (check && immediate) {
2139
+ function processSignature(s) {
2140
+ if (s.preformatted === void 0) {
2141
+ s.preformatted = preformatted;
2142
+ debug.trace("set preformatted to ", preformatted);
2143
+ } else if (s.preformatted !== preformatted) {
2144
+ return [new EitherNormalOrPreMessage(node.location)];
2145
+ }
2146
+ return [];
2147
+ }
2148
+ const check = inject ? checkArguments(node, 1, 2) : checkArguments(node, 0, 1);
2149
+ if (check) {
1579
2150
  node.state = { ok: false };
1580
2151
  return check;
1581
2152
  }
1582
- const store = cxt.get(builtins);
1583
- const data = isInline ? store.inlineSlotData : store.blockSlotData;
1584
- let id = "";
1585
- if (node.arguments.length == 1) {
1586
- const arg = node.arguments[0];
1587
- if (!arg.expansion) {
2153
+ const msgs = (() => {
2154
+ const store = cxt.get(builtins);
2155
+ const data = isInline ? store.inlineInstantiationData : store.blockInstantiationData;
2156
+ const stack = isInline ? store.inlineSlotDelayedStack : store.blockSlotDelayedStack;
2157
+ if (data.length == 0 && stack.length == 0) {
1588
2158
  node.state = { ok: false };
1589
- return [new InvalidArgumentMessage(arg.start, arg.end - arg.start)];
2159
+ return [new SlotUsedOutsideDefinitionMessage(node.location)];
2160
+ }
2161
+ if (node.arguments.length == (inject ? 1 : 0)) {
2162
+ let signature2 = stack.at(-1);
2163
+ if (signature2) return processSignature(signature2);
2164
+ node.state = { ok: true, data: data.at(-1), index: data.length - 1 };
2165
+ return;
2166
+ }
2167
+ const id = node.arguments[0].expansion;
2168
+ let signature = stack.find((x) => x.slotName == id);
2169
+ if (signature) return processSignature(signature);
2170
+ for (let i = data.length - 1; i >= 0; i--) if (data[i].slotName === id) {
2171
+ node.state = { ok: true, data: data[i], index: i };
2172
+ return;
1590
2173
  }
1591
- id = arg.expansion;
1592
- }
1593
- if (data.length == 0) {
1594
2174
  if (immediate) {
1595
2175
  node.state = { ok: false };
1596
- return [new SlotUsedOutsideDefinitionMessage(node.start, node.head.end - node.start)];
2176
+ const arg = node.arguments[0];
2177
+ return [new InvalidArgumentMessage(arg.location, id)];
1597
2178
  }
1598
- return [];
1599
- }
1600
- const stack = isInline ? store.inlineSlotDelayedStack : store.blockSlotDelayedStack;
1601
- if (stack.includes(id)) {
1602
- debug.trace("delaying", id == "" ? "unnamed slot" : "slot: " + id);
1603
- return [];
1604
- }
1605
- if (node.arguments.length == 0) {
1606
- node.state = { ok: true, data: data.at(-1), index: data.length - 1 };
1607
- return [];
1608
- }
1609
- for (let i = data.length - 1; i >= 0; i--) if (data[i][0] == id) {
1610
- node.state = { ok: true, data: data[i], index: i };
1611
- return [];
1612
- }
1613
- if (immediate) {
1614
- node.state = { ok: false };
1615
- const arg = node.arguments[0];
1616
- return [new InvalidArgumentMessage(arg.start, arg.end - arg.start, id)];
2179
+ })();
2180
+ if (inject) {
2181
+ const arg = node.arguments.at(-1);
2182
+ const modName = arg.expansion;
2183
+ const mod2 = (isInline ? cxt.config.inlineModifiers : cxt.config.blockModifiers).get(modName);
2184
+ if (!mod2) {
2185
+ node.state = { ok: false };
2186
+ return [new UnknownModifierMessage(arg.location, modName)];
2187
+ }
2188
+ if (node.state?.ok)
2189
+ node.state.injectMod = mod2;
1617
2190
  }
2191
+ if (msgs) return msgs;
1618
2192
  return [];
1619
2193
  };
1620
2194
  mod.expand = (node, cxt) => {
1621
2195
  if (!node.state) return void 0;
1622
2196
  if (!node.state.ok) return [];
1623
- return cloneNodes(node.state.data[1].slotContent);
2197
+ let cloned = cloneNodes(node.state.data.slotContent);
2198
+ if (inject) {
2199
+ const mod2 = node.state.injectMod;
2200
+ const modNode = {
2201
+ type,
2202
+ mod: mod2,
2203
+ location: node.location,
2204
+ head: node.head,
2205
+ arguments: [],
2206
+ // TODO: enable injecting args
2207
+ content: cloned
2208
+ };
2209
+ return [modNode];
2210
+ } else return cloned;
1624
2211
  };
1625
2212
  mod.beforeProcessExpansion = (node, cxt) => {
1626
2213
  if (!node.state?.ok) return [];
1627
2214
  const store = cxt.get(builtins);
1628
- debug.trace("temporarily removed slot data for", node.state.data[1].mod.name);
1629
- const data = isInline ? store.inlineSlotData : store.blockSlotData;
2215
+ debug.trace("temporarily removed slot data for", node.state.data.mod.name);
2216
+ const data = isInline ? store.inlineInstantiationData : store.blockInstantiationData;
1630
2217
  data.splice(node.state.index, 1);
1631
2218
  return [];
1632
2219
  };
1633
2220
  mod.afterProcessExpansion = (node, cxt) => {
1634
2221
  if (!node.state?.ok) return [];
1635
2222
  const store = cxt.get(builtins);
1636
- debug.trace("reinstated slot data for", node.state.data[1].mod.name);
1637
- const data = isInline ? store.inlineSlotData : store.blockSlotData;
2223
+ debug.trace("reinstated slot data for", node.state.data.mod.name);
2224
+ const data = isInline ? store.inlineInstantiationData : store.blockInstantiationData;
1638
2225
  data.splice(node.state.index, 0, node.state.data);
1639
2226
  return [];
1640
2227
  };
1641
2228
  return mod;
1642
2229
  }
1643
- var SlotBlockMod = slotModifier(7 /* BlockModifier */);
1644
- var SlotInlineMod = slotModifier(6 /* InlineModifier */);
2230
+ var SlotBlockMod = slotModifier("slot", 7 /* BlockModifier */, false, false);
2231
+ var SlotInlineMod = slotModifier("slot", 6 /* InlineModifier */, false, false);
2232
+ var PreSlotBlockMod = slotModifier("pre-slot", 7 /* BlockModifier */, true, false);
2233
+ var PreSlotInlineMod = slotModifier("pre-slot", 6 /* InlineModifier */, true, false);
2234
+ var InjectPreSlotBlockMod = slotModifier(
2235
+ "inject-pre-slot",
2236
+ 7 /* BlockModifier */,
2237
+ true,
2238
+ true
2239
+ );
2240
+ var InjectPreSlotInlineMod = slotModifier(
2241
+ "inject-pre-slot",
2242
+ 6 /* InlineModifier */,
2243
+ true,
2244
+ true
2245
+ );
1645
2246
 
1646
2247
  // src/builtin/var.ts
1647
2248
  function resolveId(id, cxt) {
1648
2249
  const store = cxt.get(builtins);
2250
+ if (store.inlineSlotDelayedStack.find((x) => x.args.includes(id)) || store.blockSlotDelayedStack.find((x) => x.args.includes(id))) {
2251
+ debug.trace("delaying the yet unknown argument", id);
2252
+ return void 0;
2253
+ }
1649
2254
  let value = void 0;
1650
- for (let i = store.inlineSlotData.length - 1; i >= 0; i--) {
1651
- const [_, data] = store.inlineSlotData[i];
2255
+ for (let i = store.inlineInstantiationData.length - 1; i >= 0; i--) {
2256
+ const data = store.inlineInstantiationData[i];
1652
2257
  if ((value = data.args.get(id)) !== void 0)
1653
2258
  break;
1654
2259
  }
1655
- for (let i = store.blockSlotData.length - 1; i >= 0; i--) {
1656
- const [_, data] = store.blockSlotData[i];
2260
+ for (let i = store.blockInstantiationData.length - 1; i >= 0; i--) {
2261
+ const data = store.blockInstantiationData[i];
1657
2262
  if ((value = data.args.get(id)) !== void 0)
1658
2263
  break;
1659
2264
  }
@@ -1661,53 +2266,62 @@ function resolveId(id, cxt) {
1661
2266
  value = cxt.variables.get(id);
1662
2267
  return value;
1663
2268
  }
1664
- var GetVarInlineMod = new InlineModifierDefinition("$", 2 /* Marker */, {
1665
- // .$:id
1666
- prepareExpand(node, cxt) {
1667
- const check = checkArguments(node, 1);
1668
- if (check) return check;
1669
- const arg = node.arguments[0];
1670
- const id = arg.expansion;
1671
- if (id == "")
1672
- return [new InvalidArgumentMessage(arg.start, arg.end - arg.start)];
1673
- const value = resolveId(id, cxt);
1674
- if (value === void 0)
1675
- return [new UndefinedVariableMessage(arg.start, arg.end - arg.start, id)];
1676
- node.state = { value };
1677
- return [];
1678
- },
1679
- expand(node, cxt) {
1680
- if (!node.state) return [];
1681
- return [{ type: 3 /* Text */, content: node.state.value, start: -1, end: -1 }];
2269
+ var GetVarInlineMod = new InlineModifierDefinition(
2270
+ "$",
2271
+ 2 /* None */,
2272
+ {
2273
+ alwaysTryExpand: true,
2274
+ // .$:id
2275
+ prepareExpand(node, cxt, immediate) {
2276
+ const check = checkArguments(node, 1);
2277
+ if (check)
2278
+ return immediate ? check : [];
2279
+ const arg = node.arguments[0];
2280
+ const id = arg.expansion;
2281
+ if (id == "")
2282
+ return immediate ? [new InvalidArgumentMessage(arg.location)] : [];
2283
+ const value = resolveId(id, cxt);
2284
+ if (value === void 0)
2285
+ return immediate ? [new UndefinedVariableMessage(arg.location, id)] : [];
2286
+ node.state = { value };
2287
+ return [];
2288
+ },
2289
+ expand(node, _, immediate) {
2290
+ if (!node.state) return immediate ? [] : void 0;
2291
+ return [{ type: 3 /* Text */, content: node.state.value, location: node.location }];
2292
+ }
1682
2293
  }
1683
- });
1684
- var PrintInlineMod = new InlineModifierDefinition("print", 2 /* Marker */, {
1685
- // .print:args...
1686
- prepareExpand(node) {
1687
- const check = checkArguments(node);
1688
- if (check) return check;
1689
- node.state = { value: node.arguments.map((x) => x.expansion).join("") };
1690
- return [];
1691
- },
1692
- expand(node) {
1693
- if (!node.state) return [];
1694
- return [{ type: 3 /* Text */, content: node.state.value, start: -1, end: -1 }];
2294
+ );
2295
+ var PrintInlineMod = new InlineModifierDefinition(
2296
+ "print",
2297
+ 2 /* None */,
2298
+ {
2299
+ // .print:args...
2300
+ prepareExpand(node) {
2301
+ const check = checkArguments(node);
2302
+ if (check) return check;
2303
+ node.state = { value: node.arguments.map((x) => x.expansion).join("") };
2304
+ return [];
2305
+ },
2306
+ expand(node) {
2307
+ if (!node.state) return [];
2308
+ return [{ type: 3 /* Text */, content: node.state.value, location: node.location }];
2309
+ }
1695
2310
  }
1696
- });
2311
+ );
1697
2312
  var GetVarInterpolator = new ArgumentInterpolatorDefinition(
1698
2313
  "$(",
1699
2314
  ")",
1700
2315
  {
1701
2316
  alwaysTryExpand: true,
1702
- expand(content, cxt, immediate) {
2317
+ expand(content, cxt) {
1703
2318
  const result = resolveId(content, cxt);
1704
- if (result === void 0) debug.trace("var interp failed:", content);
1705
- else debug.trace(`$(${content}) --> ${result}`);
2319
+ if (result !== void 0) debug.trace(`$(${content}) --> ${result}`);
1706
2320
  return result;
1707
2321
  }
1708
2322
  }
1709
2323
  );
1710
- var VarMod = new SystemModifierDefinition("var", 2 /* Marker */, {
2324
+ var VarMod = new SystemModifierDefinition("var", 2 /* None */, {
1711
2325
  // .var id:value
1712
2326
  prepareExpand(node, cxt) {
1713
2327
  const check = checkArguments(node, 2);
@@ -1715,7 +2329,7 @@ var VarMod = new SystemModifierDefinition("var", 2 /* Marker */, {
1715
2329
  const arg = node.arguments[0];
1716
2330
  const id = arg.expansion;
1717
2331
  if (id == "")
1718
- return [new InvalidArgumentMessage(arg.start, arg.end - arg.start)];
2332
+ return [new InvalidArgumentMessage(arg.location)];
1719
2333
  node.state = {
1720
2334
  id,
1721
2335
  value: node.arguments[1].expansion
@@ -1732,13 +2346,677 @@ var VarMod = new SystemModifierDefinition("var", 2 /* Marker */, {
1732
2346
  });
1733
2347
 
1734
2348
  // src/builtin/builtin.ts
1735
- var basic = new Configuration();
1736
- basic.initializers = [initParseContext];
1737
- basic.systemModifiers.add(DefineBlockMod, DefineInlineMod, VarMod, PushNotationMod, PopNotationMod);
1738
- basic.blockModifiers.add(SlotBlockMod);
1739
- basic.inlineModifiers.add(SlotInlineMod, GetVarInlineMod, PrintInlineMod);
1740
- basic.argumentInterpolators.add(GetVarInterpolator);
1741
- var BuiltinConfiguration = Object.freeze(basic);
2349
+ var builtin = new Configuration();
2350
+ builtin.initializers = [initParseContext];
2351
+ builtin.systemModifiers.add(
2352
+ DefineBlockMod,
2353
+ DefineInlineMod,
2354
+ DefineBlockShorthandMod,
2355
+ DefineInlineShorthandMod,
2356
+ VarMod,
2357
+ UseSystemMod
2358
+ );
2359
+ builtin.blockModifiers.add(
2360
+ SlotBlockMod,
2361
+ PreSlotBlockMod,
2362
+ InjectPreSlotBlockMod,
2363
+ ModuleMod,
2364
+ UseBlockMod
2365
+ );
2366
+ builtin.inlineModifiers.add(
2367
+ SlotInlineMod,
2368
+ PreSlotInlineMod,
2369
+ InjectPreSlotInlineMod,
2370
+ GetVarInlineMod,
2371
+ PrintInlineMod
2372
+ );
2373
+ builtin.argumentInterpolators.add(GetVarInterpolator);
2374
+ var BuiltinConfiguration = Object.freeze(builtin);
2375
+
2376
+ // src/default/bullets.ts
2377
+ var bulletItemBlock = new BlockModifierDefinition(
2378
+ "bullet-item",
2379
+ 0 /* Normal */,
2380
+ { roleHint: void 0 }
2381
+ );
2382
+ var orderedListItemBlock = new BlockModifierDefinition(
2383
+ "ordered-item",
2384
+ 0 /* Normal */,
2385
+ {
2386
+ roleHint: void 0,
2387
+ prepareExpand(node) {
2388
+ let msgs = checkArguments(node, 0, 1);
2389
+ if (msgs) return msgs;
2390
+ let arg = node.arguments[0];
2391
+ let num = Number.parseInt(arg.expansion);
2392
+ if (isNaN(num)) return [
2393
+ new InvalidArgumentMessage(arg.location, "should be a number")
2394
+ ];
2395
+ node.state = num;
2396
+ return [];
2397
+ }
2398
+ }
2399
+ );
2400
+ var subItemBlock = new BlockModifierDefinition(
2401
+ "subitem",
2402
+ 0 /* Normal */,
2403
+ { roleHint: void 0 }
2404
+ );
2405
+ var BulletBlocks = [bulletItemBlock, orderedListItemBlock, subItemBlock];
2406
+ var BulletBlockRenderersHTML = [
2407
+ [bulletItemBlock, (node, cxt) => {
2408
+ return `<li>${cxt.state.render(node.content, cxt)}</li>`;
2409
+ }],
2410
+ [subItemBlock, (node, cxt) => {
2411
+ return `<div class='subitem'>${cxt.state.render(node.content, cxt)}</div>`;
2412
+ }],
2413
+ [orderedListItemBlock, (node, cxt) => {
2414
+ if (node.state === void 0)
2415
+ return cxt.state.invalidBlock(node, "bad format");
2416
+ return `<li value='${node.state}'>${cxt.state.render(node.content, cxt)}</li>`;
2417
+ }]
2418
+ ];
2419
+
2420
+ // src/default/headings.ts
2421
+ var headings = Symbol();
2422
+ function initHeadings(cxt) {
2423
+ cxt.init(headings, {
2424
+ path: []
2425
+ });
2426
+ }
2427
+ function setHeading(cxt, data) {
2428
+ const path = cxt.get(headings).path;
2429
+ while (path.length > 0 && path.at(-1).level >= data.level)
2430
+ path.pop();
2431
+ path.push(data);
2432
+ return [];
2433
+ }
2434
+ function currentHeadingLevel(cxt) {
2435
+ return cxt.get(headings).path.at(-1)?.level;
2436
+ }
2437
+ function currentExplicitHeadingLevel(cxt) {
2438
+ return cxt.get(headings).path.findLast((x) => !x.implicit)?.level;
2439
+ }
2440
+ var headingBlock = new BlockModifierDefinition(
2441
+ "heading",
2442
+ 0 /* Normal */,
2443
+ {
2444
+ delayContentExpansion: true,
2445
+ roleHint: "heading",
2446
+ beforeParseContent(node, cxt) {
2447
+ let msgs = checkArguments(node, 0, 1);
2448
+ if (msgs) return msgs;
2449
+ msgs = onlyPermitSingleBlock(node);
2450
+ if (msgs) return msgs;
2451
+ msgs = onlyPermitSimpleParagraphs(node);
2452
+ if (msgs) return msgs;
2453
+ node.state = { name: void 0, level: currentHeadingLevel(cxt) ?? 1 };
2454
+ if (node.arguments.length == 1) {
2455
+ const arg = node.arguments[0];
2456
+ const level = Number.parseInt(arg.expansion);
2457
+ if (isNaN(level) || level < 1 || level > 6)
2458
+ msgs = [new InvalidArgumentMessage(
2459
+ arg.location,
2460
+ "should be a number between 1 and 6"
2461
+ )];
2462
+ else node.state.level = level;
2463
+ }
2464
+ setHeading(cxt, node.state);
2465
+ return msgs ?? [];
2466
+ }
2467
+ }
2468
+ );
2469
+ var implicitHeadingBlock = new BlockModifierDefinition(
2470
+ "implicit-heading",
2471
+ 2 /* None */,
2472
+ {
2473
+ roleHint: "heading",
2474
+ beforeParseContent(node, cxt) {
2475
+ let msgs = checkArguments(node, 0, 1);
2476
+ if (msgs) return msgs;
2477
+ node.state = {
2478
+ name: void 0,
2479
+ implicit: true,
2480
+ level: (currentExplicitHeadingLevel(cxt) ?? 0) + 1
2481
+ };
2482
+ if (node.arguments.length == 1) {
2483
+ const arg = node.arguments[0];
2484
+ const level = Number.parseInt(arg.expansion);
2485
+ if (isNaN(level) || level < 1 || level > 6)
2486
+ msgs = [new InvalidArgumentMessage(
2487
+ arg.location,
2488
+ "should be a number between 1 and 6"
2489
+ )];
2490
+ else node.state.level = level;
2491
+ }
2492
+ setHeading(cxt, node.state);
2493
+ return msgs ?? [];
2494
+ }
2495
+ }
2496
+ );
2497
+ var numberedHeadingBlock = new BlockModifierDefinition(
2498
+ "numbered-heading",
2499
+ 0 /* Normal */,
2500
+ {
2501
+ delayContentExpansion: true,
2502
+ roleHint: "heading",
2503
+ beforeParseContent(node, cxt) {
2504
+ let msgs = checkArguments(node, 1);
2505
+ if (msgs) return msgs;
2506
+ msgs = onlyPermitSingleBlock(node);
2507
+ if (msgs) return msgs;
2508
+ msgs = onlyPermitSimpleParagraphs(node);
2509
+ if (msgs) return msgs;
2510
+ node.state = { name: void 0, level: currentHeadingLevel(cxt) ?? 1 };
2511
+ const arg = node.arguments[0];
2512
+ const split = arg.expansion.trim().split(".").filter((x) => x.length > 0);
2513
+ if (split.length == 0 || split.length > 6)
2514
+ msgs = [new InvalidArgumentMessage(
2515
+ arg.location,
2516
+ "should be a number between 1 and 6"
2517
+ )];
2518
+ else node.state = { name: split.join("."), level: split.length };
2519
+ setHeading(cxt, node.state);
2520
+ return msgs ?? [];
2521
+ }
2522
+ }
2523
+ );
2524
+ var HeadingBlocks = [headingBlock, implicitHeadingBlock, numberedHeadingBlock];
2525
+ var HeadingBlockRenderersHTML = [
2526
+ [headingBlock, (node, cxt) => {
2527
+ if (node.state !== void 0) {
2528
+ let tag = "h" + node.state.level;
2529
+ let para = node.content[0];
2530
+ return `<${tag}>${cxt.state.render(para.content, cxt)}</${tag}>`;
2531
+ }
2532
+ return cxt.state.invalidBlock(node, "Bad format");
2533
+ }],
2534
+ [implicitHeadingBlock, (node, cxt) => {
2535
+ if (node.state !== void 0) {
2536
+ let tag = "h" + node.state.level;
2537
+ return `<${tag} class='implicit'></${tag}>`;
2538
+ }
2539
+ return cxt.state.invalidBlock(node, "Bad format");
2540
+ }],
2541
+ [numberedHeadingBlock, (node, cxt) => {
2542
+ if (node.state !== void 0) {
2543
+ let tag = "h" + node.state.level;
2544
+ let para = node.content[0];
2545
+ return `<${tag}><span class='heading-number'>${node.state.name}</span>${cxt.state.render(para.content, cxt)}</${tag}>`;
2546
+ }
2547
+ return cxt.state.invalidBlock(node, "Bad format");
2548
+ }]
2549
+ ];
2550
+
2551
+ // src/default/notes.ts
2552
+ var notes = Symbol();
2553
+ function initNotes(cxt) {
2554
+ cxt.init(notes, {
2555
+ systems: /* @__PURE__ */ new Map(),
2556
+ definitions: []
2557
+ });
2558
+ }
2559
+ var noteMarkerInline = new InlineModifierDefinition(
2560
+ "note",
2561
+ 2 /* None */,
2562
+ {
2563
+ roleHint: "link",
2564
+ prepareExpand(node) {
2565
+ let msgs = checkArguments(node, 1);
2566
+ if (msgs) return msgs;
2567
+ node.state = node.arguments[0].expansion;
2568
+ return [];
2569
+ }
2570
+ }
2571
+ );
2572
+ var noteInline = new InlineModifierDefinition(
2573
+ "note-inline",
2574
+ 0 /* Normal */,
2575
+ {
2576
+ roleHint: "quote",
2577
+ prepareExpand(node) {
2578
+ let msgs = checkArguments(node, 0, 1);
2579
+ if (msgs) return msgs;
2580
+ node.state = node.arguments.at(0)?.expansion ?? "";
2581
+ return [];
2582
+ },
2583
+ afterProcessExpansion(node, cxt) {
2584
+ if (node.state !== void 0) {
2585
+ cxt.get(notes).definitions.push({
2586
+ system: "",
2587
+ name: node.state,
2588
+ location: node.location,
2589
+ content: [{
2590
+ type: 1 /* Paragraph */,
2591
+ location: {
2592
+ source: node.location.source,
2593
+ start: node.head.end,
2594
+ end: node.location.actualEnd ?? node.location.end
2595
+ },
2596
+ content: node.content
2597
+ }]
2598
+ });
2599
+ }
2600
+ return [];
2601
+ }
2602
+ }
2603
+ );
2604
+ var noteBlock = new BlockModifierDefinition(
2605
+ "note",
2606
+ 0 /* Normal */,
2607
+ {
2608
+ roleHint: "quote",
2609
+ prepareExpand(node) {
2610
+ let msgs = checkArguments(node, 1);
2611
+ if (msgs) return msgs;
2612
+ node.state = node.arguments[0].expansion;
2613
+ return [];
2614
+ },
2615
+ afterProcessExpansion(node, cxt) {
2616
+ if (node.state !== void 0) {
2617
+ let content = stripNode(...node.content);
2618
+ debug.trace(`add note: system=<${""}> name=${node.state} @${node.location.start}`);
2619
+ debug.trace(`-->
2620
+ `, debugPrint.node(...content));
2621
+ cxt.get(notes).definitions.push({
2622
+ system: "",
2623
+ name: node.state,
2624
+ location: node.location,
2625
+ content
2626
+ });
2627
+ }
2628
+ node.expansion = [];
2629
+ return [];
2630
+ }
2631
+ }
2632
+ );
2633
+ var NoteBlocks = [noteBlock];
2634
+ var NoteInlines = [noteInline, noteMarkerInline];
2635
+ var NoteInlineRenderersHTML = [
2636
+ [noteMarkerInline, (node, cxt) => {
2637
+ if (node.state === void 0)
2638
+ return cxt.state.invalidInline(node, "bad format");
2639
+ const defs = cxt.parseContext.get(notes).definitions;
2640
+ const note = defs.findIndex((x) => (
2641
+ /*x.position >= node.start &&*/
2642
+ x.name == node.state
2643
+ ));
2644
+ if (note < 0)
2645
+ return `<sup class='note invalid'>Not found: ${node.state}</sup>`;
2646
+ return `<sup class='note' id='notemarker-id-${note}'><a href='#note-id-${note}'>${node.state}</a></sup>`;
2647
+ }]
2648
+ ];
2649
+ var NotesFooterPlugin = (cxt) => {
2650
+ let defs = cxt.parseContext.get(notes).definitions;
2651
+ if (defs.length == 0) return void 0;
2652
+ return `<hr/>
2653
+ <section class='notes'>
2654
+ ${defs.map((x, i) => `<section class='note' id='note-id-${i}'>
2655
+ <div class='note-name'><p><a href='#notemarker-id-${i}'>${x.name}</a></p></div>
2656
+ <div class='note-content'>${cxt.state.render(x.content, cxt)}</div></section>`).join("\n")}
2657
+ </section>`;
2658
+ };
2659
+
2660
+ // src/default/code.ts
2661
+ var CodeBlock = new BlockModifierDefinition(
2662
+ "code",
2663
+ 1 /* Preformatted */,
2664
+ { roleHint: "code" }
2665
+ );
2666
+ var CodeInline = new InlineModifierDefinition(
2667
+ "code",
2668
+ 1 /* Preformatted */,
2669
+ { roleHint: "code" }
2670
+ );
2671
+ var CodeBlockRendererHTML = [CodeBlock, (node, cxt) => {
2672
+ return `<pre><code>${cxt.state.render(node.content, cxt)}</code></pre>`;
2673
+ }];
2674
+ var CodeInlineRendererHTML = [CodeInline, (node, cxt) => {
2675
+ return `<span><code>${cxt.state.render(node.content, cxt)}</code></span>`;
2676
+ }];
2677
+
2678
+ // src/default/quotes.ts
2679
+ var quoteBlock = new BlockModifierDefinition(
2680
+ "quote",
2681
+ 0 /* Normal */,
2682
+ { roleHint: "quote" }
2683
+ );
2684
+ var epitaphBlock = new BlockModifierDefinition(
2685
+ "epitaph",
2686
+ 0 /* Normal */,
2687
+ { roleHint: "quote" }
2688
+ );
2689
+ var attributionBlock = new BlockModifierDefinition(
2690
+ "by",
2691
+ 0 /* Normal */,
2692
+ {
2693
+ roleHint: "quote",
2694
+ prepareExpand(node) {
2695
+ let msgs = onlyPermitSingleBlock(node);
2696
+ if (msgs) return msgs;
2697
+ msgs = onlyPermitSimpleParagraphs(node);
2698
+ if (msgs) return msgs;
2699
+ node.state = true;
2700
+ return [];
2701
+ }
2702
+ }
2703
+ );
2704
+ var QuoteBlocks = [quoteBlock, epitaphBlock, attributionBlock];
2705
+ var QuoteBlockRenderersHTML = [
2706
+ [quoteBlock, (node, cxt) => {
2707
+ return `<blockquote>${cxt.state.render(node.content, cxt)}</blockquote>`;
2708
+ }],
2709
+ [epitaphBlock, (node, cxt) => {
2710
+ return `<blockquote class='epitaph'>${cxt.state.render(node.content, cxt)}</blockquote>`;
2711
+ }],
2712
+ [attributionBlock, (node, cxt) => {
2713
+ if (!node.state)
2714
+ return cxt.state.invalidBlock(node, "bad format");
2715
+ let para = node.content[0];
2716
+ return `<p class='attribution'>${cxt.state.render(para.content, cxt)}</p>`;
2717
+ }]
2718
+ ];
2719
+
2720
+ // src/default/inline-styles.ts
2721
+ var emphasisInline = new InlineModifierDefinition(
2722
+ "emphasis",
2723
+ 0 /* Normal */,
2724
+ { roleHint: "emphasis" }
2725
+ );
2726
+ var keywordInline = new InlineModifierDefinition(
2727
+ "keyword",
2728
+ 0 /* Normal */,
2729
+ { roleHint: "keyword" }
2730
+ );
2731
+ var highlightInline = new InlineModifierDefinition(
2732
+ "highlight",
2733
+ 0 /* Normal */,
2734
+ { roleHint: "highlight" }
2735
+ );
2736
+ var commentaryInline = new InlineModifierDefinition(
2737
+ "commentary",
2738
+ 0 /* Normal */,
2739
+ { roleHint: "commentary" }
2740
+ );
2741
+ var InlineStyles = [emphasisInline, keywordInline, highlightInline, commentaryInline];
2742
+ var InlineStyleRenderersHTML = [
2743
+ [emphasisInline, (node, cxt) => {
2744
+ return `<em>${cxt.state.render(node.content, cxt)}</em>`;
2745
+ }],
2746
+ [keywordInline, (node, cxt) => {
2747
+ return `<b>${cxt.state.render(node.content, cxt)}</b>`;
2748
+ }],
2749
+ [highlightInline, (node, cxt) => {
2750
+ return `<mark>${cxt.state.render(node.content, cxt)}</mark>`;
2751
+ }],
2752
+ [commentaryInline, (node, cxt) => {
2753
+ return `<span class='commentary'>${cxt.state.render(node.content, cxt)}</span>`;
2754
+ }]
2755
+ ];
2756
+
2757
+ // src/default/misc.ts
2758
+ var rubyInline = new InlineModifierDefinition(
2759
+ "ruby",
2760
+ 0 /* Normal */,
2761
+ {
2762
+ roleHint: void 0,
2763
+ prepareExpand(node) {
2764
+ let msgs = checkArguments(node, 1);
2765
+ if (msgs) return msgs;
2766
+ node.state = node.arguments[0].expansion;
2767
+ return [];
2768
+ }
2769
+ }
2770
+ );
2771
+ var linkInline = new InlineModifierDefinition(
2772
+ "link",
2773
+ 0 /* Normal */,
2774
+ {
2775
+ roleHint: "link",
2776
+ prepareExpand(node) {
2777
+ let msgs = checkArguments(node, 1);
2778
+ if (msgs) return msgs;
2779
+ node.state = node.arguments[0].expansion;
2780
+ return [];
2781
+ }
2782
+ }
2783
+ );
2784
+ var styleBlock = new BlockModifierDefinition(
2785
+ "style",
2786
+ 0 /* Normal */,
2787
+ {
2788
+ prepareExpand(node) {
2789
+ let msgs = checkArguments(node, 1);
2790
+ if (msgs) return msgs;
2791
+ node.state = node.arguments[0].expansion;
2792
+ return [];
2793
+ }
2794
+ }
2795
+ );
2796
+ var breakBlock = new BlockModifierDefinition(
2797
+ "break",
2798
+ 2 /* None */
2799
+ );
2800
+ var linkBlock = new BlockModifierDefinition(
2801
+ "link",
2802
+ 0 /* Normal */,
2803
+ {
2804
+ roleHint: "link",
2805
+ prepareExpand(node) {
2806
+ let msgs = checkArguments(node, 1);
2807
+ if (msgs) return msgs;
2808
+ node.state = node.arguments[0].expansion;
2809
+ return [];
2810
+ }
2811
+ }
2812
+ );
2813
+ var imageBlock = new BlockModifierDefinition(
2814
+ "image",
2815
+ 0 /* Normal */,
2816
+ {
2817
+ roleHint: "link",
2818
+ prepareExpand(node) {
2819
+ let msgs = checkArguments(node, 1, 2);
2820
+ if (msgs) return msgs;
2821
+ msgs = onlyPermitSingleBlock(node);
2822
+ if (msgs) return msgs;
2823
+ msgs = onlyPermitSimpleParagraphs(node);
2824
+ if (msgs) return msgs;
2825
+ node.state = node.arguments.map((x) => x.expansion).join(":");
2826
+ return [];
2827
+ }
2828
+ }
2829
+ );
2830
+ var MiscInlines = [rubyInline, linkInline];
2831
+ var MiscBlocks = [styleBlock, breakBlock, linkBlock, imageBlock];
2832
+ var MiscInlineRenderersHTML = [
2833
+ [rubyInline, (node, cxt) => {
2834
+ if (node.state === void 0)
2835
+ return cxt.state.invalidInline(node, "bad format");
2836
+ return `<ruby>${cxt.state.render(node.content, cxt)}<rt>${node.state}</rt></ruby>`;
2837
+ }],
2838
+ [linkInline, (node, cxt) => {
2839
+ if (node.state === void 0)
2840
+ return cxt.state.invalidInline(node, "bad format");
2841
+ return `<a href="${encodeURI(node.state)}">${cxt.state.render(node.content, cxt)}</a>`;
2842
+ }]
2843
+ ];
2844
+ var MiscBlockRenderersHTML = [
2845
+ [styleBlock, (node, cxt) => {
2846
+ if (node.state === void 0)
2847
+ return cxt.state.invalidBlock(node, "bad format");
2848
+ return `<div class="${node.state}" style="display:contents">${cxt.state.render(node.content, cxt)}</div>`;
2849
+ }],
2850
+ [breakBlock, () => {
2851
+ return `<hr>`;
2852
+ }],
2853
+ [linkBlock, (node, cxt) => {
2854
+ if (node.state === void 0)
2855
+ return cxt.state.invalidBlock(node, "bad format");
2856
+ return `<a href="${encodeURI(node.state)}">${cxt.state.render(node.content, cxt)}</a>`;
2857
+ }],
2858
+ [imageBlock, (node, cxt) => {
2859
+ let transformed;
2860
+ if (node.state === void 0)
2861
+ return cxt.state.invalidBlock(node, "bad format");
2862
+ try {
2863
+ transformed = cxt.config.options.transformAsset(node.state);
2864
+ } catch {
2865
+ return cxt.state.invalidBlock(node, "unable to transform asset");
2866
+ }
2867
+ const img = transformed ? `<img src="${transformed}" data-original-src="${node.state}"/>` : `<img src="${node.state}"/>`;
2868
+ const para = node.content.length == 0 ? "" : "\n<figcaption>" + cxt.state.render(node.content[0].content, cxt) + "</figcaption>";
2869
+ return `<figure>${img}${para}</figure>`;
2870
+ }]
2871
+ ];
2872
+
2873
+ // src/default/vars.ts
2874
+ function createWrapper(name, varname) {
2875
+ varname = varname ?? name.toUpperCase();
2876
+ return new SystemModifierDefinition(name, 0 /* Normal */, {
2877
+ delayContentExpansion: true,
2878
+ afterProcessExpansion(node, cxt) {
2879
+ let msgs = checkArguments(node, 0);
2880
+ if (msgs) return msgs;
2881
+ const result = onlyPermitPlaintextParagraph(node);
2882
+ if (typeof result !== "string") return result;
2883
+ const previous = cxt.variables.get(varname);
2884
+ if (previous)
2885
+ msgs = [new OverwriteSpecialVariableMessage(node.head, varname, previous)];
2886
+ cxt.variables.set(varname, result);
2887
+ return msgs ?? [];
2888
+ }
2889
+ });
2890
+ }
2891
+ var VarWrappers = [
2892
+ createWrapper("title"),
2893
+ createWrapper("subtitle"),
2894
+ createWrapper("author"),
2895
+ createWrapper("translator"),
2896
+ createWrapper("proofreader"),
2897
+ createWrapper("typeset-by"),
2898
+ createWrapper("cover-by"),
2899
+ createWrapper("cover-img"),
2900
+ createWrapper("orig-title"),
2901
+ createWrapper("orig-link"),
2902
+ createWrapper("theme-color")
2903
+ ];
2904
+
2905
+ // src/default/default.ts
2906
+ var config = Configuration.from(BuiltinConfiguration);
2907
+ config.initializers.push(initNotes, initHeadings);
2908
+ config.blockModifiers.add(
2909
+ ...HeadingBlocks,
2910
+ ...BulletBlocks,
2911
+ CodeBlock,
2912
+ ...QuoteBlocks,
2913
+ ...MiscBlocks,
2914
+ ...NoteBlocks
2915
+ );
2916
+ config.inlineModifiers.add(
2917
+ CodeInline,
2918
+ ...InlineStyles,
2919
+ ...MiscInlines,
2920
+ ...NoteInlines
2921
+ );
2922
+ config.systemModifiers.add(
2923
+ ...VarWrappers
2924
+ );
2925
+ var DefaultConfiguration = Object.freeze(config);
2926
+
2927
+ // src/default/html-renderer.ts
2928
+ var HTMLRenderState = class {
2929
+ title = "";
2930
+ stylesheet = "";
2931
+ // FIXME: very unsafe!
2932
+ cssVariables = /* @__PURE__ */ new Map();
2933
+ // https://stackoverflow.com/questions/7381974
2934
+ escape(content) {
2935
+ return content.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("\n", "<br/>");
2936
+ }
2937
+ invalidBlock(node, msg) {
2938
+ let name = NodeType[node.type];
2939
+ if (node.type === 7 /* BlockModifier */)
2940
+ name += ` (${node.mod.name})`;
2941
+ return `<details class='invalid'><summary>Invalid ${this.escape(name)}</summary><i>${this.escape(msg)}</i></details>`;
2942
+ }
2943
+ invalidInline(node, msg) {
2944
+ let name = NodeType[node.type];
2945
+ if (node.type === 6 /* InlineModifier */)
2946
+ name += ` (${node.mod.name})`;
2947
+ return `<span class='invalid'>Invalid ${this.escape(name)} \u2013 <i>${this.escape(msg)}</i></span>`;
2948
+ }
2949
+ render(elems, cxt) {
2950
+ return elems.map((x) => cxt.renderEntity(x)).filter((x) => x !== void 0).join("");
2951
+ }
2952
+ };
2953
+ var htmlConfig = new RenderConfiguration(
2954
+ {
2955
+ headPlugins: [],
2956
+ headerPlugins: [],
2957
+ footerPlugins: [NotesFooterPlugin],
2958
+ transformAsset: (x) => void 0
2959
+ // postprocessPlugins: [],
2960
+ },
2961
+ (results, cxt) => {
2962
+ let styles = cxt.state.stylesheet.replaceAll(
2963
+ /var\(--(.*?)\)/g,
2964
+ (m, c) => cxt.state.cssVariables.get(c) ?? m
2965
+ );
2966
+ return `
2967
+ <!DOCTYPE html>
2968
+ <html>
2969
+ <head>
2970
+ <meta charset="UTF-8">
2971
+ ${cxt.config.options.headPlugins.map((x) => x(cxt)).filter((x) => x !== void 0).join("\n")}
2972
+ <title>${cxt.state.escape(cxt.state.title)}</title>
2973
+ <style>${styles}</style>
2974
+ </head>
2975
+ <body>
2976
+ <section class="article-container">
2977
+ <section class="article-body">
2978
+ ${cxt.config.options.headerPlugins.map((x) => x(cxt)).filter((x) => x !== void 0).join("\n")}
2979
+ ${results.join("\n")}
2980
+ ${cxt.config.options.footerPlugins.map((x) => x(cxt)).filter((x) => x !== void 0).join("\n")}
2981
+ </section>
2982
+ </section>
2983
+ </body>
2984
+ </html>`;
2985
+ }
2986
+ );
2987
+ htmlConfig.paragraphRenderer = (node, cxt) => `<p>${node.content.map((x) => cxt.renderEntity(x)).filter((x) => x !== void 0).join("")}</p>`;
2988
+ htmlConfig.textRenderer = (node, cxt) => {
2989
+ switch (node.type) {
2990
+ case 2 /* Preformatted */:
2991
+ return cxt.state.escape(node.content.text);
2992
+ case 3 /* Text */:
2993
+ case 4 /* Escaped */:
2994
+ return cxt.state.escape(node.content);
2995
+ default:
2996
+ return debug.never(node);
2997
+ }
2998
+ };
2999
+ htmlConfig.undefinedBlockRenderer = (node, cxt) => {
3000
+ return cxt.state.invalidBlock(node, `No renderer defined for ${node.mod.name}`);
3001
+ };
3002
+ htmlConfig.undefinedInlineRenderer = (node, cxt) => {
3003
+ return cxt.state.invalidInline(node, `No renderer defined for ${node.mod.name}`);
3004
+ };
3005
+ htmlConfig.addBlockRenderer(
3006
+ ...HeadingBlockRenderersHTML,
3007
+ ...BulletBlockRenderersHTML,
3008
+ CodeBlockRendererHTML,
3009
+ ...QuoteBlockRenderersHTML,
3010
+ ...MiscBlockRenderersHTML
3011
+ // TODO: notes
3012
+ );
3013
+ htmlConfig.addInlineRenderer(
3014
+ CodeInlineRendererHTML,
3015
+ ...InlineStyleRenderersHTML,
3016
+ ...MiscInlineRenderersHTML,
3017
+ ...NoteInlineRenderersHTML
3018
+ );
3019
+ var HTMLRenderConfiguration = htmlConfig;
1742
3020
 
1743
3021
  // src/index.ts
1744
3022
  function setDebugLevel(level) {
@@ -1750,14 +3028,20 @@ export {
1750
3028
  BuiltinConfiguration,
1751
3029
  Configuration,
1752
3030
  DebugLevel,
3031
+ DefaultConfiguration,
1753
3032
  Document,
3033
+ HTMLRenderConfiguration,
3034
+ HTMLRenderState,
1754
3035
  InlineModifierDefinition,
1755
3036
  MessageSeverity,
1756
- ModifierFlags,
3037
+ ModifierSlotType,
1757
3038
  NodeType,
1758
3039
  ParseContext,
3040
+ RenderConfiguration,
3041
+ RenderContext,
1759
3042
  SimpleScanner,
1760
3043
  SystemModifierDefinition,
3044
+ debugPrint,
1761
3045
  messages_exports as messages,
1762
3046
  parse,
1763
3047
  setDebugLevel