Skip to content
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
38 changes: 17 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,13 @@ md-components:
\`\`\`
```

### 示例


#### 示例样式

```scss
.ant-card {
border-color: black;
text-align: center;
width: 200px;
}
支持行内组件:
```md
我是一个行内组件\`md-components:Button{"type":"link","onClick":"$onClick","children":"我是一个行内按钮"}\`
```

### 示例

#### 示例代码

- 这里填写示例标题
Expand All @@ -67,7 +61,7 @@ md-components:
const { default: MarkdownComponentsRender } = _MarkdownComponentsRender;
const { default: mdUrl } = md;
const { default: Fetch } = _ReactFetch;
const { Card, Button, App } = antd;
const { Card, Button, App, Flex } = antd;

const BaseExample = () => {
const { message } = App.useApp();
Expand All @@ -77,15 +71,17 @@ const BaseExample = () => {
ignoreSuccessState
render={({ data }) => {
return (
<MarkdownComponentsRender
components={{ Card, Button }}
variables={{
onClick: () => {
message.info('你好');
}
}}>
{data}
</MarkdownComponentsRender>
<Flex vertical gap={10}>
<MarkdownComponentsRender
components={{ Card, Button }}
variables={{
onClick: () => {
message.info('你好');
}
}}>
{data}
</MarkdownComponentsRender>
</Flex>
);
}}></Fetch>
);
Expand Down
22 changes: 12 additions & 10 deletions doc/base.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { default: MarkdownComponentsRender } = _MarkdownComponentsRender;
const { default: mdUrl } = md;
const { default: Fetch } = _ReactFetch;
const { Card, Button, App } = antd;
const { Card, Button, App, Flex } = antd;

const BaseExample = () => {
const { message } = App.useApp();
Expand All @@ -11,15 +11,17 @@ const BaseExample = () => {
ignoreSuccessState
render={({ data }) => {
return (
<MarkdownComponentsRender
components={{ Card, Button }}
variables={{
onClick: () => {
message.info('你好');
}
}}>
{data}
</MarkdownComponentsRender>
<Flex vertical gap={10}>
<MarkdownComponentsRender
components={{ Card, Button }}
variables={{
onClick: () => {
message.info('你好');
}
}}>
{data}
</MarkdownComponentsRender>
</Flex>
);
}}></Fetch>
);
Expand Down
4 changes: 3 additions & 1 deletion doc/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ md-components:
type: primary
children: 我是一个按钮
onClick: $onClick
```
```

我是一个行内的组件`md-components:Button{"type":"link","onClick":"$onClick","children":"我是一个行内按钮"}`测试行内按钮
5 changes: 0 additions & 5 deletions doc/style.scss
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
.ant-card {
border-color: black;
text-align: center;
width: 200px;
}
5 changes: 5 additions & 0 deletions doc/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ md-components:
children: 我是一个按钮
onClick: $onClick
\`\`\`
```

支持行内组件:
```md
我是一个行内组件\`md-components:Button{"type":"link","onClick":"$onClick","children":"我是一个行内按钮"}\`
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kne/markdown-components-render",
"version": "0.1.5",
"version": "0.1.6",
"description": "渲染markdown文本,支持components.",
"syntax": {
"esmodules": true
Expand Down
32 changes: 16 additions & 16 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo, Fragment } from 'react';
import React, { useMemo, Fragment, createElement } from 'react';
import markdown from 'markdown-it';
import mdComponents from './markdown-it-components';
import compileVariables from './compileVariables';
Expand All @@ -23,23 +23,23 @@ const MarkdownComponentsRender = ({ children = '', render: customRender, ...prop
md.use(mdComponents);

const html = md.render(children);
const root = document.createElement('div');
root.innerHTML = typeof htmlTransform === 'function' ? htmlTransform(html) : html;
return [].slice.call(root.children).map((element, index) => {
if (element.className === 'yaml-components' && element.dataset.components) {
const componentsData = JSON.parse(element.dataset.components);
if (!componentsData['md-components']) {
return null;
}
const { type, props } = componentsData['md-components'];
const MdComponent = components[type];
if (!MdComponent) {
return null;

return htmlParser(typeof htmlTransform === 'function' ? htmlTransform(html) : html, {
replace(element) {
if (element.attribs && element.attribs.class === 'md-components' && element.attribs['data-components']) {
const componentsData = JSON.parse(element.attribs['data-components']);
if (!componentsData['md-components']) {
return null;
}
const { type, props } = componentsData['md-components'];
const MdComponent = components[type];
if (!MdComponent) {
return null;
}
return <MdComponent {...Object.assign({}, compileVariables(props, variables))} />;
}
return <MdComponent {...Object.assign({}, compileVariables(props, variables))} key={index} />;
return element;
}

return <Fragment key={index}>{htmlParser(element.outerHTML)}</Fragment>;
});
});

Expand Down
36 changes: 34 additions & 2 deletions src/markdown-it-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,50 @@ const validate = ajv.compile(mdComponentsSchema);

const mdComponents = function (md) {
const defaultFence = md.renderer.rules.fence;
const defaultCodeInline = md.renderer.rules.code_inline;

md.renderer.rules.code_inline = function (tokens, idx, options, env, self) {
const token = tokens[idx];
const regex = /^md-components:(.+)\{(.+)}$/;
try {
if (regex.test(token.content)) {
const matcher = token.content.match(regex);
const componentsType = matcher[1],
props = JSON.parse(`{${matcher[2]}}`);
const jsonData = {
'md-components': {
type: componentsType,
props: props
}
};
if (validate(jsonData)) {
const element = document.createElement('code');
element.setAttribute('class', 'md-components');
element.dataset.components = JSON.stringify(jsonData);
return element.outerHTML;
}
}
} catch (e) {
console.warn(e);
}

return defaultCodeInline(tokens, idx, options, env, self);
};

md.renderer.rules.fence = function (tokens, idx, options, env, self) {
const token = tokens[idx];
if (token.info.trim() === 'yml') {
try {
const jsonData = yaml.load(token.content);
if (validate(jsonData)) {
const element = document.createElement('pre');
element.setAttribute('class', 'yaml-components');
element.setAttribute('class', 'md-components');
element.dataset.components = JSON.stringify(jsonData);
return element.outerHTML;
}
} catch (e) {}
} catch (e) {
console.warn(e);
}
}
return defaultFence(tokens, idx, options, env, self);
};
Expand Down