@astryxdesign/core 0.6.2-canary.d4cc232 → 0.6.2-canary.d993f65

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.
Files changed (48) hide show
  1. package/dist/Markdown/Markdown.d.ts +8 -2
  2. package/dist/Markdown/Markdown.d.ts.map +1 -1
  3. package/dist/Markdown/Markdown.js +171 -53
  4. package/dist/Markdown/ast.d.ts +35 -2
  5. package/dist/Markdown/ast.d.ts.map +1 -1
  6. package/dist/Markdown/ast.js +18 -2
  7. package/dist/Markdown/index.d.ts +3 -1
  8. package/dist/Markdown/index.d.ts.map +1 -1
  9. package/dist/Markdown/index.js +1 -0
  10. package/dist/Markdown/parser.d.ts +99 -52
  11. package/dist/Markdown/parser.d.ts.map +1 -1
  12. package/dist/Markdown/parser.js +274 -65
  13. package/dist/Markdown/plugins/index.d.ts +8 -0
  14. package/dist/Markdown/plugins/index.d.ts.map +1 -0
  15. package/dist/Markdown/plugins/index.js +9 -0
  16. package/dist/Markdown/plugins/protocol.d.ts +135 -0
  17. package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
  18. package/dist/Markdown/plugins/protocol.js +551 -0
  19. package/dist/Markdown/url.d.ts +4 -0
  20. package/dist/Markdown/url.d.ts.map +1 -0
  21. package/dist/Markdown/url.js +25 -0
  22. package/dist/Markdown/utils.d.ts +4 -2
  23. package/dist/Markdown/utils.d.ts.map +1 -1
  24. package/dist/Markdown/utils.js +2 -1
  25. package/dist/Outline/index.d.ts +1 -0
  26. package/dist/Outline/index.d.ts.map +1 -1
  27. package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
  28. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  29. package/dist/Outline/parseOutlineFromMarkdown.js +9 -3
  30. package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
  31. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  32. package/dist/Outline/useOutlineFromMarkdown.js +8 -3
  33. package/package.json +8 -3
  34. package/src/Markdown/Markdown.doc.mjs +53 -0
  35. package/src/Markdown/Markdown.public.test.ts +54 -3
  36. package/src/Markdown/Markdown.tsx +296 -55
  37. package/src/Markdown/ast.ts +76 -4
  38. package/src/Markdown/index.ts +34 -0
  39. package/src/Markdown/parser.ts +610 -167
  40. package/src/Markdown/plugins/index.ts +27 -0
  41. package/src/Markdown/plugins/protocol.test.tsx +955 -0
  42. package/src/Markdown/plugins/protocol.ts +1065 -0
  43. package/src/Markdown/url.ts +30 -0
  44. package/src/Markdown/utils.ts +13 -1
  45. package/src/Outline/Outline.doc.mjs +7 -5
  46. package/src/Outline/index.ts +1 -0
  47. package/src/Outline/parseOutlineFromMarkdown.ts +34 -3
  48. package/src/Outline/useOutlineFromMarkdown.ts +15 -3
@@ -2,6 +2,7 @@ import type React from 'react';
2
2
  import type { TextDisplay } from '../theme/types';
3
3
  import type { BaseProps } from '../BaseProps';
4
4
  import type { CitationSource } from '../Citation/Citation';
5
+ import type { MarkdownPluginEntry } from './plugins/protocol';
5
6
  /**
6
7
  * A plugin that transforms text patterns into custom React elements
7
8
  * inside Markdown. Applied to parsed text nodes only — code blocks,
@@ -79,7 +80,7 @@ export interface MarkdownComponents {
79
80
  }>;
80
81
  hr?: React.ComponentType<object>;
81
82
  }
82
- export interface MarkdownProps extends BaseProps<HTMLElement> {
83
+ export interface MarkdownProps<Plugins extends ReadonlyArray<MarkdownPluginEntry> = readonly []> extends BaseProps<HTMLElement> {
83
84
  ref?: React.Ref<HTMLDivElement> | React.Ref<HTMLSpanElement>;
84
85
  children: string;
85
86
  /**
@@ -137,6 +138,11 @@ export interface MarkdownProps extends BaseProps<HTMLElement> {
137
138
  * are unaffected. Patterns are matched in order; first match wins
138
139
  * for overlapping ranges.
139
140
  */
141
+ /** Ordered syntax, immutable transforms, and typed extension renderers. */
142
+ plugins?: Plugins;
143
+ /**
144
+ * Legacy text-match renderers. Unchanged and independent from `plugins`.
145
+ */
140
146
  inlinePlugins?: MarkdownInlinePlugin[];
