const MarkdownIt = require("markdown-it"); const MarkdownItAnchor = require('markdown-it-anchor') const MarkdownItContainer = require("markdown-it-container"); const VueTemplateComplier = require("vue-template-compiler"); const hljs = require("highlight.js"); const slugify = require('transliteration').slugify; // 引入transliteration中的slugify方法 const { parse, compileTemplate } = require("@vue/component-compiler-utils"); module.exports = source => { // 需要解析成vue代码块集合 const componentCodeList = []; let styleCodeList = []; // 初始还MarkdownIt用于转换md文件为html const markdownIt = MarkdownIt({ html: true, // 将markdown中的代码块用hljs高亮显示 highlight: (str, lang) => { if (lang && hljs.getLanguage(lang)) { return `
${hljs.highlight(lang, str, true).value}`;
}
return `${markdownIt.utils.escapeHtml(str)}`;
}
});
// 使用【markdown-it-anchor】插件为markdown创建锚点
markdownIt.use(MarkdownItAnchor, {
level: 2, // 添加超链接锚点的最小标题级别, 如: #标题 不会添加锚点
slugify: slugify, // 自定义slugify, 我们使用的是将中文转为汉语拼音,最终生成为标题id属性
permalink: true, // 开启标题锚点功能
// permalinkBefore: true, // 在标题前创建锚点
permalinkSymbol: '#', // 锚点标志
});
// 使用【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 `