@readme/markdown 11.12.0 → 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 +421 -107
- package/dist/main.node.js +421 -107
- package/dist/main.node.js.map +1 -1
- package/dist/processor/transform/mdxish/mdxish-component-blocks.d.ts +63 -0
- package/dist/processor/transform/mdxish/mdxish-mermaid.d.ts +8 -0
- package/dist/processor/transform/mdxish/retain-boolean-attributes.d.ts +9 -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}
|