141
147
  /**
142
148
  * Opt-in autolinking of bare URLs and emails inside text.
@@ -163,7 +169,7 @@ export interface MarkdownProps extends BaseProps<HTMLElement> {
163
169
  * </Markdown>
164
170
  * ```
165
171
  */
166
- export declare function Markdown({ ref, children, display, density, headingLevelStart, isStreaming, onLinkClick, sources, citationStyle, contentWidth, contentAlign, components, inlinePlugins, autolink, xstyle, className, style, 'data-testid': testId, ...props }: MarkdownProps): React.ReactElement;
172
+ export declare function Markdown<const Plugins extends ReadonlyArray<MarkdownPluginEntry> = readonly []>({ ref, children, display, density, headingLevelStart, isStreaming, onLinkClick, sources, citationStyle, contentWidth, contentAlign, components, plugins, inlinePlugins, autolink, xstyle, className, style, 'data-testid': testId, ...props }: MarkdownProps<Plugins>): React.ReactElement;
167
173
  export declare namespace Markdown {
168
174
  var displayName: string;
169
175
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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"}
@@ -4,11 +4,11 @@
4
4
 
5
5
  /**
6
6
  * @file Markdown.tsx
7
- * @input Markdown string, parser AST types, optional custom renderers
7
+ * @input Markdown string, canonical AST, optional plugins and custom renderers
8
8
  * @output Exports Markdown component, MarkdownProps, and renderer contracts
9
9
  * @position Core implementation; renders markdown as Astryx components
10
10
  */
11
- import { useMemo, useRef } from 'react';
11
+ import { Component, Suspense, useMemo, useRef } from 'react';
12
12
  import { Fragment } from 'react';
13
13
  import * as stylex from '@stylexjs/stylex';
14
14
  import "../theme/tokens.stylex.js";
@@ -33,6 +33,8 @@ import { Citation } from "../Citation/Citation.js";
33
33
  import { useLinkComponent } from "../Link/useLinkComponent.js";
34
34
  import { parseInlineAst, parseMarkdownAst, parseMarkdownAstIncremental, createIncrementalState, trimStreamingArtifacts, slugify, uniqueSlug } from "./parser.js";
35
35
  import { markdownAstText } from "./ast.js";
36
+ import { applyMarkdownTransforms, getMarkdownExtensionRenderer, markdownExtensionText, prepareMarkdownPlugins, reportMarkdownPluginFailure } from "./plugins/protocol.js";
37
+ import { sanitizeMarkdownUrl } from "./url.js";
36
38
  import { themeProps } from "../utils/themeProps.js";
37
39
  import { useTranslator } from "../i18n/index.js";
38
40
 
@@ -355,6 +357,9 @@ function countInlineTextLength(nodes) {
355
357
  case 'citation':
356
358
  len += 1;
357
359
  break;
360
+ case 'extension':
361
+ len += node.source?.length ?? 0;
362
+ break;
358
363
  }
359
364
  }
360
365
  return len;
@@ -392,6 +397,9 @@ function countBlockTextLength(nodes) {
392
397
  }
393
398
  }
394
399
  break;
400
+ case 'extension':
401
+ len += node.source?.length ?? 0;
402
+ break;
395
403
  case 'thematicBreak':
396
404
  break;
397
405
  case 'image':
@@ -411,26 +419,6 @@ const headingStyles = {
411
419
  };
412
420
 
413
421
  // ---------------------------------------------------------------------------
414
- // URL sanitization — block dangerous protocols
415
- // ---------------------------------------------------------------------------
416
-
417
- const DANGEROUS_URL_PATTERN = /^(javascript|data|vbscript):/i;
418
- function sanitizeUrl(url) {
419
- // Strip control characters before testing, the same normalization the
420
- // parser's isSafeUrl applies — the anchored pattern must see the URL the
421
- // way a browser will. Return the normalized value so the stripped
422
- // characters don't ride along into an attribute or component override.
423
- // eslint-disable-next-line no-control-regex -- control chars are the bypass
424
- const normalized = url.replace(/[\x00-\x1f\x7f]/g, '').trim();
425
- if (normalized.length === 0) {
426
- return null;
427
- }
428
- if (DANGEROUS_URL_PATTERN.test(normalized)) {
429
- return null;
430
- }
431
- return normalized;
432
- }
433
-
434
422
  // ---------------------------------------------------------------------------
435
423
  // Inline plugin matching
436
424
  // ---------------------------------------------------------------------------
@@ -522,6 +510,42 @@ function applyInlinePlugins(text, plugins) {
522
510
  }
523
511
  return segments;
524
512
  }
