Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: markdown 支持自定义组件渲染 #179

Merged
merged 2 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading