@readme/markdown 11.12.1 → 11.13.0
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/components/Anchor.tsx +10 -1
- package/components/Code/index.tsx +3 -2
- package/components/CodeTabs/index.tsx +31 -12
- package/dist/index.d.ts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/mdxish.d.ts +15 -1
- package/dist/main.js +144 -34
- package/dist/main.node.js +144 -34
- package/dist/main.node.js.map +1 -1
- package/dist/processor/transform/mdxish/mdxish-mermaid.d.ts +8 -0
- package/package.json +1 -1
package/components/Anchor.tsx
CHANGED
|
@@ -59,10 +59,19 @@ function Anchor(props: Props) {
|
|
|
59
59
|
const { children, href = '', target = '', title = '', ...attrs } = props;
|
|
60
60
|
const baseUrl: string = useContext(BaseUrlContext);
|
|
61
61
|
|
|
62
|
+
// Unwrap any nested anchor elements that GFM's autolinker may have created.
|
|
63
|
+
// This prevents invalid nested <a> tags when the Anchor's text content looks like a URL.
|
|
64
|
+
const unwrappedChildren = React.Children.map(children, child => {
|
|
65
|
+
if (React.isValidElement(child) && child.type === 'a') {
|
|
66
|
+
return child.props.children;
|
|
67
|
+
}
|
|
68
|
+
return child;
|
|
69
|
+
});
|
|
70
|
+
|
|
62
71
|
return (
|
|
63
72
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
64
73
|
<a {...attrs} href={getHref(href, baseUrl)} target={target} title={title} {...docLink(href)}>
|
|
65
|
-
{
|
|
74
|
+
{unwrappedChildren}
|
|
66
75
|
</a>
|
|
67
76
|
);
|
|
68
77
|
}
|
|
@@ -61,7 +61,8 @@ const Code = (props: CodeProps) => {
|
|
|
61
61
|
const copyButtons = useContext(CodeOptsContext) || props.copyButtons;
|
|
62
62
|
const isHydrated = useHydrated();
|
|
63
63
|
|
|
64
|
-
const language =
|
|
64
|
+
const language = canonicalLanguage(lang);
|
|
65
|
+
const isMermaid = language === 'mermaid';
|
|
65
66
|
|
|
66
67
|
const codeRef = createRef<HTMLElement>();
|
|
67
68
|
|
|
@@ -78,7 +79,7 @@ const Code = (props: CodeProps) => {
|
|
|
78
79
|
? syntaxHighlighter(code, language, codeOpts, { mdx: true })
|
|
79
80
|
: code;
|
|
80
81
|
|
|
81
|
-
if (
|
|
82
|
+
if (isHydrated && isMermaid) {
|
|
82
83
|
return code;
|
|
83
84
|
}
|
|
84
85
|
|
|
@@ -4,6 +4,7 @@ import syntaxHighlighterUtils from '@readme/syntax-highlighter/utils';
|
|
|
4
4
|
import React, { useContext, useEffect } from 'react';
|
|
5
5
|
|
|
6
6
|
import ThemeContext from '../../contexts/Theme';
|
|
7
|
+
import useHydrated from '../../hooks/useHydrated';
|
|
7
8
|
|
|
8
9
|
let mermaid: Mermaid;
|
|
9
10
|
|
|
@@ -16,11 +17,26 @@ interface Props {
|
|
|
16
17
|
const CodeTabs = (props: Props) => {
|
|
17
18
|
const { children } = props;
|
|
18
19
|
const theme = useContext(ThemeContext);
|
|
19
|
-
const
|
|
20
|
+
const isHydrated = useHydrated();
|
|
20
21
|
|
|
21
|
-
//
|
|
22
|
+
// Handle both array (from rehype-react in rendering mdxish) and single element (MDX/JSX runtime) cases
|
|
23
|
+
// The children here is the individual code block objects
|
|
24
|
+
const childrenArray = Array.isArray(children) ? children : [children];
|
|
25
|
+
|
|
26
|
+
// The structure varies depending on rendering context:
|
|
27
|
+
// - When rendered via rehype-react: pre.props.children is an array where the first element is the Code component
|
|
28
|
+
// - When rendered via MDX/JSX runtime: pre.props.children is directly the Code component
|
|
29
|
+
const getCodeComponent = (pre: JSX.Element) => {
|
|
30
|
+
return Array.isArray(pre?.props?.children) ? pre.props.children[0] : pre?.props?.children;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const containAtLeastOneMermaid = childrenArray.some(pre => getCodeComponent(pre)?.props?.lang === 'mermaid');
|
|
34
|
+
|
|
35
|
+
// Render Mermaid diagram
|
|
22
36
|
useEffect(() => {
|
|
23
|
-
|
|
37
|
+
// Ensure we only render mermaids when frontend is hydrated to avoid hydration errors
|
|
38
|
+
// because mermaid mutates the DOM before react hydrates
|
|
39
|
+
if (typeof window !== 'undefined' && containAtLeastOneMermaid && isHydrated) {
|
|
24
40
|
import('mermaid').then(module => {
|
|
25
41
|
mermaid = module.default;
|
|
26
42
|
mermaid.initialize({
|
|
@@ -32,7 +48,7 @@ const CodeTabs = (props: Props) => {
|
|
|
32
48
|
});
|
|
33
49
|
});
|
|
34
50
|
}
|
|
35
|
-
}, [
|
|
51
|
+
}, [containAtLeastOneMermaid, theme, isHydrated]);
|
|
36
52
|
|
|
37
53
|
function handleClick({ target }, index: number) {
|
|
38
54
|
const $wrap = target.parentElement.parentElement;
|
|
@@ -46,22 +62,25 @@ const CodeTabs = (props: Props) => {
|
|
|
46
62
|
target.classList.add('CodeTabs_active');
|
|
47
63
|
}
|
|
48
64
|
|
|
49
|
-
// render single
|
|
50
|
-
if (
|
|
51
|
-
const
|
|
52
|
-
|
|
65
|
+
// We want to render single mermaid diagrams without the code tabs UI
|
|
66
|
+
if (childrenArray.length === 1) {
|
|
67
|
+
const codeComponent = getCodeComponent(childrenArray[0]);
|
|
68
|
+
if (codeComponent?.props?.lang === 'mermaid') {
|
|
69
|
+
const value = codeComponent?.props?.value;
|
|
70
|
+
return <pre className="mermaid-render mermaid_single">{value}</pre>;
|
|
71
|
+
}
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
return (
|
|
56
75
|
<div className={`CodeTabs CodeTabs_initial theme-${theme}`}>
|
|
57
76
|
<div className="CodeTabs-toolbar">
|
|
58
|
-
{
|
|
77
|
+
{childrenArray.map((pre, i) => {
|
|
59
78
|
// the first or only child should be our Code component
|
|
60
|
-
const
|
|
79
|
+
const tabCodeComponent = Array.isArray(pre.props?.children)
|
|
61
80
|
? pre.props.children[0]
|
|
62
81
|
: pre.props?.children;
|
|
63
|
-
const lang =
|
|
64
|
-
const meta =
|
|
82
|
+
const lang = tabCodeComponent?.props?.lang;
|
|
83
|
+
const meta = tabCodeComponent?.props?.meta;
|
|
65
84
|
|
|
66
85
|
/* istanbul ignore next */
|
|
67
86
|
return (
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare const utils: {
|
|
|
6
6
|
getHref: typeof getHref;
|
|
7
7
|
calloutIcons: {};
|
|
8
8
|
};
|
|
9
|
-
export { compile, exports, hast, run, mdast, mdastV6, mdx, mdxish, mdxishTags, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, } from './lib';
|
|
9
|
+
export { compile, exports, hast, run, mdast, mdastV6, mdx, mdxish, mdxishAstProcessor, mdxishMdastToMd, mdxishTags, migrate, mix, plain, renderMdxish, remarkPlugins, stripComments, tags, } from './lib';
|
|
10
10
|
export { default as Owlmoji } from './lib/owlmoji';
|
|
11
11
|
export { Components, utils };
|
|
12
12
|
export { tailwindCompiler } from './utils/tailwind-compiler';
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { default as mdast } from './mdast';
|
|
|
7
7
|
export { default as mdastV6 } from './mdastV6';
|
|
8
8
|
export { default as mdx } from './mdx';
|
|
9
9
|
export { default as mix } from './mix';
|
|
10
|
-
export { default as mdxish } from './mdxish';
|
|
10
|
+
export { default as mdxish, mdxishAstProcessor, mdxishMdastToMd } from './mdxish';
|
|
11
11
|
export type { MdxishOpts } from './mdxish';
|
|
12
12
|
export { default as migrate } from './migrate';
|
|
13
13
|
export { default as plain } from './plain';
|
package/dist/lib/mdxish.d.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import type { CustomComponents } from '../types';
|
|
2
2
|
import type { Root } from 'hast';
|
|
3
|
+
import type { Root as MdastRoot } from 'mdast';
|
|
3
4
|
import { type JSXContext } from '../processor/transform/mdxish/preprocess-jsx-expressions';
|
|
4
5
|
export interface MdxishOpts {
|
|
5
6
|
components?: CustomComponents;
|
|
6
7
|
jsxContext?: JSXContext;
|
|
7
8
|
useTailwind?: boolean;
|
|
8
9
|
}
|
|
10
|
+
export declare function mdxishAstProcessor(mdContent: string, opts?: MdxishOpts): {
|
|
11
|
+
processor: import("unified").Processor<MdastRoot, import("unist").Node, import("unist").Node, undefined, undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* @todo we need to return this transformed content for now
|
|
14
|
+
* but ultimately need to properly tokenize our special markdown syntax
|
|
15
|
+
* into hast nodes instead of relying on transformed content
|
|
16
|
+
*/
|
|
17
|
+
parserReadyContent: string;
|
|
18
|
+
};
|
|
9
19
|
/**
|
|
10
|
-
*
|
|
20
|
+
* Converts an Mdast to a Markdown string.
|
|
21
|
+
*/
|
|
22
|
+
export declare function mdxishMdastToMd(mdast: MdastRoot): string;
|
|
23
|
+
/**
|
|
24
|
+
* Processes markdown content with MDX syntax support and returns a HAST.
|
|
11
25
|
* Detects and renders custom component tags from the components hash.
|
|
12
26
|
*
|
|
13
27
|
* @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
|
package/dist/main.js
CHANGED
|
@@ -11366,6 +11366,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
11366
11366
|
mdastV6: () => (/* reexport */ lib_mdastV6),
|
|
11367
11367
|
mdx: () => (/* reexport */ lib_mdx),
|
|
11368
11368
|
mdxish: () => (/* reexport */ lib_mdxish),
|
|
11369
|
+
mdxishAstProcessor: () => (/* reexport */ mdxishAstProcessor),
|
|
11370
|
+
mdxishMdastToMd: () => (/* reexport */ mdxishMdastToMd),
|
|
11369
11371
|
mdxishTags: () => (/* reexport */ mdxishTags),
|
|
11370
11372
|
migrate: () => (/* reexport */ lib_migrate),
|
|
11371
11373
|
mix: () => (/* reexport */ lib_mix),
|
|
@@ -11513,9 +11515,17 @@ function docLink(href) {
|
|
|
11513
11515
|
function Anchor(props) {
|
|
11514
11516
|
const { children, href = '', target = '', title = '', ...attrs } = props;
|
|
11515
11517
|
const baseUrl = (0,external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.useContext)(BaseUrl);
|
|
11518
|
+
// Unwrap any nested anchor elements that GFM's autolinker may have created.
|
|
11519
|
+
// This prevents invalid nested <a> tags when the Anchor's text content looks like a URL.
|
|
11520
|
+
const unwrappedChildren = external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().Children.map(children, child => {
|
|
11521
|
+
if (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().isValidElement(child) && child.type === 'a') {
|
|
11522
|
+
return child.props.children;
|
|
11523
|
+
}
|
|
11524
|
+
return child;
|
|
11525
|
+
});
|
|
11516
11526
|
return (
|
|
11517
11527
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
11518
|
-
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("a", { ...attrs, href: getHref(href, baseUrl), target: target, title: title, ...docLink(href) },
|
|
11528
|
+
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("a", { ...attrs, href: getHref(href, baseUrl), target: target, title: title, ...docLink(href) }, unwrappedChildren));
|
|
11519
11529
|
}
|
|
11520
11530
|
/* harmony default export */ const components_Anchor = (Anchor);
|
|
11521
11531
|
|
|
@@ -11653,7 +11663,8 @@ const Code = (props) => {
|
|
|
11653
11663
|
const theme = (0,external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.useContext)(Theme);
|
|
11654
11664
|
const copyButtons = (0,external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.useContext)(CodeOpts) || props.copyButtons;
|
|
11655
11665
|
const isHydrated = useHydrated();
|
|
11656
|
-
const language =
|
|
11666
|
+
const language = canonicalLanguage(lang);
|
|
11667
|
+
const isMermaid = language === 'mermaid';
|
|
11657
11668
|
const codeRef = (0,external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.createRef)();
|
|
11658
11669
|
const codeOpts = {
|
|
11659
11670
|
inline: !lang,
|
|
@@ -11664,7 +11675,7 @@ const Code = (props) => {
|
|
|
11664
11675
|
const highlightedCode = syntaxHighlighter && typeof syntaxHighlighter === 'function' && code && isHydrated
|
|
11665
11676
|
? syntaxHighlighter(code, language, codeOpts, { mdx: true })
|
|
11666
11677
|
: code;
|
|
11667
|
-
if (
|
|
11678
|
+
if (isHydrated && isMermaid) {
|
|
11668
11679
|
return code;
|
|
11669
11680
|
}
|
|
11670
11681
|
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement((external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default()).Fragment, null,
|
|
@@ -11680,15 +11691,28 @@ var dist_utils_default = /*#__PURE__*/__webpack_require__.n(dist_utils);
|
|
|
11680
11691
|
|
|
11681
11692
|
|
|
11682
11693
|
|
|
11694
|
+
|
|
11683
11695
|
let mermaid;
|
|
11684
11696
|
const { uppercase } = (dist_utils_default());
|
|
11685
11697
|
const CodeTabs = (props) => {
|
|
11686
11698
|
const { children } = props;
|
|
11687
11699
|
const theme = (0,external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.useContext)(Theme);
|
|
11688
|
-
const
|
|
11689
|
-
//
|
|
11700
|
+
const isHydrated = useHydrated();
|
|
11701
|
+
// Handle both array (from rehype-react in rendering mdxish) and single element (MDX/JSX runtime) cases
|
|
11702
|
+
// The children here is the individual code block objects
|
|
11703
|
+
const childrenArray = Array.isArray(children) ? children : [children];
|
|
11704
|
+
// The structure varies depending on rendering context:
|
|
11705
|
+
// - When rendered via rehype-react: pre.props.children is an array where the first element is the Code component
|
|
11706
|
+
// - When rendered via MDX/JSX runtime: pre.props.children is directly the Code component
|
|
11707
|
+
const getCodeComponent = (pre) => {
|
|
11708
|
+
return Array.isArray(pre?.props?.children) ? pre.props.children[0] : pre?.props?.children;
|
|
11709
|
+
};
|
|
11710
|
+
const containAtLeastOneMermaid = childrenArray.some(pre => getCodeComponent(pre)?.props?.lang === 'mermaid');
|
|
11711
|
+
// Render Mermaid diagram
|
|
11690
11712
|
(0,external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_.useEffect)(() => {
|
|
11691
|
-
|
|
11713
|
+
// Ensure we only render mermaids when frontend is hydrated to avoid hydration errors
|
|
11714
|
+
// because mermaid mutates the DOM before react hydrates
|
|
11715
|
+
if (typeof window !== 'undefined' && containAtLeastOneMermaid && isHydrated) {
|
|
11692
11716
|
Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 1387, 23)).then(module => {
|
|
11693
11717
|
mermaid = module.default;
|
|
11694
11718
|
mermaid.initialize({
|
|
@@ -11700,7 +11724,7 @@ const CodeTabs = (props) => {
|
|
|
11700
11724
|
});
|
|
11701
11725
|
});
|
|
11702
11726
|
}
|
|
11703
|
-
}, [
|
|
11727
|
+
}, [containAtLeastOneMermaid, theme, isHydrated]);
|
|
11704
11728
|
function handleClick({ target }, index) {
|
|
11705
11729
|
const $wrap = target.parentElement.parentElement;
|
|
11706
11730
|
const $open = [].slice.call($wrap.querySelectorAll('.CodeTabs_active'));
|
|
@@ -11710,19 +11734,22 @@ const CodeTabs = (props) => {
|
|
|
11710
11734
|
codeblocks[index].classList.add('CodeTabs_active');
|
|
11711
11735
|
target.classList.add('CodeTabs_active');
|
|
11712
11736
|
}
|
|
11713
|
-
// render single
|
|
11714
|
-
if (
|
|
11715
|
-
const
|
|
11716
|
-
|
|
11737
|
+
// We want to render single mermaid diagrams without the code tabs UI
|
|
11738
|
+
if (childrenArray.length === 1) {
|
|
11739
|
+
const codeComponent = getCodeComponent(childrenArray[0]);
|
|
11740
|
+
if (codeComponent?.props?.lang === 'mermaid') {
|
|
11741
|
+
const value = codeComponent?.props?.value;
|
|
11742
|
+
return external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("pre", { className: "mermaid-render mermaid_single" }, value);
|
|
11743
|
+
}
|
|
11717
11744
|
}
|
|
11718
11745
|
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("div", { className: `CodeTabs CodeTabs_initial theme-${theme}` },
|
|
11719
|
-
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("div", { className: "CodeTabs-toolbar" },
|
|
11746
|
+
external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("div", { className: "CodeTabs-toolbar" }, childrenArray.map((pre, i) => {
|
|
11720
11747
|
// the first or only child should be our Code component
|
|
11721
|
-
const
|
|
11748
|
+
const tabCodeComponent = Array.isArray(pre.props?.children)
|
|
11722
11749
|
? pre.props.children[0]
|
|
11723
11750
|
: pre.props?.children;
|
|
11724
|
-
const lang =
|
|
11725
|
-
const meta =
|
|
11751
|
+
const lang = tabCodeComponent?.props?.lang;
|
|
11752
|
+
const meta = tabCodeComponent?.props?.meta;
|
|
11726
11753
|
/* istanbul ignore next */
|
|
11727
11754
|
return (external_amd_react_commonjs_react_commonjs2_react_root_React_umd_react_default().createElement("button", { key: i, onClick: e => handleClick(e, i), type: "button", value: lang }, meta || `${!lang ? 'Text' : uppercase(lang)}`));
|
|
11728
11755
|
})),
|
|
@@ -71214,10 +71241,20 @@ const coerceJsxToMd = ({ components = {}, html = false } = {}) => (node, index,
|
|
|
71214
71241
|
hProperties.url = hProperties.href;
|
|
71215
71242
|
delete hProperties.href;
|
|
71216
71243
|
}
|
|
71244
|
+
// Unwrap any autolinked children to prevent nested links.
|
|
71245
|
+
// GFM's autolink feature can convert URL-like text inside Anchor children
|
|
71246
|
+
// into link nodes, which would create invalid nested links when Anchor
|
|
71247
|
+
// is converted back to a link node.
|
|
71248
|
+
const children = node.children.flatMap(child => {
|
|
71249
|
+
if (child.type === 'link') {
|
|
71250
|
+
return child.children;
|
|
71251
|
+
}
|
|
71252
|
+
return child;
|
|
71253
|
+
});
|
|
71217
71254
|
// @ts-expect-error we don't have a mechanism to enforce the URL attribute type right now
|
|
71218
71255
|
const mdNode = {
|
|
71219
71256
|
...hProperties,
|
|
71220
|
-
children
|
|
71257
|
+
children,
|
|
71221
71258
|
type: types[node.name],
|
|
71222
71259
|
position: node.position,
|
|
71223
71260
|
};
|
|
@@ -86506,16 +86543,17 @@ const tocHastToMdx = (toc, components) => {
|
|
|
86506
86543
|
|
|
86507
86544
|
|
|
86508
86545
|
|
|
86509
|
-
const { codeTabsTransformer: compile_codeTabsTransformer, ...transforms } = defaultTransforms;
|
|
86510
86546
|
const sanitizeSchema = cjs_default()(defaultSchema, {
|
|
86511
86547
|
protocols: ['doc', 'ref', 'blog', 'changelog', 'page'],
|
|
86512
86548
|
});
|
|
86513
86549
|
const compile_compile = (text, { components = {}, missingComponents, copyButtons, useTailwind, ...opts } = {}) => {
|
|
86550
|
+
// Destructure at runtime to avoid circular dependency issues
|
|
86551
|
+
const { codeTabsTransformer, ...transforms } = defaultTransforms;
|
|
86514
86552
|
const remarkPlugins = [
|
|
86515
86553
|
remarkFrontmatter,
|
|
86516
86554
|
remarkGfm,
|
|
86517
86555
|
...Object.values(transforms),
|
|
86518
|
-
[
|
|
86556
|
+
[codeTabsTransformer, { copyButtons }],
|
|
86519
86557
|
[
|
|
86520
86558
|
handle_missing_components,
|
|
86521
86559
|
{ components, missingComponents: ['ignore', 'throw'].includes(missingComponents) ? missingComponents : 'ignore' },
|
|
@@ -93793,8 +93831,6 @@ const mdxishHtmlBlocks = () => tree => {
|
|
|
93793
93831
|
* Taken from the v6 branch
|
|
93794
93832
|
*/
|
|
93795
93833
|
const RGXP = /^\s*\[block:([^\]]*)\]([^]+?)\[\/block\]/;
|
|
93796
|
-
/** Parses markdown in table cells */
|
|
93797
|
-
const cellParser = unified().use(remarkParse).use(remarkGfm);
|
|
93798
93834
|
/**
|
|
93799
93835
|
* Wraps a node in a "pinned" container if sidebar: true is set in the JSON.
|
|
93800
93836
|
* Pinned blocks are displayed in a sidebar/floating position in the UI.
|
|
@@ -93828,11 +93864,13 @@ const imgWidthBySize = new Proxy(imgSizeValues, {
|
|
|
93828
93864
|
const textToInline = (text) => [{ type: 'text', value: text }];
|
|
93829
93865
|
// Simple text to block nodes (wraps in paragraph)
|
|
93830
93866
|
const textToBlock = (text) => [{ children: textToInline(text), type: 'paragraph' }];
|
|
93867
|
+
/** Parses markdown and html to markdown nodes */
|
|
93868
|
+
const contentParser = unified().use(remarkParse).use(remarkGfm);
|
|
93831
93869
|
// Table cells may contain html or markdown content, so we need to parse it accordingly instead of keeping it as raw text
|
|
93832
|
-
const
|
|
93870
|
+
const parseTableCell = (text) => {
|
|
93833
93871
|
if (!text.trim())
|
|
93834
93872
|
return [{ type: 'text', value: '' }];
|
|
93835
|
-
const tree =
|
|
93873
|
+
const tree = contentParser.runSync(contentParser.parse(text));
|
|
93836
93874
|
// If there are multiple block-level nodes, keep them as-is to preserve the document structure and spacing
|
|
93837
93875
|
if (tree.children.length > 1) {
|
|
93838
93876
|
return tree.children;
|
|
@@ -93841,6 +93879,13 @@ const parseInline = (text) => {
|
|
|
93841
93879
|
// This unwraps the extra p node that might appear & wrapping the content
|
|
93842
93880
|
n.type === 'paragraph' && 'children' in n ? n.children : [n]);
|
|
93843
93881
|
};
|
|
93882
|
+
// Parse markdown/HTML into block-level nodes (preserves paragraphs, headings, lists, etc.)
|
|
93883
|
+
const parseBlock = (text) => {
|
|
93884
|
+
if (!text.trim())
|
|
93885
|
+
return [{ type: 'paragraph', children: [{ type: 'text', value: '' }] }];
|
|
93886
|
+
const tree = contentParser.runSync(contentParser.parse(text));
|
|
93887
|
+
return tree.children;
|
|
93888
|
+
};
|
|
93844
93889
|
/**
|
|
93845
93890
|
* Parse a magic block string and return MDAST nodes.
|
|
93846
93891
|
*
|
|
@@ -93919,7 +93964,7 @@ function parseMagicBlock(raw, options = {}) {
|
|
|
93919
93964
|
data: {
|
|
93920
93965
|
hProperties: {
|
|
93921
93966
|
...(imgData.align && { align: imgData.align }),
|
|
93922
|
-
|
|
93967
|
+
...(imgData.border && { border: imgData.border.toString() }),
|
|
93923
93968
|
...(imgData.sizing && { width: imgWidthBySize[imgData.sizing] }),
|
|
93924
93969
|
},
|
|
93925
93970
|
},
|
|
@@ -93958,8 +94003,9 @@ function parseMagicBlock(raw, options = {}) {
|
|
|
93958
94003
|
const [icon, theme] = Array.isArray(resolvedType) ? resolvedType : ['👍', 'default'];
|
|
93959
94004
|
if (!(calloutJson.title || calloutJson.body))
|
|
93960
94005
|
return [];
|
|
93961
|
-
|
|
93962
|
-
const
|
|
94006
|
+
// Parses html & markdown content
|
|
94007
|
+
const titleBlocks = parseBlock(calloutJson.title || '');
|
|
94008
|
+
const bodyBlocks = parseBlock(calloutJson.body || '');
|
|
93963
94009
|
const children = [];
|
|
93964
94010
|
if (titleBlocks.length > 0 && titleBlocks[0].type === 'paragraph') {
|
|
93965
94011
|
const firstTitle = titleBlocks[0];
|
|
@@ -94013,7 +94059,7 @@ function parseMagicBlock(raw, options = {}) {
|
|
|
94013
94059
|
return mapped;
|
|
94014
94060
|
}, []);
|
|
94015
94061
|
// In compatibility mode, wrap cell content in paragraphs; otherwise inline text
|
|
94016
|
-
const tokenizeCell = compatibilityMode ? textToBlock :
|
|
94062
|
+
const tokenizeCell = compatibilityMode ? textToBlock : parseTableCell;
|
|
94017
94063
|
const children = Array.from({ length: rows + 1 }, (_, y) => ({
|
|
94018
94064
|
children: Array.from({ length: cols }, (__, x) => ({
|
|
94019
94065
|
children: sparseData[y]?.[x] ? tokenizeCell(sparseData[y][x]) : [{ type: 'text', value: '' }],
|
|
@@ -94147,6 +94193,38 @@ const magicBlockRestorer = ({ blocks }) => tree => {
|
|
|
94147
94193
|
};
|
|
94148
94194
|
/* harmony default export */ const mdxish_magic_blocks = (magicBlockRestorer);
|
|
94149
94195
|
|
|
94196
|
+
;// ./processor/transform/mdxish/mdxish-mermaid.ts
|
|
94197
|
+
|
|
94198
|
+
/**
|
|
94199
|
+
* Rehype plugin for mdxish pipeline to add mermaid-render className to mermaid code blocks.
|
|
94200
|
+
* The mermaid-render class is used to identify the mermaid diagrams elements for the
|
|
94201
|
+
* mermaid library to transform. See components/CodeTabs/index.tsx for context
|
|
94202
|
+
*/
|
|
94203
|
+
const mdxishMermaidTransformer = () => (tree) => {
|
|
94204
|
+
visit(tree, 'element', (node) => {
|
|
94205
|
+
if (node.tagName !== 'pre' || node.children.length !== 1)
|
|
94206
|
+
return;
|
|
94207
|
+
const [child] = node.children;
|
|
94208
|
+
if (child.type === 'element' &&
|
|
94209
|
+
child.tagName === 'code' &&
|
|
94210
|
+
child.properties?.lang === 'mermaid') {
|
|
94211
|
+
// Combine existing className with the new mermaid-render class
|
|
94212
|
+
const existingClassName = node.properties?.className;
|
|
94213
|
+
const classNameArray = Array.isArray(existingClassName)
|
|
94214
|
+
? existingClassName.filter(c => typeof c === 'string' || typeof c === 'number')
|
|
94215
|
+
: existingClassName && (typeof existingClassName === 'string' || typeof existingClassName === 'number')
|
|
94216
|
+
? [existingClassName]
|
|
94217
|
+
: [];
|
|
94218
|
+
node.properties = {
|
|
94219
|
+
...node.properties,
|
|
94220
|
+
className: ['mermaid-render', ...classNameArray],
|
|
94221
|
+
};
|
|
94222
|
+
}
|
|
94223
|
+
});
|
|
94224
|
+
return tree;
|
|
94225
|
+
};
|
|
94226
|
+
/* harmony default export */ const mdxish_mermaid = (mdxishMermaidTransformer);
|
|
94227
|
+
|
|
94150
94228
|
;// ./lib/constants.ts
|
|
94151
94229
|
/**
|
|
94152
94230
|
* Pattern to match component tags (PascalCase or snake_case)
|
|
@@ -94593,18 +94671,15 @@ function loadComponents() {
|
|
|
94593
94671
|
|
|
94594
94672
|
|
|
94595
94673
|
|
|
94674
|
+
|
|
94675
|
+
|
|
94676
|
+
|
|
94596
94677
|
|
|
94597
94678
|
|
|
94598
94679
|
|
|
94599
94680
|
|
|
94600
94681
|
const defaultTransformers = [callouts, code_tabs, gemoji_, transform_embeds];
|
|
94601
|
-
|
|
94602
|
-
* Process markdown content with MDX syntax support.
|
|
94603
|
-
* Detects and renders custom component tags from the components hash.
|
|
94604
|
-
*
|
|
94605
|
-
* @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
|
|
94606
|
-
*/
|
|
94607
|
-
function mdxish(mdContent, opts = {}) {
|
|
94682
|
+
function mdxishAstProcessor(mdContent, opts = {}) {
|
|
94608
94683
|
const { components: userComponents = {}, jsxContext = {}, useTailwind } = opts;
|
|
94609
94684
|
const components = {
|
|
94610
94685
|
...loadComponents(),
|
|
@@ -94639,11 +94714,46 @@ function mdxish(mdContent, opts = {}) {
|
|
|
94639
94714
|
.use(evaluate_expressions, { context: jsxContext }) // Evaluate MDX expressions using jsxContext
|
|
94640
94715
|
.use(variables_text) // Parse {user.*} patterns from text (can't rely on remarkMdx)
|
|
94641
94716
|
.use(useTailwind ? transform_tailwind : undefined, { components: tempComponentsMap })
|
|
94642
|
-
.use(remarkGfm)
|
|
94717
|
+
.use(remarkGfm);
|
|
94718
|
+
return {
|
|
94719
|
+
processor,
|
|
94720
|
+
/**
|
|
94721
|
+
* @todo we need to return this transformed content for now
|
|
94722
|
+
* but ultimately need to properly tokenize our special markdown syntax
|
|
94723
|
+
* into hast nodes instead of relying on transformed content
|
|
94724
|
+
*/
|
|
94725
|
+
parserReadyContent,
|
|
94726
|
+
};
|
|
94727
|
+
}
|
|
94728
|
+
/**
|
|
94729
|
+
* Converts an Mdast to a Markdown string.
|
|
94730
|
+
*/
|
|
94731
|
+
function mdxishMdastToMd(mdast) {
|
|
94732
|
+
const md = unified().use(remarkGfm).use(processor_compile).use(remarkStringify, {
|
|
94733
|
+
bullet: '-',
|
|
94734
|
+
emphasis: '_',
|
|
94735
|
+
}).stringify(mdast);
|
|
94736
|
+
return md;
|
|
94737
|
+
}
|
|
94738
|
+
/**
|
|
94739
|
+
* Processes markdown content with MDX syntax support and returns a HAST.
|
|
94740
|
+
* Detects and renders custom component tags from the components hash.
|
|
94741
|
+
*
|
|
94742
|
+
* @see {@link https://github.com/readmeio/rmdx/blob/main/docs/mdxish-flow.md}
|
|
94743
|
+
*/
|
|
94744
|
+
function mdxish(mdContent, opts = {}) {
|
|
94745
|
+
const { components: userComponents = {} } = opts;
|
|
94746
|
+
const components = {
|
|
94747
|
+
...loadComponents(),
|
|
94748
|
+
...userComponents,
|
|
94749
|
+
};
|
|
94750
|
+
const { processor, parserReadyContent } = mdxishAstProcessor(mdContent, opts);
|
|
94751
|
+
processor
|
|
94643
94752
|
.use(remarkRehype, { allowDangerousHtml: true, handlers: mdxComponentHandlers })
|
|
94644
94753
|
.use(preserveBooleanProperties) // RehypeRaw converts boolean properties to empty strings
|
|
94645
94754
|
.use(rehypeRaw, { passThrough: ['html-block'] })
|
|
94646
94755
|
.use(restoreBooleanProperties)
|
|
94756
|
+
.use(mdxish_mermaid) // Add mermaid-render className to pre wrappers
|
|
94647
94757
|
.use(rehypeSlug)
|
|
94648
94758
|
.use(rehypeMdxishComponents, {
|
|
94649
94759
|
components,
|