@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.
- package/dist/Markdown/Markdown.d.ts +8 -2
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +171 -53
- package/dist/Markdown/ast.d.ts +35 -2
- package/dist/Markdown/ast.d.ts.map +1 -1
- package/dist/Markdown/ast.js +18 -2
- package/dist/Markdown/index.d.ts +3 -1
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/index.js +1 -0
- package/dist/Markdown/parser.d.ts +99 -52
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +274 -65
- package/dist/Markdown/plugins/index.d.ts +8 -0
- package/dist/Markdown/plugins/index.d.ts.map +1 -0
- package/dist/Markdown/plugins/index.js +9 -0
- package/dist/Markdown/plugins/protocol.d.ts +135 -0
- package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
- package/dist/Markdown/plugins/protocol.js +551 -0
- package/dist/Markdown/url.d.ts +4 -0
- package/dist/Markdown/url.d.ts.map +1 -0
- package/dist/Markdown/url.js +25 -0
- package/dist/Markdown/utils.d.ts +4 -2
- package/dist/Markdown/utils.d.ts.map +1 -1
- package/dist/Markdown/utils.js +2 -1
- package/dist/Outline/index.d.ts +1 -0
- package/dist/Outline/index.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +9 -3
- package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
- package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/useOutlineFromMarkdown.js +8 -3
- package/package.json +8 -3
- package/src/Markdown/Markdown.doc.mjs +53 -0
- package/src/Markdown/Markdown.public.test.ts +54 -3
- package/src/Markdown/Markdown.tsx +296 -55
- package/src/Markdown/ast.ts +76 -4
- package/src/Markdown/index.ts +34 -0
- package/src/Markdown/parser.ts +610 -167
- package/src/Markdown/plugins/index.ts +27 -0
- package/src/Markdown/plugins/protocol.test.tsx +955 -0
- package/src/Markdown/plugins/protocol.ts +1065 -0
- package/src/Markdown/url.ts +30 -0
- package/src/Markdown/utils.ts +13 -1
- package/src/Outline/Outline.doc.mjs +7 -5
- package/src/Outline/index.ts +1 -0
- package/src/Outline/parseOutlineFromMarkdown.ts +34 -3
- 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":"AAYA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAgBhD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
1211
|
+
autolink,
|
|
1212
|
+
plugins: syntaxPlugins
|
|
1213
|
+
}), [sourceIds, autolink, syntaxPlugins]);
|
|
1117
1214
|
const mathParseOptions = useMemo(() => ({
|
|
1118
1215
|
sourceIds,
|
|
1119
1216
|
autolink,
|
|
1120
|
-
math: true
|
|
1121
|
-
|
|
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
|
|
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
|
|
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.
|
package/dist/Markdown/ast.d.ts
CHANGED
|
@@ -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 =
|
|
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
|
|
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":"AAEA;;;;;GAKG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/Markdown/ast.ts"],"names":[],"mappings":"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"}
|
package/dist/Markdown/ast.js
CHANGED
|
@@ -7,7 +7,20 @@
|
|
|
7
7
|
* @position Internal canonical Markdown tree shared by parsing, rendering, and Outline
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
export function
|
|
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;
|