markdown-loader.js
3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const MarkdownIt = require("markdown-it");
const MarkdownItContainer = require("markdown-it-container");
const VueTemplateComplier = require("vue-template-compiler");
const hljs = require("highlight.js");
const { parse, compileTemplate } = require("@vue/component-compiler-utils");
module.exports = function(source) {
// 需要解析成vue代码块集合
const componentCodeList = [];
let styleCodeList = [];
// 初始还MarkdownIt用于转换md文件为html
const markdownIt = MarkdownIt({
// 将markdown中的代码块用hljs高亮显示
highlight: function(str, lang) {
if (lang && hljs.getLanguage(lang)) {
return `<pre class="hljs" style="white-space: pre-wrap;word-wrap: break-word;"><code>${
hljs.highlight(lang, str, true).value
}</code></pre>`;
}
return `<pre class="hljs" style="white-space: pre-wrap;word-wrap: break-word;"><code>${markdownIt.utils.escapeHtml(
str
)}</code></pre>`;
}
});
// 使用【markdown-it-container】插件解析【:::snippet :::】代码块为vue渲染
markdownIt.use(MarkdownItContainer, "snippet", {
// 验证代码块为【:::snippet :::】才进行渲染
validate(params) {
return params.trim().match(/^snippet\s*(.*)$/);
},
// 代码块渲染
render(tokens, index) {
const token = tokens[index];
const tokenInfo = token.info.trim().match(/^snippet\s*(.*)$/);
if (token.nesting === 1) {
// 获取snippet第一行的表述内容
const desc = tokenInfo && tokenInfo.length > 1 ? tokenInfo[1] : "";
// 获取vue组件示例的代码
const nextIndex = tokens[index + 1];
const content = nextIndex.type === "fence" ? nextIndex.content : "";
// 将content解析为vue组件基本属性对象;
let { template, script, styles } = parse({
source: content,
compiler: VueTemplateComplier,
needMap: false
});
styleCodeList = styleCodeList.concat(styles);
// 将template的转为render函数
const { code } = compileTemplate({
source: template.content,
compiler: VueTemplateComplier
});
// 获取script的代码
script = script ? script.content : "";
if (script) {
script = script.replace(
/export\s+default/,
"const exportJavaScript ="
);
} else {
script = "const exportJavaScript = {} ;";
}
// 代码块解析将需要解析vue组件的存储,渲染html用组件名称替代
const name = `eagle-snippent-${componentCodeList.length}`;
// 渲染组件代码添加到数据集合
componentCodeList.push(`"${name}":(function () {
${code}
${script}
return {
...exportJavaScript,
render,
staticRenderFns
}
})()`);
// 将需要渲染的示例用eagle-code-snippet组件包裹替换插槽显示示例效果
return `<eagle-code-snippet>
<div slot="desc">${markdownIt.render(desc)}</div>
<${name} slot="source" />
<div slot="code">`;
}
return ` </div>
</eagle-code-snippet> `;
}
});
// 将所有转换好的代码字符串拼接成vue单组件template、script、style格式
return `
<template>
<div class="eagle-snippet-doc">
${markdownIt.render(source)}
</div>
</template>
<script>
export default {
name: 'eagle-component-doc',
components: {
${componentCodeList.join(",")}
}
}
</script>
<style>
${Array.from(styleCodeList, m => m.content).join("\n")}
</style>`;
};