513
+ class MarkdownPluginBoundary extends Component {
514
+ state = {
515
+ failed: false,
516
+ resetKey: this.props.resetKey,
517
+ resetRenderer: this.props.resetRenderer
518
+ };
519
+ static getDerivedStateFromError() {
520
+ return {
521
+ failed: true
522
+ };
523
+ }
524
+ static getDerivedStateFromProps(props, state) {
525
+ return props.resetKey === state.resetKey && props.resetRenderer === state.resetRenderer ? null : {
526
+ failed: false,
527
+ resetKey: props.resetKey,
528
+ resetRenderer: props.resetRenderer
529
+ };
530
+ }
531
+ componentDidCatch(error) {
532
+ reportMarkdownPluginFailure(this.props.pluginName, 'render', error);
533
+ }
534
+ render() {
535
+ return this.state.failed ? this.props.fallback : this.props.children;
536
+ }
537
+ }
538
+ function useStableMarkdownSyntaxEntries(plugins) {
539
+ const identity = plugins?.syntaxIdentity ?? '';
540
+ const syntaxEntriesRef = useRef(undefined);
541
+ if (syntaxEntriesRef.current == null || syntaxEntriesRef.current.identity !== identity) {
542
+ syntaxEntriesRef.current = {
543
+ identity,
544
+ entries: plugins == null || identity === '' ? undefined : plugins.syntaxEntries
545
+ };
546
+ }
547
+ return syntaxEntriesRef.current.entries;
548
+ }
525
549
 
526
550
  // ---------------------------------------------------------------------------
527
551
  // Inline renderer
@@ -569,7 +593,7 @@ function getCitationNumber(ctx, sourceId) {
569
593
  }
570
594
  return num;
571
595
  }
