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 = 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 `
${
          hljs.highlight(lang, str.replace(/\{\{/g, '{ {').replace(/\}\}/g, '} }'), true).value
        }
`; } return `
${markdownIt.utils.escapeHtml(
        str.replace(/\{\{/g, '{ {').replace(/\}\}/g, '} }')
      )}
`; } }); // 使用【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 `
${markdownIt.render(desc)}
<${name} slot="source" />
`; } return `
`; } }); // 使用【markdown-it-container】插件解析【:::html :::】代码块为vue渲染 markdownIt.use(MarkdownItContainer, "html", { // 验证代码块为【:::html :::】才进行渲染 validate(params) { return params.trim().match(/^html\s*(.*)$/); }, // 代码块渲染 render(tokens, index) { if (tokens[index].nesting === 1) { return ``; } return ``; } }); // 将所有转换好的代码字符串拼接成vue单组件template、script、style格式 return ` `; };