Skip to content

Commit

Permalink
✨ feat: markdown 支持自定义组件渲染 (#179)
Browse files Browse the repository at this point in the history
* ✨ feat: markdown support add custom render

* 💚 fix: update snapshot
  • Loading branch information
ONLY-yours authored Apr 19, 2024
1 parent 2090e5f commit 4328b89
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 3 deletions.
27 changes: 27 additions & 0 deletions src/Markdown/demos/renderComponets.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Markdown } from '@ant-design/pro-editor';
import { Button } from 'antd';
import { memo } from 'react';

export default () => {
return (
<Markdown
components={{
a: memo((props) => (
<Button
onClick={() => {
console.log(props.href);
}}
>
该链接不允许点击跳转!{props.href}
</Button>
)),
}}
>
{`
This is [an example](http://example.com/ "Title") inline link.
<http://example.com/>
`}
</Markdown>
);
};
2 changes: 2 additions & 0 deletions src/Markdown/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Markdown is a React component used to render Markdown text. It supports various

<code src="./demos/htmlPlugin.tsx" nopadding title="Custom Plugins Input" description="We have built-in some plugins for Markdown conversion, but if you have other requirements, you can customize the input of `rehypePlugins` and `remarkPlugins` to enhance the current rendering capabilities. The example is a sample input of rehypeRaw for rendering HTML capabilities. It is worth noting that there may be parsing conflicts between different plugins, which may need to be resolved by the user."></code>

<code src="./demos/renderComponets.tsx" nopadding title="Custom Partial Components" description="You can customize the rendering of some React-Markdown components through the Components property. For example, here is a case where the current A tag is modified"></code>

## APIs

| Property | Type | Description |
Expand Down
17 changes: 14 additions & 3 deletions src/Markdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Collapse, Divider, Typography } from 'antd';
import { CSSProperties, memo } from 'react';
import ReactMarkdown from 'react-markdown';
import ReactMarkdown, { Components } from 'react-markdown';
import rehypeKatex from 'rehype-katex';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
Expand All @@ -20,14 +20,19 @@ export interface MarkdownProps {
style?: CSSProperties;
rehypePlugins?: PluggableList;
remarkPlugins?: PluggableList;
components?: Components;
}

const MemoHr = memo((props) => (
<Divider style={{ marginBottom: '1em', marginTop: 0 }} {...props} />
));
const MemoDetails = memo((props) => <Collapse style={{ marginBottom: '1em' }} {...props} />);
const MemoImage = memo((props) => <img {...props} />);
const MemoAlink = memo((props) => <Typography.Link {...props} />);
const MemoAlink = memo((props) => {
console.log(props);

return <Typography.Link {...props} />;
});