572
- function renderInline(node, index, onLinkClick, cursor, citationCtx, linkComponent = 'a', inlinePlugins, components) {
596
+ function renderInline(node, index, onLinkClick, cursor, citationCtx, linkComponent = 'a', inlinePlugins, components, preparedPlugins) {
573
597
  switch (node.type) {
574
598
  case 'text':
575
599
  {
@@ -604,18 +628,18 @@ function renderInline(node, index, onLinkClick, cursor, citationCtx, linkCompone
604
628
  ...{
605
629
  className: "x2mo6ok"
606
630
  },
607
- children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
631
+ children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
608
632
  }, index);
609
633
  case 'emphasis':
610
634
  return /*#__PURE__*/_jsx("em", {
611
- children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
635
+ children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
612
636
  }, index);
613
637
  case 'delete':
614
638
  return /*#__PURE__*/_jsx("del", {
615
639
  ...{
616
640
  className: "xv1l7n4"
617
641
  },
618
- children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
642
+ children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
619
643
  }, index);
620
644
  case 'inlineCode':
621
645
  {
@@ -643,18 +667,18 @@ function renderInline(node, index, onLinkClick, cursor, citationCtx, linkCompone
643
667
  }
644
668
  case 'link':
645
669
  {
646
- const safeHref = sanitizeUrl(node.url);
670
+ const safeHref = sanitizeMarkdownUrl(node.url);
647
671
  if (safeHref == null) {
648
672
  // Unsafe URL — render as plain text
649
673
  return /*#__PURE__*/_jsx("span", {
650
- children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
674
+ children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
651
675
  }, index);
652
676
  }
653
677
  const LinkComp = components?.link;
654
678
  if (LinkComp) {
655
679
  return /*#__PURE__*/_jsx(LinkComp, {
656
680
  href: safeHref,
657
- children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
681
+ children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
658
682
  }, index);
659
683
  }
660
684
  const isExternal = safeHref.startsWith('https://') || safeHref.startsWith('http://');
@@ -678,12 +702,12 @@ function renderInline(node, index, onLinkClick, cursor, citationCtx, linkCompone
678
702
  ...{
679
703
  className: "xjse4m1 x1bvjpef"
680
704
  },
681
- children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
705
+ children: node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
682
706
  }, index);
683
707
  }
684
708
  case 'image':
685
709
  {
686
- const safeSrc = sanitizeUrl(node.url);
710
+ const safeSrc = sanitizeMarkdownUrl(node.url);
687
711
  if (safeSrc == null) {
688
712
  return /*#__PURE__*/_jsxs("span", {
689
713
  children: ["[", node.alt, "]"]
@@ -704,6 +728,33 @@ function renderInline(node, index, onLinkClick, cursor, citationCtx, linkCompone
704
728
  }
705
729
  }, index);
706
730
  }
731
+ case 'extension':
732
+ {
733
+ const renderer = getMarkdownExtensionRenderer(preparedPlugins, node);
734
+ const fallback = wrapTextWithFade(node.source ?? markdownExtensionText(preparedPlugins, node), cursor, index);
735
+ if (renderer == null) {
736
+ return fallback;
737
+ }
738
+ let rendered;
739
+ try {
740
+ rendered = renderer.render({
741
+ node
742
+ });
743
+ } catch (error) {
744
+ reportMarkdownPluginFailure(node.plugin, 'render', error);
745
+ return fallback;
746
+ }
747
+ return /*#__PURE__*/_jsx(MarkdownPluginBoundary, {
748
+ pluginName: node.plugin,
749
+ resetKey: node,
750
+ resetRenderer: renderer.render,
751
+ fallback: fallback,
752
+ children: /*#__PURE__*/_jsx(Suspense, {
753
+ fallback: fallback,
754
+ children: rendered
755
+ })
756
+ }, index);
757
+ }
707
758
  case 'break':
708
759
  cursor.offset += 1;
709
760
  return /*#__PURE__*/_jsx("br", {}, index);
@@ -756,6 +807,8 @@ function getElementSpacing(node, density) {
756
807
  return compact ? styles.spacingListCompact : styles.spacingListDefault;
757
808
  case 'table':
758
809
  return compact ? styles.spacingTableCompact : styles.spacingTableDefault;
810
+ case 'extension':
811
+ return compact ? styles.spacingParagraphCompact : styles.spacingParagraphDefault;
759
812
  case 'thematicBreak':
760
813
  return compact ? styles.spacingHrCompact : styles.spacingHrDefault;
761
814
  case 'image':
@@ -790,7 +843,7 @@ function computeTableColumnMinWidths(node) {
790
843
  return maxLen <= 6 ? 60 : maxLen <= 15 ? 80 : 120;
791
844
  });
792
845
  }
793
- function renderBlock(node, index, blockCount, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent = 'a', inlinePlugins, components, t, headingIdMap) {
846
+ function renderBlock(node, index, blockCount, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent = 'a', inlinePlugins, components, preparedPlugins, t, headingIdMap) {
794
847
  const blockAlignMargin = BLOCK_ALIGN_MARGIN[contentAlign];
795
848
  const blockAlignStyle = blockAlignMargin != null ? dynamicStyles.blockAlign(blockAlignMargin) : null;
796
849
  const spacing = getElementSpacing(node, density);
@@ -800,7 +853,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
800
853
  case 'heading':
801
854
  {
802
855
  const level = Math.min(node.depth + headingLevelStart - 1, 6);
803
- const headingChildren = node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components));
856
+ const headingChildren = node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins));
804
857
  // Only top-level headings get an id: the map is built from the same
805
858
  // traversal parseOutlineFromMarkdown uses (which skips headings nested
806
859
  // in blockquotes / list items), so rendered ids and outline ids stay
@@ -826,7 +879,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
826
879
  }
827
880
  case 'paragraph':
828
881
  {
829
- const paraChildren = node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components));
882
+ const paraChildren = node.children.map((c, i) => renderInline(c, i, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins));
830
883
  const ParagraphComp = components?.paragraph;
831
884
  if (ParagraphComp) {
832
885
  return /*#__PURE__*/_jsx(ParagraphComp, {
@@ -892,7 +945,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
892
945
  {
893
946
  const BlockquoteComp = components?.blockquote;
894
947
  if (BlockquoteComp) {
895
- const bqC = node.children.map((c, i) => renderBlock(c, i, node.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, t));
948
+ const bqC = node.children.map((c, i) => renderBlock(c, i, node.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, preparedPlugins, t));
896
949
  return /*#__PURE__*/_jsx(BlockquoteComp, {
897
950
  children: bqC
898
951
  }, index);
@@ -902,7 +955,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
902
955
  density
903
956
  }),
904
957
  xstyle: [spacing, contentWidthValue != null ? dynamicStyles.proseWidth(contentWidthValue) : undefined, contentAlign !== 'start' ? dynamicStyles.proseAlign(ALIGN_MARGIN[contentAlign]) : undefined, isFirst && styles.noMarginBlockStart, isLast && styles.noMarginBlockEnd],
905
- children: node.children.map((c, i) => renderBlock(c, i, node.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, t))
958
+ children: node.children.map((c, i) => renderBlock(c, i, node.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, preparedPlugins, t))
906
959
  }, index);
907
960
  }
908
961
  case 'list':
@@ -934,9 +987,9 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
934
987
  const firstChild = item.children[0];
935
988
  const isInline = item.children.length === 1 && firstChild?.type === 'paragraph';
