@willwang-io/react-djot 0.1.4 → 0.1.6

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
@@ -1,30 +1,100 @@
1
1
  import { parse } from '@djot/djot';
2
- import { Fragment, createElement } from 'react';
2
+ import { Fragment, createElement, isValidElement, cloneElement } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
5
5
  // src/Djot.tsx
6
6
  function isParentNode(node) {
7
7
  return Array.isArray(node.children);
8
8
  }
9
- function isSoftBreakNode(node) {
10
- return node.tag === "soft_break" || node.tag === "softbreak";
9
+ function collectFootnoteReferences(nodes, indexByLabel, order) {
10
+ for (const node of nodes) {
11
+ if (node.tag === "footnote_reference") {
12
+ const label = node.text;
13
+ if (!indexByLabel.has(label)) {
14
+ const index = order.length + 1;
15
+ indexByLabel.set(label, index);
16
+ order.push(label);
17
+ }
18
+ continue;
19
+ }
20
+ if (isParentNode(node)) {
21
+ collectFootnoteReferences(node.children, indexByLabel, order);
22
+ }
23
+ }
11
24
  }
12
- function isHardBreakNode(node) {
13
- return node.tag === "hard_break" || node.tag === "hardbreak";
25
+ function createFootnoteState(node) {
26
+ const indexByLabel = /* @__PURE__ */ new Map();
27
+ const order = [];
28
+ collectFootnoteReferences(node.children, indexByLabel, order);
29
+ return {
30
+ autoReferencesByLabel: node.autoReferences ?? {},
31
+ firstRefIdByLabel: /* @__PURE__ */ new Map(),
32
+ indexByLabel,
33
+ order,
34
+ referencesByLabel: node.references ?? {},
35
+ refCountByLabel: /* @__PURE__ */ new Map()
36
+ };
14
37
  }
15
- function pickComponent(components, primary, alias) {
16
- if (!components) {
38
+ function resolveReferenceNode(node, footnoteState) {
39
+ if (!node.reference || !footnoteState) {
17
40
  return void 0;
18
41
  }
19
- return components[primary] ?? (alias ? components[alias] : void 0);
42
+ return footnoteState.referencesByLabel[node.reference] ?? footnoteState.autoReferencesByLabel[node.reference];
20
43
  }
21
- function renderChildren(children, components) {
22
- return children.map(
23
- (child, index) => renderNode(child, {
24
- components,
25
- key: index
26
- })
27
- );
44
+ function resolveReferenceDestination(node, footnoteState) {
45
+ if (node.destination) {
46
+ return node.destination;
47
+ }
48
+ return resolveReferenceNode(node, footnoteState)?.destination;
49
+ }
50
+ function ensureFootnoteIndex(label, footnoteState) {
51
+ const existing = footnoteState.indexByLabel.get(label);
52
+ if (existing) {
53
+ return existing;
54
+ }
55
+ const index = footnoteState.order.length + 1;
56
+ footnoteState.indexByLabel.set(label, index);
57
+ footnoteState.order.push(label);
58
+ return index;
59
+ }
60
+ function appendBacklink(nodes, backlink) {
61
+ if (nodes.length === 0) {
62
+ return [backlink];
63
+ }
64
+ const next = nodes.slice();
65
+ const lastIndex = next.length - 1;
66
+ const last = next[lastIndex];
67
+ if (isValidElement(last)) {
68
+ next[lastIndex] = cloneElement(last, void 0, last.props.children, backlink);
69
+ return next;
70
+ }
71
+ next.push(backlink);
72
+ return next;
73
+ }
74
+
75
+ // src/renderNode.utils.ts
76
+ function isParentNode2(node) {
77
+ return Array.isArray(node.children);
78
+ }
79
+ function toSmartPunctuation(type, fallback) {
80
+ switch (type) {
81
+ case "left_double_quote":
82
+ return "\u201C";
83
+ case "right_double_quote":
84
+ return "\u201D";
85
+ case "left_single_quote":
86
+ return "\u2018";
87
+ case "right_single_quote":
88
+ return "\u2019";
89
+ case "em_dash":
90
+ return "\u2014";
91
+ case "en_dash":
92
+ return "\u2013";
93
+ case "ellipses":
94
+ return "\u2026";
95
+ default:
96
+ return fallback;
97
+ }
28
98
  }
29
99
  function toAltText(nodes) {
30
100
  let output = "";
@@ -33,8 +103,27 @@ function toAltText(nodes) {
33
103
  case "str":
34
104
  case "code":
35
105
  case "verbatim":
106
+ case "inline_math":
107
+ case "display_math":
36
108
  case "code_block":
37
- output += node.text;
109
+ case "raw_block":
110
+ case "raw_inline":
111
+ case "symb":
112
+ case "url":
113
+ case "email":
114
+ output += node.tag === "symb" ? `:${node.alias}:` : node.text;
115
+ break;
116
+ case "non_breaking_space":
117
+ output += "\xA0";
118
+ break;
119
+ case "smart_punctuation":
120
+ output += toSmartPunctuation(node.type, node.text);
121
+ break;
122
+ case "double_quoted":
123
+ output += `\u201C${toAltText(node.children)}\u201D`;
124
+ break;
125
+ case "single_quoted":
126
+ output += `\u2018${toAltText(node.children)}\u2019`;
38
127
  break;
39
128
  case "soft_break":
40
129
  case "softbreak":
@@ -45,7 +134,7 @@ function toAltText(nodes) {
45
134
  output += "\n";
46
135
  break;
47
136
  default:
48
- if (isParentNode(node)) {
137
+ if (isParentNode2(node)) {
49
138
  output += toAltText(node.children);
50
139
  }
51
140
  break;
@@ -71,6 +160,354 @@ function withKey(props, key) {
71
160
  key
72
161
  };
73
162
  }
163
+ function toDomPropsFromAttributes(attributes) {
164
+ if (!attributes) {
165
+ return {};
166
+ }
167
+ const props = {};
168
+ for (const [name, value] of Object.entries(attributes)) {
169
+ if (name === "class") {
170
+ props.className = value;
171
+ } else {
172
+ props[name] = value;
173
+ }
174
+ }
175
+ return props;
176
+ }
177
+ function toDomPropsFromNode(node) {
178
+ return {
179
+ ...toDomPropsFromAttributes(node.autoAttributes),
180
+ ...toDomPropsFromAttributes(node.attributes)
181
+ };
182
+ }
183
+ function joinClassNames(...values) {
184
+ const classes = values.filter((value) => Boolean(value && value.length > 0));
185
+ return classes.length > 0 ? classes.join(" ") : void 0;
186
+ }
187
+ function toStyleObject(value) {
188
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
189
+ return void 0;
190
+ }
191
+ return value;
192
+ }
193
+ function mergeDomProps(node, extra = {}) {
194
+ const nodeProps = toDomPropsFromNode(node);
195
+ const merged = {
196
+ ...extra,
197
+ ...nodeProps
198
+ };
199
+ const className = joinClassNames(
200
+ typeof extra.className === "string" ? extra.className : void 0,
201
+ typeof nodeProps.className === "string" ? nodeProps.className : void 0
202
+ );
203
+ if (className) {
204
+ merged.className = className;
205
+ }
206
+ const extraStyle = toStyleObject(extra.style);
207
+ const nodeStyle = toStyleObject(nodeProps.style);
208
+ if (extraStyle || nodeStyle) {
209
+ merged.style = {
210
+ ...extraStyle ?? {},
211
+ ...nodeStyle ?? {}
212
+ };
213
+ }
214
+ return merged;
215
+ }
216
+ function textAlignForCell(align) {
217
+ if (align === "left") {
218
+ return "left";
219
+ }
220
+ if (align === "right") {
221
+ return "right";
222
+ }
223
+ if (align === "center") {
224
+ return "center";
225
+ }
226
+ return void 0;
227
+ }
228
+ function toOrderedListType(style) {
229
+ if (!style || /1/.test(style)) {
230
+ return void 0;
231
+ }
232
+ const type = style.replace(/[().]/g, "");
233
+ return type.length > 0 ? type : void 0;
234
+ }
235
+
236
+ // src/renderNode.rawHtml.tsx
237
+ var RAW_HTML_ATTR_PATTERN = /([^\s"'=<>`/]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
238
+ var RAW_HTML_TOKEN_PATTERN = /<!--[\s\S]*?-->|<\/?[A-Za-z][^>]*>|[^<]+|</g;
239
+ var RAW_HTML_BLOCKED_TAGS = /* @__PURE__ */ new Set([
240
+ "base",
241
+ "embed",
242
+ "form",
243
+ "iframe",
244
+ "meta",
245
+ "object",
246
+ "script"
247
+ ]);
248
+ var RAW_HTML_BOOLEAN_ATTRS = /* @__PURE__ */ new Set([
249
+ "allowfullscreen",
250
+ "async",
251
+ "autofocus",
252
+ "autoplay",
253
+ "checked",
254
+ "controls",
255
+ "default",
256
+ "defer",
257
+ "disabled",
258
+ "hidden",
259
+ "loop",
260
+ "multiple",
261
+ "muted",
262
+ "novalidate",
263
+ "open",
264
+ "playsinline",
265
+ "readonly",
266
+ "required",
267
+ "reversed",
268
+ "selected"
269
+ ]);
270
+ var RAW_HTML_UNSAFE_PROTOCOL = /^\s*(?:javascript:|vbscript:|data:)/i;
271
+ var RAW_HTML_URL_ATTRS = /* @__PURE__ */ new Set([
272
+ "action",
273
+ "formaction",
274
+ "href",
275
+ "poster",
276
+ "src",
277
+ "xlink:href"
278
+ ]);
279
+ var RAW_HTML_VOID_TAGS = /* @__PURE__ */ new Set([
280
+ "area",
281
+ "base",
282
+ "br",
283
+ "col",
284
+ "embed",
285
+ "hr",
286
+ "img",
287
+ "input",
288
+ "link",
289
+ "meta",
290
+ "param",
291
+ "source",
292
+ "track",
293
+ "wbr"
294
+ ]);
295
+ function decodeHtmlEntities(value) {
296
+ return value.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (_match, entity) => {
297
+ if (entity.startsWith("#x") || entity.startsWith("#X")) {
298
+ const codePoint = Number.parseInt(entity.slice(2), 16);
299
+ if (!Number.isNaN(codePoint)) {
300
+ return String.fromCodePoint(codePoint);
301
+ }
302
+ return _match;
303
+ }
304
+ if (entity.startsWith("#")) {
305
+ const codePoint = Number.parseInt(entity.slice(1), 10);
306
+ if (!Number.isNaN(codePoint)) {
307
+ return String.fromCodePoint(codePoint);
308
+ }
309
+ return _match;
310
+ }
311
+ switch (entity) {
312
+ case "amp":
313
+ return "&";
314
+ case "apos":
315
+ return "'";
316
+ case "gt":
317
+ return ">";
318
+ case "lt":
319
+ return "<";
320
+ case "nbsp":
321
+ return "\xA0";
322
+ case "quot":
323
+ return '"';
324
+ default:
325
+ return _match;
326
+ }
327
+ });
328
+ }
329
+ function parseRawHtmlAttributes(source) {
330
+ const attributes = [];
331
+ for (const match of source.matchAll(RAW_HTML_ATTR_PATTERN)) {
332
+ const name = match[1]?.toLowerCase();
333
+ if (!name) {
334
+ continue;
335
+ }
336
+ const rawValue = match[2] ?? match[3] ?? match[4] ?? "";
337
+ const value = decodeHtmlEntities(rawValue);
338
+ attributes.push({ name, value });
339
+ }
340
+ return attributes;
341
+ }
342
+ function parseRawHtmlFragment(source) {
343
+ const root = {
344
+ attributes: [],
345
+ children: [],
346
+ tagName: "#root",
347
+ type: "element"
348
+ };
349
+ const stack = [root];
350
+ for (const match of source.matchAll(RAW_HTML_TOKEN_PATTERN)) {
351
+ const token = match[0];
352
+ if (token.startsWith("<!--")) {
353
+ continue;
354
+ }
355
+ if (token === "<") {
356
+ stack[stack.length - 1]?.children.push({ text: "<", type: "text" });
357
+ continue;
358
+ }
359
+ const closingTag = /^<\/\s*([A-Za-z][\w:-]*)\s*>$/.exec(token);
360
+ if (closingTag) {
361
+ const closingTagName = closingTag[1];
362
+ if (!closingTagName) {
363
+ continue;
364
+ }
365
+ const tagName = closingTagName.toLowerCase();
366
+ for (let index = stack.length - 1; index > 0; index -= 1) {
367
+ if (stack[index]?.tagName === tagName) {
368
+ stack.length = index;
369
+ break;
370
+ }
371
+ }
372
+ continue;
373
+ }
374
+ const openingTag = /^<\s*([A-Za-z][\w:-]*)([\s\S]*?)>$/.exec(token);
375
+ if (openingTag) {
376
+ const openingTagName = openingTag[1];
377
+ if (!openingTagName) {
378
+ continue;
379
+ }
380
+ const tagName = openingTagName.toLowerCase();
381
+ const rawAttributes = openingTag[2] ?? "";
382
+ const selfClosing = /\/\s*$/.test(rawAttributes) || RAW_HTML_VOID_TAGS.has(tagName);
383
+ const attrSource = selfClosing ? rawAttributes.replace(/\/\s*$/, "") : rawAttributes;
384
+ const element = {
385
+ attributes: parseRawHtmlAttributes(attrSource),
386
+ children: [],
387
+ tagName,
388
+ type: "element"
389
+ };
390
+ stack[stack.length - 1]?.children.push(element);
391
+ if (!selfClosing) {
392
+ stack.push(element);
393
+ }
394
+ continue;
395
+ }
396
+ stack[stack.length - 1]?.children.push({
397
+ text: decodeHtmlEntities(token),
398
+ type: "text"
399
+ });
400
+ }
401
+ return root.children;
402
+ }
403
+ function toCamelCaseCssProperty(name) {
404
+ return name.trim().replace(/^-+/, "").replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
405
+ }
406
+ function parseStyleAttribute(value) {
407
+ const style = {};
408
+ for (const declaration of value.split(";")) {
409
+ const separatorIndex = declaration.indexOf(":");
410
+ if (separatorIndex === -1) {
411
+ continue;
412
+ }
413
+ const property = toCamelCaseCssProperty(declaration.slice(0, separatorIndex));
414
+ const propertyValue = declaration.slice(separatorIndex + 1).trim();
415
+ if (!property || !propertyValue) {
416
+ continue;
417
+ }
418
+ style[property] = propertyValue;
419
+ }
420
+ if (Object.keys(style).length === 0) {
421
+ return void 0;
422
+ }
423
+ return style;
424
+ }
425
+ function toRawHtmlDomProps(attributes) {
426
+ const props = {};
427
+ for (const { name, value } of attributes) {
428
+ if (name.startsWith("on")) {
429
+ continue;
430
+ }
431
+ if (RAW_HTML_URL_ATTRS.has(name) && RAW_HTML_UNSAFE_PROTOCOL.test(value)) {
432
+ continue;
433
+ }
434
+ if (name === "class") {
435
+ props.className = value;
436
+ continue;
437
+ }
438
+ if (name === "for") {
439
+ props.htmlFor = value;
440
+ continue;
441
+ }
442
+ if (name === "style") {
443
+ const style = parseStyleAttribute(value);
444
+ if (style) {
445
+ props.style = style;
446
+ }
447
+ continue;
448
+ }
449
+ if (RAW_HTML_BOOLEAN_ATTRS.has(name) && value.length === 0) {
450
+ props[name] = true;
451
+ continue;
452
+ }
453
+ props[name] = value;
454
+ }
455
+ return props;
456
+ }
457
+ function renderRawHtmlNode(node, key) {
458
+ if (node.type === "text") {
459
+ return node.text;
460
+ }
461
+ if (RAW_HTML_BLOCKED_TAGS.has(node.tagName)) {
462
+ return null;
463
+ }
464
+ const children = renderRawHtmlNodes(node.children, key);
465
+ return createElement(
466
+ node.tagName,
467
+ withKey(toRawHtmlDomProps(node.attributes), key),
468
+ children.length > 0 ? children : void 0
469
+ );
470
+ }
471
+ function renderRawHtmlNodes(nodes, keyPrefix) {
472
+ const rendered = [];
473
+ for (const [index, node] of nodes.entries()) {
474
+ const next = renderRawHtmlNode(node, `${keyPrefix}-${index}`);
475
+ if (next !== null) {
476
+ rendered.push(next);
477
+ }
478
+ }
479
+ return rendered;
480
+ }
481
+ function rawHtmlChildren(value, keyPrefix) {
482
+ return renderRawHtmlNodes(parseRawHtmlFragment(value), keyPrefix);
483
+ }
484
+
485
+ // src/renderNode.tsx
486
+ function isParentNode3(node) {
487
+ return Array.isArray(node.children);
488
+ }
489
+ function isSoftBreakNode(node) {
490
+ return node.tag === "soft_break" || node.tag === "softbreak";
491
+ }
492
+ function isHardBreakNode(node) {
493
+ return node.tag === "hard_break" || node.tag === "hardbreak";
494
+ }
495
+ function pickComponent(components, primary, alias) {
496
+ if (!components) {
497
+ return void 0;
498
+ }
499
+ return components[primary] ?? (alias ? components[alias] : void 0);
500
+ }
501
+ function renderChildren(children, components, footnoteState, listTight) {
502
+ return children.map(
503
+ (child, index) => renderNode(child, {
504
+ components,
505
+ footnoteState,
506
+ key: index,
507
+ listTight
508
+ })
509
+ );
510
+ }
74
511
  function renderWithOverride(override, fallback, domProps, customProps, key, children) {
75
512
  const Component = override ?? fallback;
76
513
  const props = typeof Component === "string" ? withKey(domProps, key) : withKey(
@@ -80,52 +517,386 @@ function renderWithOverride(override, fallback, domProps, customProps, key, chil
80
517
  },
81
518
  key
82
519
  );
83
- return createElement(Component, props, children);
520
+ return createElement(Component, props, children);
521
+ }
522
+ function renderDoc(node, components, key) {
523
+ const footnoteState = createFootnoteState(node);
524
+ const children = renderChildren(node.children, components, footnoteState);
525
+ const endnotes = renderEndnotes(node, components, footnoteState);
526
+ const allChildren = endnotes ? [...children, endnotes] : children;
527
+ const Component = pickComponent(components, "doc");
528
+ if (Component) {
529
+ const domProps = mergeDomProps(node);
530
+ if (typeof Component === "string") {
531
+ return createElement(Component, withKey(domProps, key), allChildren);
532
+ }
533
+ return createElement(Component, withKey({ ...domProps, node }, key), allChildren);
534
+ }
535
+ return createElement(Fragment, withKey({}, key), allChildren);
536
+ }
537
+ function renderSection(node, components, footnoteState, key) {
538
+ const children = renderChildren(node.children, components, footnoteState);
539
+ return renderWithOverride(
540
+ pickComponent(components, "section"),
541
+ "section",
542
+ mergeDomProps(node),
543
+ {
544
+ node
545
+ },
546
+ key,
547
+ children
548
+ );
549
+ }
550
+ function renderDiv(node, components, footnoteState, key) {
551
+ const children = renderChildren(node.children, components, footnoteState);
552
+ return renderWithOverride(
553
+ pickComponent(components, "div"),
554
+ "div",
555
+ mergeDomProps(node),
556
+ {
557
+ node
558
+ },
559
+ key,
560
+ children
561
+ );
562
+ }
563
+ function renderTable(node, components, footnoteState, key) {
564
+ const captionChildren = [];
565
+ const headRows = [];
566
+ const bodyRows = [];
567
+ const otherChildren = [];
568
+ for (const [index, child] of node.children.entries()) {
569
+ const rendered = renderNode(child, {
570
+ components,
571
+ footnoteState,
572
+ key: index
573
+ });
574
+ if (child.tag === "caption") {
575
+ captionChildren.push(rendered);
576
+ continue;
577
+ }
578
+ if (child.tag === "row") {
579
+ if (child.head && bodyRows.length === 0) {
580
+ headRows.push(rendered);
581
+ } else {
582
+ bodyRows.push(rendered);
583
+ }
584
+ continue;
585
+ }
586
+ otherChildren.push(rendered);
587
+ }
588
+ const children = [...captionChildren];
589
+ if (headRows.length > 0) {
590
+ children.push(createElement("thead", { key: "thead" }, headRows));
591
+ }
592
+ if (bodyRows.length > 0) {
593
+ children.push(createElement("tbody", { key: "tbody" }, bodyRows));
594
+ }
595
+ if (otherChildren.length > 0) {
596
+ children.push(...otherChildren);
597
+ }
598
+ return renderWithOverride(
599
+ pickComponent(components, "table"),
600
+ "table",
601
+ mergeDomProps(node),
602
+ {
603
+ node
604
+ },
605
+ key,
606
+ children
607
+ );
608
+ }
609
+ function renderCaption(node, components, footnoteState, key) {
610
+ const children = renderChildren(node.children, components, footnoteState);
611
+ const Component = pickComponent(components, "caption");
612
+ if (!Component && children.length === 0) {
613
+ return null;
614
+ }
615
+ return renderWithOverride(
616
+ Component,
617
+ "caption",
618
+ mergeDomProps(node),
619
+ {
620
+ node
621
+ },
622
+ key,
623
+ children
624
+ );
625
+ }
626
+ function renderRow(node, components, footnoteState, key) {
627
+ const children = renderChildren(node.children, components, footnoteState);
628
+ return renderWithOverride(
629
+ pickComponent(components, "row"),
630
+ "tr",
631
+ mergeDomProps(node),
632
+ {
633
+ head: node.head,
634
+ node
635
+ },
636
+ key,
637
+ children
638
+ );
639
+ }
640
+ function renderCell(node, components, footnoteState, key) {
641
+ const children = renderChildren(node.children, components, footnoteState);
642
+ const textAlign = textAlignForCell(node.align);
643
+ const domProps = mergeDomProps(node, {
644
+ style: textAlign ? { textAlign } : void 0
645
+ });
646
+ return renderWithOverride(
647
+ pickComponent(components, "cell"),
648
+ node.head ? "th" : "td",
649
+ domProps,
650
+ {
651
+ align: node.align,
652
+ head: node.head,
653
+ node
654
+ },
655
+ key,
656
+ children
657
+ );
658
+ }
659
+ function renderHeading(node, components, footnoteState, key) {
660
+ const level = clampHeadingLevel(node.level);
661
+ const children = renderChildren(node.children, components, footnoteState);
662
+ return renderWithOverride(
663
+ pickComponent(components, "heading"),
664
+ `h${level}`,
665
+ mergeDomProps(node),
666
+ {
667
+ level,
668
+ node
669
+ },
670
+ key,
671
+ children
672
+ );
673
+ }
674
+ function renderMark(node, components, footnoteState, key, primary, alias) {
675
+ const children = renderChildren(node.children, components, footnoteState);
676
+ return renderWithOverride(
677
+ pickComponent(components, primary, alias),
678
+ "mark",
679
+ mergeDomProps(node),
680
+ {
681
+ node
682
+ },
683
+ key,
684
+ children
685
+ );
686
+ }
687
+ function renderSuperscript(node, components, footnoteState, key, primary, alias) {
688
+ const children = renderChildren(node.children, components, footnoteState);
689
+ return renderWithOverride(
690
+ pickComponent(components, primary, alias),
691
+ "sup",
692
+ mergeDomProps(node),
693
+ {
694
+ node
695
+ },
696
+ key,
697
+ children
698
+ );
699
+ }
700
+ function renderSubscript(node, components, footnoteState, key) {
701
+ const children = renderChildren(node.children, components, footnoteState);
702
+ return renderWithOverride(
703
+ pickComponent(components, "subscript"),
704
+ "sub",
705
+ mergeDomProps(node),
706
+ {
707
+ node
708
+ },
709
+ key,
710
+ children
711
+ );
712
+ }
713
+ function renderInsert(node, components, footnoteState, key) {
714
+ const children = renderChildren(node.children, components, footnoteState);
715
+ return renderWithOverride(
716
+ pickComponent(components, "insert"),
717
+ "ins",
718
+ mergeDomProps(node),
719
+ {
720
+ node
721
+ },
722
+ key,
723
+ children
724
+ );
725
+ }
726
+ function renderDelete(node, components, footnoteState, key) {
727
+ const children = renderChildren(node.children, components, footnoteState);
728
+ return renderWithOverride(
729
+ pickComponent(components, "delete"),
730
+ "del",
731
+ mergeDomProps(node),
732
+ {
733
+ node
734
+ },
735
+ key,
736
+ children
737
+ );
738
+ }
739
+ function renderFootnoteReference(node, components, footnoteState, key) {
740
+ const label = node.text;
741
+ const index = footnoteState ? ensureFootnoteIndex(label, footnoteState) : 1;
742
+ const refCount = (footnoteState?.refCountByLabel.get(label) ?? 0) + 1;
743
+ if (footnoteState) {
744
+ footnoteState.refCountByLabel.set(label, refCount);
745
+ }
746
+ const id = refCount === 1 ? `fnref${index}` : `fnref${index}-${refCount}`;
747
+ if (footnoteState && !footnoteState.firstRefIdByLabel.has(label)) {
748
+ footnoteState.firstRefIdByLabel.set(label, id);
749
+ }
750
+ const href = `#fn${index}`;
751
+ const children = createElement("sup", null, index);
752
+ return renderWithOverride(
753
+ pickComponent(components, "footnote_reference"),
754
+ "a",
755
+ mergeDomProps(node, {
756
+ href,
757
+ id,
758
+ role: "doc-noteref"
759
+ }),
760
+ {
761
+ index,
762
+ label,
763
+ node
764
+ },
765
+ key,
766
+ children
767
+ );
768
+ }
769
+ function renderEndnotes(node, components, footnoteState) {
770
+ if (footnoteState.order.length === 0) {
771
+ return null;
772
+ }
773
+ const items = footnoteState.order.map((label, itemIndex) => {
774
+ const index = itemIndex + 1;
775
+ const footnoteNode = node.footnotes?.[label] ?? {
776
+ children: [],
777
+ label,
778
+ tag: "footnote"
779
+ };
780
+ const footnoteChildren = renderChildren(footnoteNode.children, components, footnoteState);
781
+ const backlink = createElement(
782
+ "a",
783
+ {
784
+ href: `#${footnoteState.firstRefIdByLabel.get(label) ?? `fnref${index}`}`,
785
+ role: "doc-backlink"
786
+ },
787
+ "\u21A9\uFE0E"
788
+ );
789
+ const content = appendBacklink(footnoteChildren, backlink);
790
+ return renderWithOverride(
791
+ pickComponent(components, "footnote"),
792
+ "li",
793
+ mergeDomProps(footnoteNode, {
794
+ id: `fn${index}`,
795
+ key: label
796
+ }),
797
+ {
798
+ index,
799
+ label,
800
+ node: footnoteNode
801
+ },
802
+ label,
803
+ content
804
+ );
805
+ });
806
+ const ol = createElement("ol", null, items);
807
+ const sectionChildren = [createElement("hr", { key: "hr" }), createElement(Fragment, { key: "ol" }, ol)];
808
+ return renderWithOverride(
809
+ pickComponent(components, "endnotes"),
810
+ "section",
811
+ {
812
+ role: "doc-endnotes"
813
+ },
814
+ {
815
+ node,
816
+ order: footnoteState.order
817
+ },
818
+ "endnotes",
819
+ sectionChildren
820
+ );
821
+ }
822
+ function renderQuoted(node, components, footnoteState, key, primary, alias, openQuote, closeQuote) {
823
+ const children = renderChildren(node.children, components, footnoteState);
824
+ const Component = pickComponent(components, primary, alias);
825
+ const domProps = mergeDomProps(node);
826
+ if (!Component) {
827
+ return createElement(Fragment, withKey({}, key), openQuote, children, closeQuote);
828
+ }
829
+ if (typeof Component === "string") {
830
+ return createElement(Component, withKey(domProps, key), openQuote, children, closeQuote);
831
+ }
832
+ return createElement(
833
+ Component,
834
+ withKey(
835
+ {
836
+ ...domProps,
837
+ node
838
+ },
839
+ key
840
+ ),
841
+ openQuote,
842
+ children,
843
+ closeQuote
844
+ );
84
845
  }
85
- function renderDoc(node, components, key) {
86
- const children = renderChildren(node.children, components);
87
- const Component = pickComponent(components, "doc");
88
- if (Component) {
89
- if (typeof Component === "string") {
90
- return createElement(Component, withKey({}, key), children);
91
- }
92
- return createElement(Component, withKey({ node }, key), children);
846
+ function renderSmartPunctuation(node, components, key) {
847
+ const value = toSmartPunctuation(node.type, node.text);
848
+ const Component = pickComponent(components, "smart_punctuation");
849
+ const domProps = mergeDomProps(node);
850
+ if (!Component) {
851
+ return value;
93
852
  }
94
- return createElement(Fragment, withKey({}, key), children);
95
- }
96
- function renderSection(node, components, key) {
97
- const children = renderChildren(node.children, components);
98
- const Component = pickComponent(components, "section");
99
- if (Component) {
100
- if (typeof Component === "string") {
101
- return createElement(Component, withKey({}, key), children);
102
- }
103
- return createElement(
104
- Component,
105
- withKey(
106
- {
107
- node
108
- },
109
- key
110
- ),
111
- children
112
- );
853
+ if (typeof Component === "string") {
854
+ return createElement(Component, withKey(domProps, key), value);
113
855
  }
114
- return createElement(Fragment, withKey({}, key), children);
856
+ return createElement(
857
+ Component,
858
+ withKey(
859
+ {
860
+ ...domProps,
861
+ kind: node.type,
862
+ node,
863
+ value
864
+ },
865
+ key
866
+ ),
867
+ value
868
+ );
115
869
  }
116
- function renderHeading(node, components, key) {
117
- const level = clampHeadingLevel(node.level);
118
- const children = renderChildren(node.children, components);
870
+ function renderInlineMath(node, components, key) {
871
+ const value = node.text;
119
872
  return renderWithOverride(
120
- pickComponent(components, "heading"),
121
- `h${level}`,
122
- {},
873
+ pickComponent(components, "inline_math"),
874
+ "span",
875
+ mergeDomProps(node, {
876
+ className: "math inline"
877
+ }),
123
878
  {
124
- level,
125
- node
879
+ node,
880
+ value
126
881
  },
127
882
  key,
128
- children
883
+ `\\(${value}\\)`
884
+ );
885
+ }
886
+ function renderDisplayMath(node, components, key) {
887
+ const value = node.text;
888
+ return renderWithOverride(
889
+ pickComponent(components, "display_math"),
890
+ "span",
891
+ mergeDomProps(node, {
892
+ className: "math display"
893
+ }),
894
+ {
895
+ node,
896
+ value
897
+ },
898
+ key,
899
+ `\\[${value}\\]`
129
900
  );
130
901
  }
131
902
  function renderCode(node, components, key, primary, alias) {
@@ -133,7 +904,7 @@ function renderCode(node, components, key, primary, alias) {
133
904
  return renderWithOverride(
134
905
  pickComponent(components, primary, alias),
135
906
  "code",
136
- {},
907
+ mergeDomProps(node),
137
908
  {
138
909
  node,
139
910
  value
@@ -155,7 +926,7 @@ function renderCodeBlock(node, components, key) {
155
926
  return renderWithOverride(
156
927
  pickComponent(components, "code_block"),
157
928
  "pre",
158
- {},
929
+ mergeDomProps(node),
159
930
  {
160
931
  language,
161
932
  node,
@@ -165,15 +936,136 @@ function renderCodeBlock(node, components, key) {
165
936
  fallbackChildren
166
937
  );
167
938
  }
168
- function renderLink(node, components, key) {
169
- const children = renderChildren(node.children, components);
170
- const href = node.destination;
939
+ function renderRawBlock(node, components, key) {
940
+ const format = node.format;
941
+ const value = node.text;
942
+ const htmlChildren = format === "html" ? rawHtmlChildren(value, `raw-block-${String(key ?? "node")}`) : void 0;
943
+ const Component = pickComponent(components, "raw_block");
944
+ const domProps = mergeDomProps(node);
945
+ if (!Component) {
946
+ if (format !== "html") {
947
+ return null;
948
+ }
949
+ return createElement(Fragment, withKey({}, key), htmlChildren);
950
+ }
951
+ if (typeof Component === "string") {
952
+ return createElement(Component, withKey(domProps, key), htmlChildren ?? value);
953
+ }
954
+ return createElement(
955
+ Component,
956
+ withKey(
957
+ {
958
+ ...domProps,
959
+ format,
960
+ node,
961
+ value
962
+ },
963
+ key
964
+ ),
965
+ htmlChildren ?? value
966
+ );
967
+ }
968
+ function renderRawInline(node, components, key) {
969
+ const format = node.format;
970
+ const value = node.text;
971
+ const htmlChildren = format === "html" ? rawHtmlChildren(value, `raw-inline-${String(key ?? "node")}`) : void 0;
972
+ const Component = pickComponent(components, "raw_inline");
973
+ const domProps = mergeDomProps(node);
974
+ if (!Component) {
975
+ if (format !== "html") {
976
+ return null;
977
+ }
978
+ return createElement(Fragment, withKey({}, key), htmlChildren);
979
+ }
980
+ if (typeof Component === "string") {
981
+ return createElement(Component, withKey(domProps, key), htmlChildren ?? value);
982
+ }
983
+ return createElement(
984
+ Component,
985
+ withKey(
986
+ {
987
+ ...domProps,
988
+ format,
989
+ node,
990
+ value
991
+ },
992
+ key
993
+ ),
994
+ htmlChildren ?? value
995
+ );
996
+ }
997
+ function renderUrl(node, components, key) {
998
+ const value = node.text;
999
+ const href = value;
171
1000
  return renderWithOverride(
172
- pickComponent(components, "link"),
1001
+ pickComponent(components, "url"),
173
1002
  "a",
1003
+ mergeDomProps(node, {
1004
+ href
1005
+ }),
174
1006
  {
1007
+ href,
1008
+ node,
1009
+ value
1010
+ },
1011
+ key,
1012
+ value
1013
+ );
1014
+ }
1015
+ function renderEmail(node, components, key) {
1016
+ const value = node.text;
1017
+ const href = `mailto:${value}`;
1018
+ return renderWithOverride(
1019
+ pickComponent(components, "email"),
1020
+ "a",
1021
+ mergeDomProps(node, {
175
1022
  href
1023
+ }),
1024
+ {
1025
+ href,
1026
+ node,
1027
+ value
176
1028
  },
1029
+ key,
1030
+ value
1031
+ );
1032
+ }
1033
+ function renderSymb(node, components, key) {
1034
+ const alias = node.alias;
1035
+ const value = `:${alias}:`;
1036
+ const Component = pickComponent(components, "symb");
1037
+ if (!Component) {
1038
+ return value;
1039
+ }
1040
+ if (typeof Component === "string") {
1041
+ return createElement(Component, withKey(mergeDomProps(node), key), value);
1042
+ }
1043
+ return createElement(
1044
+ Component,
1045
+ withKey(
1046
+ {
1047
+ ...mergeDomProps(node),
1048
+ alias,
1049
+ node,
1050
+ value
1051
+ },
1052
+ key
1053
+ ),
1054
+ value
1055
+ );
1056
+ }
1057
+ function renderLink(node, components, footnoteState, key) {
1058
+ const children = renderChildren(node.children, components, footnoteState);
1059
+ const referenceNode = resolveReferenceNode(node, footnoteState);
1060
+ const referenceProps = referenceNode ? toDomPropsFromNode(referenceNode) : {};
1061
+ const href = resolveReferenceDestination(node, footnoteState);
1062
+ return renderWithOverride(
1063
+ pickComponent(components, "link"),
1064
+ "a",
1065
+ mergeDomProps(node, {
1066
+ href,
1067
+ ...referenceProps
1068
+ }),
177
1069
  {
178
1070
  node
179
1071
  },
@@ -181,16 +1073,19 @@ function renderLink(node, components, key) {
181
1073
  children
182
1074
  );
183
1075
  }
184
- function renderImage(node, components, key) {
1076
+ function renderImage(node, components, footnoteState, key) {
185
1077
  const alt = toAltText(node.children) || void 0;
186
- const src = node.destination;
1078
+ const referenceNode = resolveReferenceNode(node, footnoteState);
1079
+ const referenceProps = referenceNode ? toDomPropsFromNode(referenceNode) : {};
1080
+ const src = resolveReferenceDestination(node, footnoteState);
187
1081
  return renderWithOverride(
188
1082
  pickComponent(components, "image"),
189
1083
  "img",
190
- {
1084
+ mergeDomProps(node, {
191
1085
  alt,
192
- src
193
- },
1086
+ src,
1087
+ ...referenceProps
1088
+ }),
194
1089
  {
195
1090
  alt,
196
1091
  node
@@ -198,28 +1093,165 @@ function renderImage(node, components, key) {
198
1093
  key
199
1094
  );
200
1095
  }
201
- function renderOrderedList(node, components, key) {
202
- const children = renderChildren(node.children, components);
1096
+ function renderOrderedList(node, components, footnoteState, key) {
1097
+ const tight = node.tight ?? false;
1098
+ const children = renderChildren(node.children, components, footnoteState, tight);
1099
+ const start = node.start !== void 0 && node.start !== 1 ? node.start : void 0;
1100
+ const type = toOrderedListType(node.style);
203
1101
  return renderWithOverride(
204
1102
  pickComponent(components, "ordered_list"),
205
1103
  "ol",
1104
+ mergeDomProps(node, {
1105
+ start,
1106
+ type
1107
+ }),
1108
+ {
1109
+ node,
1110
+ start,
1111
+ tight
1112
+ },
1113
+ key,
1114
+ children
1115
+ );
1116
+ }
1117
+ function renderDefinitionList(node, components, footnoteState, key) {
1118
+ const children = renderChildren(node.children, components, footnoteState);
1119
+ return renderWithOverride(
1120
+ pickComponent(components, "definition_list"),
1121
+ "dl",
1122
+ mergeDomProps(node),
206
1123
  {
207
- start: node.start
1124
+ node
208
1125
  },
1126
+ key,
1127
+ children
1128
+ );
1129
+ }
1130
+ function renderDefinitionListItem(node, components, footnoteState, key) {
1131
+ const children = renderChildren(node.children, components, footnoteState);
1132
+ const Component = pickComponent(components, "definition_list_item");
1133
+ const domProps = mergeDomProps(node);
1134
+ if (Component) {
1135
+ if (typeof Component === "string") {
1136
+ return createElement(Component, withKey(domProps, key), children);
1137
+ }
1138
+ return createElement(
1139
+ Component,
1140
+ withKey(
1141
+ {
1142
+ ...domProps,
1143
+ node
1144
+ },
1145
+ key
1146
+ ),
1147
+ children
1148
+ );
1149
+ }
1150
+ return createElement(Fragment, withKey({}, key), children);
1151
+ }
1152
+ function renderBulletList(node, components, footnoteState, key) {
1153
+ const tight = node.tight ?? false;
1154
+ const children = renderChildren(node.children, components, footnoteState, tight);
1155
+ return renderWithOverride(
1156
+ pickComponent(components, "bullet_list"),
1157
+ "ul",
1158
+ mergeDomProps(node),
209
1159
  {
210
1160
  node,
211
- start: node.start
1161
+ tight
1162
+ },
1163
+ key,
1164
+ children
1165
+ );
1166
+ }
1167
+ function renderListItem(node, components, footnoteState, listTight, key) {
1168
+ const override = pickComponent(components, "list_item");
1169
+ if (override) {
1170
+ const domProps = mergeDomProps(node);
1171
+ const contentChildren2 = renderChildren(node.children, components, footnoteState);
1172
+ if (typeof override === "string") {
1173
+ return createElement(override, withKey(domProps, key), contentChildren2);
1174
+ }
1175
+ return createElement(
1176
+ override,
1177
+ withKey({ ...domProps, node, tight: listTight }, key),
1178
+ contentChildren2
1179
+ );
1180
+ }
1181
+ const firstChild = node.children[0];
1182
+ const inlineSource = listTight === true && node.children.length === 1 && firstChild?.tag === "para" ? firstChild.children : node.children;
1183
+ const contentChildren = renderChildren(inlineSource, components, footnoteState);
1184
+ return createElement("li", withKey(mergeDomProps(node), key), contentChildren);
1185
+ }
1186
+ function renderTerm(node, components, footnoteState, key) {
1187
+ const children = renderChildren(node.children, components, footnoteState);
1188
+ return renderWithOverride(
1189
+ pickComponent(components, "term"),
1190
+ "dt",
1191
+ mergeDomProps(node),
1192
+ {
1193
+ node
1194
+ },
1195
+ key,
1196
+ children
1197
+ );
1198
+ }
1199
+ function renderDefinition(node, components, footnoteState, key) {
1200
+ const children = renderChildren(node.children, components, footnoteState);
1201
+ return renderWithOverride(
1202
+ pickComponent(components, "definition"),
1203
+ "dd",
1204
+ mergeDomProps(node),
1205
+ {
1206
+ node
212
1207
  },
213
1208
  key,
214
1209
  children
215
1210
  );
216
1211
  }
217
- function renderBlockQuote(node, components, key, primary, alias) {
218
- const children = renderChildren(node.children, components);
1212
+ function renderTaskList(node, components, footnoteState, key) {
1213
+ const tight = node.tight ?? false;
1214
+ const children = renderChildren(node.children, components, footnoteState, tight);
1215
+ return renderWithOverride(
1216
+ pickComponent(components, "task_list"),
1217
+ "ul",
1218
+ mergeDomProps(node, { className: "task-list" }),
1219
+ { node, tight },
1220
+ key,
1221
+ children
1222
+ );
1223
+ }
1224
+ function renderTaskListItem(node, components, footnoteState, listTight, key) {
1225
+ const override = pickComponent(components, "task_list_item");
1226
+ if (override) {
1227
+ const domProps = mergeDomProps(node);
1228
+ const contentChildren2 = renderChildren(node.children, components, footnoteState);
1229
+ if (typeof override === "string") {
1230
+ return createElement(override, withKey(domProps, key), contentChildren2);
1231
+ }
1232
+ return createElement(
1233
+ override,
1234
+ withKey({ ...domProps, node, checkbox: node.checkbox, tight: listTight }, key),
1235
+ contentChildren2
1236
+ );
1237
+ }
1238
+ const firstChild = node.children[0];
1239
+ const inlineSource = listTight === true && node.children.length === 1 && firstChild?.tag === "para" ? firstChild.children : node.children;
1240
+ const contentChildren = renderChildren(inlineSource, components, footnoteState);
1241
+ const checkboxEl = createElement("input", {
1242
+ key: "checkbox",
1243
+ type: "checkbox",
1244
+ disabled: true,
1245
+ checked: node.checkbox === "checked"
1246
+ });
1247
+ return createElement("li", withKey(mergeDomProps(node), key), [checkboxEl, contentChildren]);
1248
+ }
1249
+ function renderBlockQuote(node, components, footnoteState, key, primary, alias) {
1250
+ const children = renderChildren(node.children, components, footnoteState);
219
1251
  return renderWithOverride(
220
1252
  pickComponent(components, primary, alias),
221
1253
  "blockquote",
222
- {},
1254
+ mergeDomProps(node),
223
1255
  {
224
1256
  node
225
1257
  },
@@ -230,16 +1262,49 @@ function renderBlockQuote(node, components, key, primary, alias) {
230
1262
  function renderStr(node, components, key) {
231
1263
  const value = node.text;
232
1264
  const Component = pickComponent(components, "str");
1265
+ const domProps = mergeDomProps(node);
1266
+ const hasNodeDomProps = Object.keys(domProps).length > 0;
1267
+ if (!Component) {
1268
+ if (hasNodeDomProps) {
1269
+ return createElement("span", withKey(domProps, key), value);
1270
+ }
1271
+ return value;
1272
+ }
1273
+ if (typeof Component === "string") {
1274
+ return createElement(Component, withKey(domProps, key), value);
1275
+ }
1276
+ return createElement(
1277
+ Component,
1278
+ withKey(
1279
+ {
1280
+ ...domProps,
1281
+ node,
1282
+ value
1283
+ },
1284
+ key
1285
+ ),
1286
+ value
1287
+ );
1288
+ }
1289
+ function renderNonBreakingSpace(node, components, key) {
1290
+ const value = "\xA0";
1291
+ const Component = pickComponent(components, "non_breaking_space");
1292
+ const domProps = mergeDomProps(node);
1293
+ const hasNodeDomProps = Object.keys(domProps).length > 0;
233
1294
  if (!Component) {
1295
+ if (hasNodeDomProps) {
1296
+ return createElement("span", withKey(domProps, key), value);
1297
+ }
234
1298
  return value;
235
1299
  }
236
1300
  if (typeof Component === "string") {
237
- return createElement(Component, withKey({}, key), value);
1301
+ return createElement(Component, withKey(domProps, key), value);
238
1302
  }
239
1303
  return createElement(
240
1304
  Component,
241
1305
  withKey(
242
1306
  {
1307
+ ...domProps,
243
1308
  node,
244
1309
  value
245
1310
  },
@@ -250,16 +1315,18 @@ function renderStr(node, components, key) {
250
1315
  }
251
1316
  function renderSoftBreak(node, components, key) {
252
1317
  const Component = pickComponent(components, "soft_break", "softbreak");
1318
+ const domProps = mergeDomProps(node);
253
1319
  if (!Component) {
254
1320
  return "\n";
255
1321
  }
256
1322
  if (typeof Component === "string") {
257
- return createElement(Component, withKey({}, key), "\n");
1323
+ return createElement(Component, withKey(domProps, key), "\n");
258
1324
  }
259
1325
  return createElement(
260
1326
  Component,
261
1327
  withKey(
262
1328
  {
1329
+ ...domProps,
263
1330
  node
264
1331
  },
265
1332
  key
@@ -271,7 +1338,7 @@ function renderHardBreak(node, components, key) {
271
1338
  return renderWithOverride(
272
1339
  pickComponent(components, "hard_break", "hardbreak"),
273
1340
  "br",
274
- {},
1341
+ mergeDomProps(node),
275
1342
  {
276
1343
  node
277
1344
  },
@@ -279,18 +1346,28 @@ function renderHardBreak(node, components, key) {
279
1346
  );
280
1347
  }
281
1348
  function renderNode(node, options = {}) {
282
- const { components, key } = options;
283
- const children = isParentNode(node) ? renderChildren(node.children, components) : void 0;
1349
+ const { components, footnoteState, key, listTight } = options;
1350
+ const children = isParentNode3(node) ? renderChildren(node.children, components, footnoteState, listTight) : void 0;
284
1351
  switch (node.tag) {
285
1352
  case "doc":
286
1353
  return renderDoc(node, components, key);
287
1354
  case "section":
288
- return renderSection(node, components, key);
1355
+ return renderSection(node, components, footnoteState, key);
1356
+ case "div":
1357
+ return renderDiv(node, components, footnoteState, key);
1358
+ case "table":
1359
+ return renderTable(node, components, footnoteState, key);
1360
+ case "caption":
1361
+ return renderCaption(node, components, footnoteState, key);
1362
+ case "row":
1363
+ return renderRow(node, components, footnoteState, key);
1364
+ case "cell":
1365
+ return renderCell(node, components, footnoteState, key);
289
1366
  case "para":
290
1367
  return renderWithOverride(
291
1368
  pickComponent(components, "para"),
292
1369
  "p",
293
- {},
1370
+ mergeDomProps(node),
294
1371
  {
295
1372
  node
296
1373
  },
@@ -298,12 +1375,12 @@ function renderNode(node, options = {}) {
298
1375
  children
299
1376
  );
300
1377
  case "heading":
301
- return renderHeading(node, components, key);
1378
+ return renderHeading(node, components, footnoteState, key);
302
1379
  case "emph":
303
1380
  return renderWithOverride(
304
1381
  pickComponent(components, "emph"),
305
1382
  "em",
306
- {},
1383
+ mergeDomProps(node),
307
1384
  {
308
1385
  node
309
1386
  },
@@ -314,56 +1391,128 @@ function renderNode(node, options = {}) {
314
1391
  return renderWithOverride(
315
1392
  pickComponent(components, "strong"),
316
1393
  "strong",
317
- {},
1394
+ mergeDomProps(node),
318
1395
  {
319
1396
  node
320
1397
  },
321
1398
  key,
322
1399
  children
323
1400
  );
324
- case "code":
325
- return renderCode(node, components, key, "code", "verbatim");
326
- case "verbatim":
327
- return renderCode(node, components, key, "verbatim", "code");
328
- case "code_block":
329
- return renderCodeBlock(node, components, key);
330
- case "link":
331
- return renderLink(node, components, key);
332
- case "image":
333
- return renderImage(node, components, key);
334
- case "bullet_list":
1401
+ case "mark":
1402
+ return renderMark(node, components, footnoteState, key, "mark", "highlighted");
1403
+ case "highlighted":
1404
+ return renderMark(node, components, footnoteState, key, "highlighted", "mark");
1405
+ case "superscript":
1406
+ return renderSuperscript(node, components, footnoteState, key, "superscript", "supe");
1407
+ case "supe":
1408
+ return renderSuperscript(node, components, footnoteState, key, "supe", "superscript");
1409
+ case "subscript":
1410
+ return renderSubscript(node, components, footnoteState, key);
1411
+ case "insert":
1412
+ return renderInsert(node, components, footnoteState, key);
1413
+ case "delete":
1414
+ return renderDelete(node, components, footnoteState, key);
1415
+ case "span":
335
1416
  return renderWithOverride(
336
- pickComponent(components, "bullet_list"),
337
- "ul",
338
- {},
1417
+ pickComponent(components, "span"),
1418
+ "span",
1419
+ mergeDomProps(node),
339
1420
  {
340
1421
  node
341
1422
  },
342
1423
  key,
343
1424
  children
344
1425
  );
345
- case "ordered_list":
346
- return renderOrderedList(node, components, key);
347
- case "list_item":
1426
+ case "footnote_reference":
1427
+ return renderFootnoteReference(node, components, footnoteState, key);
1428
+ case "footnote":
348
1429
  return renderWithOverride(
349
- pickComponent(components, "list_item"),
1430
+ pickComponent(components, "footnote"),
350
1431
  "li",
351
- {},
1432
+ mergeDomProps(node),
352
1433
  {
1434
+ index: 0,
1435
+ label: node.label,
353
1436
  node
354
1437
  },
355
1438
  key,
356
1439
  children
357
1440
  );
1441
+ case "double_quoted":
1442
+ return renderQuoted(
1443
+ node,
1444
+ components,
1445
+ footnoteState,
1446
+ key,
1447
+ "double_quoted",
1448
+ "single_quoted",
1449
+ "\u201C",
1450
+ "\u201D"
1451
+ );
1452
+ case "single_quoted":
1453
+ return renderQuoted(
1454
+ node,
1455
+ components,
1456
+ footnoteState,
1457
+ key,
1458
+ "single_quoted",
1459
+ "double_quoted",
1460
+ "\u2018",
1461
+ "\u2019"
1462
+ );
1463
+ case "smart_punctuation":
1464
+ return renderSmartPunctuation(node, components, key);
1465
+ case "symb":
1466
+ return renderSymb(node, components, key);
1467
+ case "inline_math":
1468
+ return renderInlineMath(node, components, key);
1469
+ case "display_math":
1470
+ return renderDisplayMath(node, components, key);
1471
+ case "code":
1472
+ return renderCode(node, components, key, "code", "verbatim");
1473
+ case "verbatim":
1474
+ return renderCode(node, components, key, "verbatim", "code");
1475
+ case "code_block":
1476
+ return renderCodeBlock(node, components, key);
1477
+ case "raw_block":
1478
+ return renderRawBlock(node, components, key);
1479
+ case "raw_inline":
1480
+ return renderRawInline(node, components, key);
1481
+ case "url":
1482
+ return renderUrl(node, components, key);
1483
+ case "email":
1484
+ return renderEmail(node, components, key);
1485
+ case "link":
1486
+ return renderLink(node, components, footnoteState, key);
1487
+ case "image":
1488
+ return renderImage(node, components, footnoteState, key);
1489
+ case "bullet_list":
1490
+ return renderBulletList(node, components, footnoteState, key);
1491
+ case "ordered_list":
1492
+ return renderOrderedList(node, components, footnoteState, key);
1493
+ case "list_item":
1494
+ return renderListItem(node, components, footnoteState, listTight, key);
1495
+ case "definition_list":
1496
+ return renderDefinitionList(node, components, footnoteState, key);
1497
+ case "definition_list_item":
1498
+ return renderDefinitionListItem(node, components, footnoteState, key);
1499
+ case "term":
1500
+ return renderTerm(node, components, footnoteState, key);
1501
+ case "definition":
1502
+ return renderDefinition(node, components, footnoteState, key);
1503
+ case "task_list":
1504
+ return renderTaskList(node, components, footnoteState, key);
1505
+ case "task_list_item":
1506
+ return renderTaskListItem(node, components, footnoteState, listTight, key);
358
1507
  case "blockquote":
359
- return renderBlockQuote(node, components, key, "blockquote", "block_quote");
1508
+ return renderBlockQuote(node, components, footnoteState, key, "blockquote", "block_quote");
360
1509
  case "block_quote":
361
- return renderBlockQuote(node, components, key, "block_quote", "blockquote");
1510
+ return renderBlockQuote(node, components, footnoteState, key, "block_quote", "blockquote");
362
1511
  case "thematic_break":
363
1512
  return renderWithOverride(
364
1513
  pickComponent(components, "thematic_break"),
365
1514
  "hr",
366
- {},
1515
+ mergeDomProps(node),
367
1516
  {
368
1517
  node
369
1518
  },
@@ -371,6 +1520,8 @@ function renderNode(node, options = {}) {
371
1520
  );
372
1521
  case "str":
373
1522
  return renderStr(node, components, key);
1523
+ case "non_breaking_space":
1524
+ return renderNonBreakingSpace(node, components, key);
374
1525
  default:
375
1526
  if (isSoftBreakNode(node)) {
376
1527
  return renderSoftBreak(node, components, key);
@@ -381,16 +1532,50 @@ function renderNode(node, options = {}) {
381
1532
  return null;
382
1533
  }
383
1534
  }
384
- function Djot({ children, components }) {
385
- const source = children ?? "";
1535
+ var COMPILE_CACHE_LIMIT = 100;
1536
+ var compileCache = /* @__PURE__ */ new Map();
1537
+ function getCachedAst(source) {
1538
+ const cached = compileCache.get(source);
1539
+ if (!cached) {
1540
+ return void 0;
1541
+ }
1542
+ compileCache.delete(source);
1543
+ compileCache.set(source, cached);
1544
+ return cached;
1545
+ }
1546
+ function setCachedAst(source, ast) {
1547
+ compileCache.set(source, ast);
1548
+ if (compileCache.size > COMPILE_CACHE_LIMIT) {
1549
+ const oldestSource = compileCache.keys().next().value;
1550
+ if (oldestSource !== void 0) {
1551
+ compileCache.delete(oldestSource);
1552
+ }
1553
+ }
1554
+ return ast;
1555
+ }
1556
+ function compileDjot(source) {
1557
+ const cached = getCachedAst(source);
1558
+ if (cached) {
1559
+ return cached;
1560
+ }
1561
+ const ast = parse(source);
1562
+ return setCachedAst(source, ast);
1563
+ }
1564
+ function Djot(props) {
1565
+ const { components } = props;
1566
+ const astFromProps = props.ast;
1567
+ if (astFromProps !== void 0) {
1568
+ return /* @__PURE__ */ jsx(Fragment, { children: renderNode(astFromProps, { components }) });
1569
+ }
1570
+ const source = props.children ?? "";
386
1571
  if (source.length === 0) {
387
1572
  return null;
388
1573
  }
389
- const ast = parse(source);
1574
+ const ast = compileDjot(source);
390
1575
  return /* @__PURE__ */ jsx(Fragment, { children: renderNode(ast, { components }) });
391
1576
  }
392
1577
  var Djot_default = Djot;
393
1578
 
394
- export { Djot, Djot_default as default, renderNode };
1579
+ export { Djot, compileDjot, Djot_default as default, renderNode };
395
1580
  //# sourceMappingURL=index.js.map
396
1581
  //# sourceMappingURL=index.js.map