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