文章目录

  • ​​效果​​
  • ​​环境​​
  • ​​思路​​
  • ​​代码 - 未完待续​​
  • ​​git 仓库​​

没有找到合适的库 期待Taro的发展
没有经过测试 只提供一个思路
项目代码在下方的git仓库
代码未必会同步更新到此出需要代码可以前往git仓库拷贝

效果

Taro markdown 解析器_git


Taro markdown 解析器_taro_02


Taro markdown 解析器_git_03

Taro markdown 解析器_taro_04

环境

"dependencies": {
"@babel/runtime": "^7.7.7",
"@tarojs/cli": "3.3.16",
"@tarojs/components": "3.3.16",
"@tarojs/react": "3.3.16",
"@tarojs/runtime": "3.3.16",
"@tarojs/taro": "3.3.16",
"linaria": "^2.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"taro-hooks": "latest"
},

思路

根据字符串一个一个排查 最终形成一个类似下面结构的数组

Taro markdown 解析器_node.js_05


然后遍历渲染对应的组件

代码 - 未完待续

function parseStr(tree: any, str: string) {
// 代码块
// let result = str.match(/^```[\S]+\n([\s|\S][^`|``|```]*)(```)?/);
let result = str.match(/^```[\S]+\n(([\s|\S](?!```))*)(```)?/);
if (result) {
tree.push({
type: "code",
text: result[1]
});
return parseStr(tree, str.slice(result[0].length + 4));
}
//标题 h1~h6
result = str.match(/^(#{1,6}) (.+)/);
if (result) {
tree.push({
type: "title",
text: result[2],
level: result[1].length
});
return parseStr(tree, str.slice(result[0].length));
}
//链接
result = str.match(/^\[([\s|\S][^\]]*)\]\(([\S][^\)]*)\)/);
if (result) {
tree.push({
type: "link",
text: result[1],
src: result[2]
});
return parseStr(tree, str.slice(result[0].length));
}
//图片
result = str.match(/^!\[([\s|\S][^\]]*)\]\(([\S][^\)]*)\)/);
if (result) {
tree.push({
type: "img",
alt: result[1],
src: result[2]
});
return parseStr(tree, str.slice(result[0].length));
}
//换行
result = str.match(/^\n/);
if (result) {
tree.push({ type: "nextLine" });
return parseStr(tree, str.slice(result[0].length));
}
//引用
result = str.match(/^>(.*)/);
if (result) {
const child = [];
parseStr(child, result[1]);
if (result[1]) {
//有时只有一个 > 这时不渲染
tree.push({
type: "quote",
child
});
}
return parseStr(tree, str.slice(result[0].length + 1)); //加1 是为了去掉结尾的\n
}
result = str.match(/^\*\*(?!\s)(.*)\*\*/); // 加粗 **xxx**
if (result) {
tree.push({ type: "bold", text: result[1] });
return parseStr(tree, str.slice(result[0].length));
}
result = str.match(/^`(.*)`/); // 标签 `xxx`
if (result) {
tree.push({ type: "tag", text: result[1] });
return parseStr(tree, str.slice(result[0].length));
}
//! 优先级要低
result = str.match(/.[^\[|\*|`|>|!|\s]*/);
if (result) {
tree.push({ type: "text", text: result[0] });
return parseStr(tree, str.slice(result[0].length));
}
}

使用

const MarkDownParse: FC<IProps> = ({ children }): ReactElement => {
const [mdTree, setMdTree] = useState<any>([]);

useEffect(() => {
const vTree: any = [];
parseStr(vTree, children);
console.log("tree:", vTree);
setMdTree(vTree);
}, [children]);

return (
<Container>
{mdTree.map(({ type, ...params }) => {
const Component = TypeComponent[type];
return <Component key={Math.random()} {...params} />;
})}
</Container>
);
};

git 仓库

​https://gitee.com/honbingitee/hongbin-blog/tree/master/src/components/MarkDownParse​