936
989
  const label = isInline ? /*#__PURE__*/_jsx(_Fragment, {
937
- children: firstChild.children.map((c, j) => renderInline(c, j, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
990
+ children: firstChild.children.map((c, j) => renderInline(c, j, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
938
991
  }) : /*#__PURE__*/_jsx(_Fragment, {
939
- children: item.children.map((c, j) => renderBlock(c, j, item.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, t))
992
+ children: item.children.map((c, j) => renderBlock(c, j, item.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, preparedPlugins, t))
940
993
  });
941
994
  return /*#__PURE__*/_jsx(CheckboxListItem
942
995
  // eslint-disable-next-line @eslint-react/no-array-index-key -- markdown task items are rendered from positional AST nodes
@@ -965,9 +1018,9 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
965
1018
  // whole item as a block instead of fading individual text spans.
966
1019
 
967
1020
  const label = isInline ? /*#__PURE__*/_jsx(_Fragment, {
968
- children: firstChild.children.map((c, j) => renderInline(c, j, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
1021
+ children: firstChild.children.map((c, j) => renderInline(c, j, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
969
1022
  }) : /*#__PURE__*/_jsx(_Fragment, {
970
- children: item.children.map((c, j) => renderBlock(c, j, item.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, t))
1023
+ children: item.children.map((c, j) => renderBlock(c, j, item.children.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidthValue, contentAlign, linkComponent, inlinePlugins, components, preparedPlugins, t))
971
1024
  });
972
1025
  return /*#__PURE__*/_jsx(ListItem
973
1026
  // eslint-disable-next-line @eslint-react/no-array-index-key -- markdown list items are rendered from positional AST nodes
@@ -1002,7 +1055,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
1002
1055
  // eslint-disable-next-line @eslint-react/no-array-index-key -- markdown table columns are positional by definition
1003
1056
  , {
1004
1057
  xstyle: [dynamicStyles.cellMinWidth(`${colMinWidths[i]}px`), node.align[i] === 'center' && cellAlignStyles.center, node.align[i] === 'right' && cellAlignStyles.end],
1005
- children: h.children.map((c, j) => renderInline(c, j, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
1058
+ children: h.children.map((c, j) => renderInline(c, j, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
1006
1059
  }, i))
1007
1060
  })
1008
1061
  }), /*#__PURE__*/_jsx(TableBody, {
@@ -1011,7 +1064,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
1011
1064
  // eslint-disable-next-line @eslint-react/no-array-index-key -- markdown table cells are positional by row and column
1012
1065
  , {
1013
1066
  xstyle: [node.align[j] === 'center' && cellAlignStyles.center, node.align[j] === 'right' && cellAlignStyles.end],
1014
- children: cell.children.map((c, k) => renderInline(c, k, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components))
1067
+ children: cell.children.map((c, k) => renderInline(c, k, onLinkClick, cursor, citationCtx, linkComponent, inlinePlugins, components, preparedPlugins))
1015
1068
  }, j));
1016
1069
  return /*#__PURE__*/_jsx(TableRow
1017
1070
  // eslint-disable-next-line @eslint-react/no-array-index-key -- markdown table rows are rendered from positional AST nodes
@@ -1023,6 +1076,36 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
1023
1076
  })
1024
1077
  }, index);
1025
1078
  }
1079
+ case 'extension':
1080
+ {
1081
+ const renderer = getMarkdownExtensionRenderer(preparedPlugins, node);
1082
+ const fallbackText = node.source ?? markdownExtensionText(preparedPlugins, node);
1083
+ const fallback = wrapTextWithFade(fallbackText, cursor, index);
1084
+ let content = fallback;
1085
+ if (renderer != null) {
1086
+ try {
1087
+ const rendered = renderer.render({
1088
+ node
1089
+ });
1090
+ content = /*#__PURE__*/_jsx(MarkdownPluginBoundary, {
1091
+ pluginName: node.plugin,
1092
+ resetKey: node,
1093
+ resetRenderer: renderer.render,
1094
+ fallback: fallback,
1095
+ children: /*#__PURE__*/_jsx(Suspense, {
1096
+ fallback: fallback,
1097
+ children: rendered
1098
+ })
1099
+ });
1100
+ } catch (error) {
1101
+ reportMarkdownPluginFailure(node.plugin, 'render', error);
1102
+ }
1103
+ }
1104
+ return /*#__PURE__*/_jsx("div", {
1105
+ ...stylex.props(spacing, contentWidthValue != null ? dynamicStyles.proseWidth(contentWidthValue) : null, contentAlign !== 'start' ? dynamicStyles.proseAlign(ALIGN_MARGIN[contentAlign]) : null, isFirst && styles.noMarginBlockStart, isLast && styles.noMarginBlockEnd),
1106
+ children: content
1107
+ }, index);
1108
+ }
1026
1109
  case 'thematicBreak':
1027
1110
  {
1028
1111
  const HrComp = components?.hr;
@@ -1037,7 +1120,7 @@ function renderBlock(node, index, blockCount, density, headingLevelStart, onLink
1037
1120
  }
1038
1121
  case 'image':
1039
1122
  {
1040
- const safeSrc = sanitizeUrl(node.url);
1123
+ const safeSrc = sanitizeMarkdownUrl(node.url);
1041
1124
  if (safeSrc == null) {
1042
1125
  return /*#__PURE__*/_jsxs("div", {
1043
1126
  ...mergeProps(themeProps('markdown-image', {
@@ -1097,6 +1180,7 @@ export function Markdown({
1097
1180
  contentWidth = 680,
1098
1181
  contentAlign = 'start',
1099
1182
  components,
1183
+ plugins,
1100
1184
  inlinePlugins,
1101
1185
  autolink,
1102
1186
  xstyle,
@@ -1109,16 +1193,30 @@ export function Markdown({
1109
1193
  const LinkComponent = useLinkComponent();
1110
1194
  // Derive the set of source IDs for the parser (stable across renders when sources don't change)
1111
1195
  const sourceIds = useMemo(() => sources ? new Set(Object.keys(sources)) : undefined, [sources]);
1196
+ const preparedPlugins = useMemo(() => {
1197
+ if (plugins == null) {
1198
+ return undefined;
1199
+ }
1200
+ try {
1201
+ return prepareMarkdownPlugins(plugins);
1202
+ } catch (error) {
1203
+ reportMarkdownPluginFailure('configuration', 'transform', error);
1204
+ return undefined;
1205
+ }
1206
+ }, [plugins]);
1207
+ const syntaxPlugins = useStableMarkdownSyntaxEntries(preparedPlugins);
1112
1208
  const hasMathRenderer = components?.math != null;
1113
1209
  const legacyParseOptions = useMemo(() => ({
1114
1210
  sourceIds,
1115
- autolink
1116
- }), [sourceIds, autolink]);
1211
+ autolink,
1212
+ plugins: syntaxPlugins
1213
+ }), [sourceIds, autolink, syntaxPlugins]);
1117
1214
  const mathParseOptions = useMemo(() => ({
1118
1215
  sourceIds,
1119
1216
  autolink,
1120
- math: true
1121
- }), [sourceIds, autolink]);
1217
+ math: true,
1218
+ plugins: syntaxPlugins
1219
+ }), [sourceIds, autolink, syntaxPlugins]);
1122
1220
 
1123
1221
  // Smooth bursty streamed chunks into a steady character-by-character reveal.
1124
1222
  // When not streaming, the hook returns children unchanged (no-op).
@@ -1133,7 +1231,7 @@ export function Markdown({
1133
1231
  prevAutolinkRef.current = autolink;
1134
1232
  prevMathRef.current = hasMathRenderer;
1135
1233
  }
1136
- const blocks = useMemo(() => {
1234
+ const parsedBlocks = useMemo(() => {
1137
1235
  if (display === 'inline') {
1138
1236
  return [];
1139
1237
  }
@@ -1148,6 +1246,11 @@ export function Markdown({
1148
1246
  }
1149
1247
  return (hasMathRenderer ? parseMarkdownAst(children, mathParseOptions) : parseMarkdownAst(children, legacyParseOptions)).children;
1150
1248
  }, [display, smoothedText, children, isStreaming, hasMathRenderer, mathParseOptions, legacyParseOptions]);
1249
+ const transformSource = isStreaming ? trimStreamingArtifacts(smoothedText, hasMathRenderer ? mathParseOptions : legacyParseOptions) : children;
1250
+ const blocks = useMemo(() => applyMarkdownTransforms({
1251
+ type: 'root',
1252
+ children: parsedBlocks
1253
+ }, preparedPlugins, transformSource, !isStreaming, 'block').children, [parsedBlocks, preparedPlugins, transformSource, isStreaming]);
1151
1254
 
1152
1255
  // Assign each top-level heading the slug that parseOutlineFromMarkdown
1153
1256
  // would derive for it, so Outline hash links built from the same source
@@ -1163,13 +1266,13 @@ export function Markdown({
1163
1266
  const counts = new Map();
1164
1267
  for (const block of blocks) {
1165
1268
  if (block.type === 'heading') {
1166
- const label = markdownAstText(block.children).trim();
1269
+ const label = markdownAstText(block.children, node => markdownExtensionText(preparedPlugins, node)).trim();
1167
1270
  map.set(block, uniqueSlug(slugify(label), counts));
1168
1271
  }
1169
1272
  }
1170
1273
  return map;
1171
- }, [display, blocks]);
1172
- const inlineNodes = useMemo(() => {
1274
+ }, [display, blocks, preparedPlugins]);
1275
+ const parsedInlineNodes = useMemo(() => {
1173
1276
  if (display !== 'inline') {
1174
1277
  return [];
1175
1278
  }
@@ -1177,6 +1280,21 @@ export function Markdown({
1177
1280
  const input = isStreaming ? trimStreamingArtifacts(smoothedText, options) : children;
1178
1281
  return hasMathRenderer ? parseInlineAst(input, mathParseOptions) : parseInlineAst(input, legacyParseOptions);
1179
1282
  }, [display, smoothedText, children, isStreaming, hasMathRenderer, mathParseOptions, legacyParseOptions]);
1283
+ const inlineTransformSource = isStreaming ? trimStreamingArtifacts(smoothedText, hasMathRenderer ? mathParseOptions : legacyParseOptions) : children;
1284
+ const inlineNodes = useMemo(() => {
1285
+ if (display !== 'inline') {
1286
+ return [];
1287
+ }
1288
+ const transformed = applyMarkdownTransforms({
1289
+ type: 'root',
1290
+ children: [{
1291
+ type: 'paragraph',
1292
+ children: parsedInlineNodes
1293
+ }]
1294
+ }, preparedPlugins, inlineTransformSource, !isStreaming, 'inline');
1295
+ const paragraph = transformed.children[0];
1296
+ return paragraph?.type === 'paragraph' ? [...paragraph.children] : parsedInlineNodes;
1297
+ }, [display, parsedInlineNodes, preparedPlugins, inlineTransformSource, isStreaming]);
1180
1298
 
1181
1299
  // Track recent boundaries for stacked fade-in animation.
1182
1300
  // The number of spans needed = ceil(animationDuration / tickInterval).
@@ -1228,7 +1346,7 @@ export function Markdown({
1228
1346
  ...mergeProps(themeProps('markdown', {
1229
1347
  density
1230
1348
  }), stylex.props(styles.root, styles.inlineRoot, xstyle), className, style),
1231
- children: inlineNodes.map((node, i) => renderInline(node, i, onLinkClick, cursor, citationCtx, LinkComponent, inlinePlugins, components))
1349
+ children: inlineNodes.map((node, i) => renderInline(node, i, onLinkClick, cursor, citationCtx, LinkComponent, inlinePlugins, components, preparedPlugins))
1232
1350
  });
1233
1351
 
1234
1352
  // Store current inline nodes for next render's boundary calculation.
@@ -1247,7 +1365,7 @@ export function Markdown({
1247
1365
  ...mergeProps(themeProps('markdown', {
1248
1366
  density
1249
1367
  }), stylex.props(styles.root, xstyle), className, style),
1250
- children: blocks.map((block, i) => renderBlock(block, i, blocks.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidth ? typeof contentWidth === 'number' ? `${contentWidth}px` : contentWidth : null, contentAlign, LinkComponent, inlinePlugins, components, t, headingIdMap))
1368
+ children: blocks.map((block, i) => renderBlock(block, i, blocks.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidth ? typeof contentWidth === 'number' ? `${contentWidth}px` : contentWidth : null, contentAlign, LinkComponent, inlinePlugins, components, preparedPlugins, t, headingIdMap))
1251
1369
  });
1252
1370
 
1253
1371
  // Store current blocks for next render's boundary calculation.
@@ -4,6 +4,9 @@
4
4
  * @output Canonical immutable MDAST-aligned Markdown node types and text projection
5
5
  * @position Internal canonical Markdown tree shared by parsing, rendering, and Outline
6
6
  */
7
+ export type MarkdownAstDataValue = null | boolean | number | string | ReadonlyArray<MarkdownAstDataValue> | {
8
+ readonly [key: string]: MarkdownAstDataValue;
9
+ };
7
10
  export interface MarkdownAstPoint {
8
11
  readonly line?: number;
9
12
  readonly column?: number;
@@ -15,8 +18,9 @@ export interface MarkdownAstPosition {
15
18
  }
16
19
  export interface MarkdownAstNodeBase {
17
20
  readonly position?: MarkdownAstPosition;
21
+ readonly data?: MarkdownAstDataValue;
18
22
  }
19
- export interface MarkdownAstExtensionNode<Plugin extends string = string, Name extends string = string, Data = Readonly<Record<string, unknown>>, Display extends 'inline' | 'block' = 'inline' | 'block'> extends MarkdownAstNodeBase {
23
+ export interface MarkdownAstExtensionNode<Plugin extends string = string, Name extends string = string, Data extends MarkdownAstDataValue = MarkdownAstDataValue, Display extends 'inline' | 'block' = 'inline' | 'block'> extends MarkdownAstNodeBase {
20
24
  readonly type: 'extension';
21
25
  readonly plugin: Plugin;
22
26
  readonly name: Name;
@@ -120,5 +124,34 @@ export interface MarkdownAstRoot<Extension extends MarkdownAstExtensionNode = ne
120
124
  readonly type: 'root';
121
125
  readonly children: ReadonlyArray<MarkdownAstBlockContent<Extension>>;
122
126
  }
123
- export declare function markdownAstText(nodes: ReadonlyArray<MarkdownAstPhrasingContent>): string;
127
+ export interface MarkdownAstNodeMap<Extension extends MarkdownAstExtensionNode = MarkdownAstExtensionNode> {
128
+ readonly root: MarkdownAstRoot<Extension>;
129
+ readonly text: MarkdownAstText;
130
+ readonly strong: MarkdownAstParent<'strong', Extension>;
131
+ readonly emphasis: MarkdownAstParent<'emphasis', Extension>;
132
+ readonly delete: MarkdownAstParent<'delete', Extension>;
133
+ readonly inlineCode: MarkdownAstInlineCode;
134
+ readonly inlineMath: MarkdownAstInlineMath;
135
+ readonly break: MarkdownAstBreak;
136
+ readonly link: MarkdownAstLink<Extension>;
137
+ readonly image: MarkdownAstImage;
138
+ readonly citation: MarkdownAstCitation;
139
+ readonly heading: MarkdownAstHeading<Extension>;
140
+ readonly paragraph: MarkdownAstParagraph<Extension>;
141
+ readonly code: MarkdownAstCode;
142
+ readonly math: MarkdownAstMath;
143
+ readonly blockquote: MarkdownAstBlockquote<Extension>;
144
+ readonly list: MarkdownAstList<Extension>;
145
+ readonly listItem: MarkdownAstListItem<Extension>;
146
+ readonly table: MarkdownAstTable<Extension>;
147
+ readonly tableRow: MarkdownAstTableRow<Extension>;
148
+ readonly tableCell: MarkdownAstTableCell<Extension>;
149
+ readonly thematicBreak: MarkdownAstThematicBreak;
150
+ readonly extension: Extension;
151
+ }
152
+ export type MarkdownAstNode<Extension extends MarkdownAstExtensionNode = MarkdownAstExtensionNode, Type extends keyof MarkdownAstNodeMap<Extension> = keyof MarkdownAstNodeMap<Extension>> = MarkdownAstNodeMap<Extension>[Type];
153
+ export declare function visitMarkdownNodes<Extension extends MarkdownAstExtensionNode, Type extends keyof MarkdownAstNodeMap<Extension>>(root: MarkdownAstRoot<Extension>, type: Type, visitor: (node: MarkdownAstNodeMap<Extension>[Type]) => void): void;
154
+ export declare function markdownAstText<Extension extends MarkdownAstExtensionNode = never>(nodes: ReadonlyArray<MarkdownAstPhrasingContent<Extension>>, extensionText?: (node: Extension & {
155
+ readonly display: 'inline';
156
+ }) => string): string;
124
157
  //# sourceMappingURL=ast.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/Markdown/ast.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/Markdown/ast.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,20 @@
7
7
  * @position Internal canonical Markdown tree shared by parsing, rendering, and Outline
8
8
  */
9
9
 
10
- export function markdownAstText(nodes) {
10
+ export function visitMarkdownNodes(root, type, visitor) {
11
+ const visit = node => {
12
+ if (node.type === type) {
13
+ visitor(node);
14
+ }
15
+ if ('children' in node) {
16
+ for (const child of node.children) {
17
+ visit(child);
18
+ }
19
+ }
20
+ };
21
+ visit(root);
22
+ }
23
+ export function markdownAstText(nodes, extensionText = node => node.source ?? '') {
11
24
  let text = '';
12
25
  for (const node of nodes) {
13
26
  switch (node.type) {
@@ -20,7 +33,7 @@ export function markdownAstText(nodes) {
20
33
  case 'emphasis':
21
34
  case 'delete':
22
35
  case 'link':
23
- text += markdownAstText(node.children);
36
+ text += markdownAstText(node.children, extensionText);
24
37
  break;
25
38
  case 'image':
26
39
  text += node.alt;
@@ -28,6 +41,9 @@ export function markdownAstText(nodes) {
28
41
  case 'citation':
29
42
  case 'break':
30
43
  break;
44
+ case 'extension':
45
+ text += extensionText(node);
46
+ break;
31
47
  default:
32
48
  {
33
49
  node;