const Markdown = memo<MarkdownProps>(
({
Expand All @@ -37,6 +42,7 @@ const Markdown = memo<MarkdownProps>(
onDoubleClick,
rehypePlugins: outRehypePlugins,
remarkPlugins: outRemarkPlugins,
components: outComponents,
...rest
}) => {
const { styles } = useStyles();
Expand All @@ -46,10 +52,15 @@ const Markdown = memo<MarkdownProps>(
a: MemoAlink,
img: MemoImage,
pre: Code,
...outComponents,
};

const rehypePlugins = [rehypeKatex, ...(outRehypePlugins || [])];
const remarkPlugins = [[remarkGfm,{singleTilde: false}], remarkMath, ...(outRemarkPlugins || [])];
const remarkPlugins = [
[remarkGfm, { singleTilde: false }],
remarkMath,
...(outRemarkPlugins || []),
];

return (
<Typography className={className} onDoubleClick={onDoubleClick} style={style}>
Expand Down
2 changes: 2 additions & 0 deletions src/Markdown/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Markdown 是一个用于渲染 Markdown 文本的 React 组件。它支持各种

<code src="./demos/htmlPlugin.tsx" nopadding title="自定义传入 Plugins" description="我们内置了一些对于 Markdown 转换的 Plugins,但是如果你有别的需求,你可以自定义传入 `rehypePlugins` 和 `remarkPlugins` 来扩充当前的渲染能力。例子是一个传入 rehypeRaw 用来渲染 Html 能力的样例。需要注意的是,不同的插件之间可能会出现解析冲突的问题,这个可能需要用户自己解决。"></code>

<code src="./demos/renderComponets.tsx" nopadding title="自定义部分组件" description="可以通过 Components 属性来自定义渲染一些 React-Markdown 的渲染组件,例如这里是一个魔改当前 A 标签的案例"></code>

## APIs

| 属性名 | 类型 | 描述 |
Expand Down
193 changes: 193 additions & 0 deletions tests/__snapshots__/demo.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -19029,6 +19029,199 @@ import { useDropNodeOnCanvas } from './useDropNodeOnCanvas';
</div>
`;

exports[`<Markdown /> > renders renderComponets.tsx correctly 1`] = `
.emotion-0 {
color: rgba(0, 0, 0, 0.88);
}

.emotion-0 h1,
.emotion-0 h2,
.emotion-0 h3,
.emotion-0 h4,
.emotion-0 h5 {
font-weight: 600;
}

.emotion-0 p {
margin-block-start: 0;
margin-block-end: 0;
font-size: 14px;
line-height: 1.8;
color: rgba(0, 0, 0, 0.88);
word-break: break-all;
word-wrap: break-word;
}

.emotion-0 p+* {
margin-block-end: 0.5em;
}

.emotion-0>*:last-child {
margin-bottom: 0!important;
}

.emotion-0 blockquote {
margin: 16px 0;
padding: 0 12px;
}

.emotion-0 blockquote p {
font-style: italic;
color: rgba(0, 0, 0, 0.45);
}

.emotion-0 p:not(:last-child) {
margin-bottom: 1em;
}

.emotion-0 a {
color: #1677ff;
}

.emotion-0 a:hover {
color: #69b1ff;
}

.emotion-0 a:active {
color: #0958d9;
}

.emotion-0 img {
max-width: 100%;
}

.emotion-0 pre,
.emotion-0 [data-code-type='highlighter'] {
border: none;
border-radius: 6px;
}

.emotion-0 pre>code,
.emotion-0 [data-code-type='highlighter']>code {
padding: 0!important;
border: none!important;
}

.emotion-0>:not([data-code-type='highlighter']) code {
padding: 2px 6px;
font-size: 10px;
border-radius: 4px;
}

.emotion-0 table {
border-spacing: 0;
width: 100%;
margin-block-start: 1em;
margin-block-end: 1em;
-webkit-margin-start: 0;
margin-inline-start: 0;
-webkit-margin-end: 0;
margin-inline-end: 0;
padding: 8px;
border: 1px solid #f0f0f0;
border-radius: 6px;
}

.emotion-0 table code {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
}

.emotion-0 th,
.emotion-0 td {
padding-block-start: 10px;
padding-block-end: 10px;
-webkit-padding-start: 16px;
padding-inline-start: 16px;
-webkit-padding-end: 16px;
padding-inline-end: 16px;
}

.emotion-0 thead tr th {
background: rgba(0, 0, 0, 0.04);
}

.emotion-0 thead tr th:first-child {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}

.emotion-0 thead tr th:last-child {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}

.emotion-0>ol>li::marker {
color: #1677ff!important;
}

.emotion-0>ul>li {
line-height: 1.8;
list-style-type: disc;
}

.emotion-0>ul>li::marker {
color: #1677ff!important;
}

.emotion-0 ol>li::marker,
.emotion-0 ul>li::marker {
color: rgba(0, 0, 0, 0.45);
}

.emotion-0 details {
margin-bottom: 1em;
padding: 12px 16px;
background: rgba(0, 0, 0, 0.04);
border: 1px solid #f0f0f0;
border-radius: 8px;
-webkit-transition: all 400ms cubic-bezier(0.215, 0.61, 0.355, 1);
transition: all 400ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.emotion-0 details[open] summary {
padding-bottom: 12px;
border-bottom: 1px solid #d9d9d9;
}

<div>
<article
class="ant-typography"
>
<div
class="emotion-0"
>
<p>
This is
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
该链接不允许点击跳转!http://example.com/
</span>
</button>
inline link.
</p>


<p>
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
该链接不允许点击跳转!http://example.com/
</span>
</button>
</p>
</div>
</article>
</div>
`;

exports[`<Snippet /> > renders index.tsx correctly 1`] = `
.emotion-0 {
background-color: transparent;
Expand Down

0 comments on commit 4328b89

Please sign in to comment.