import type {Plugin} from 'vite'; import * as marked from 'marked'; import * as prism from 'prismjs'; import * as yaml from 'js-yaml'; let loadLanguages = require('prismjs/components/'); loadLanguages([ 'bash', 'javascript', 'java', 'python', 'jsx', 'tsx', 'css', 'markup', 'json' ]); const rYml = /^\s*---([\s\S]*?)---\s/; const renderer = new marked.Renderer(); (marked as any).setOptions({ renderer: renderer, gfm: true, tables: true, breaks: false, pedantic: false, smartLists: true, smartypants: false }); // Synchronous highlighting with prism.js (marked as any).setOptions({ highlight: function (code: string, lang: string) { if (lang) { return prism.highlight(code, prism.languages[lang], lang); } else { return code; } } }); // renderer.table = function(header, body) { // return '\n' // + '\n' // + header // + '\n' // + '\n' // + body // + '\n' // + '
\n'; // }; renderer.link = function (href: string, title: string, text: string) { if ((this as any).options.sanitize) { try { var prot = decodeURIComponent(unescape(href)) .replace(/[^\w:]/g, '') .toLowerCase(); } catch (e) { return ''; } if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) { return ''; } } if (href && href[0] === '#') { href = '#' + encodeURIComponent( href .substring(1) .toLowerCase() .replace(/[^\u4e00-\u9fa5_a-zA-Z0-9]+/g, '-') ); } var out = ''; return out; }; function markdown2js(content: string, file: string) { var m = rYml.exec(content); var info: any = {}; if (m && m[1]) { info = (yaml as any).load(m[1]); content = content.substring(m[0].length); } var toc: any = { label: '目录', type: 'toc', children: [], level: 0 }; var stack = [toc]; renderer.heading = function (text, level) { var escapedText = encodeURIComponent( text.toLowerCase().replace(/[^\u4e00-\u9fa5_a-zA-Z0-9]+/g, '-') ); if (level < 5) { var menu = { label: text, fragment: escapedText, fullPath: '#' + escapedText, level: level }; while (stack.length && stack[0].level >= level) { stack.shift(); } stack[0].children = stack[0].children || []; stack[0].children.push(menu); stack.unshift(menu); } var anchor = ''; return '' + anchor + text + ''; // return '' + // text + ''; }; const placeholder: any = {}; let index = 1; content = content .replace(/\!\!\!include\s*\(([^\)]+?)\)\!\!\!/g, (_, val) => { // todo // const result = null; // if (result) { // // 暂时不支持嵌套 include // return result.file.getContent(); // } return _; }) .replace( /```(schema|html)(?::(.*?))?[\n|\r\n]([\s\S]*?)```/g, function (_, lang, attr, code) { const setting: any = {}; attr && attr.split(/\s+/).forEach(function (item: string) { var parts = item.split('='); if (parts[1] && /^('|").*\1/.test(parts[1])) { parts[1] = parts[1].substring(1, parts[1].length - 1); } setting[parts[0]] = parts[1] ? decodeURIComponent(parts[1]) : ''; if (parts[0] === 'height') { setting.height = parseInt(setting.height, 10) /*编辑器的高度*/; attr = attr.replace(item, `height="${setting.height}"`); } }); // placeholder[index] = ``; if (lang === 'html') { if (~code.indexOf('
${code}
${prism.highlight(
            code
              .replace(/"data:(\w+\/\w+);.*?"/g, '"data:$1; ..."')
              .replace(/]*)>[\s\S]*?<\/svg>/g, '...')
              .replace(/class="([^"]*?)\.\.\.([^"]*?)"/g, 'class="$1..."'),
            prism.languages[lang],
            lang
          )}
`; } else { placeholder[ index ] = `
`; } return `[[${index++}]]`; } ); content = (marked as any) .parse(content) .replace(/

\[\[(\d+)\]\]<\/p>/g, function (_: string, id: string) { return placeholder[id] || ''; }); // content = global.fis ? fis.compile.partial(content, file, 'html') : content; // + `\n\n

文档内容有误?欢迎大家一起来编写,文档地址:${file.subpath}
`; info.html = '
' + content.replace( /<\!\-\-amis\-preview\-(start|end)\-\-\>/g, function (_, type) { return type === 'start' ? '
' : '
'; } ) + '
'; info.toc = toc; return 'export default ' + JSON.stringify(info, null, 2) + ';'; } export default function markdownPlugin(options: {} = {}): Plugin { return { name: 'markdown-as-js', enforce: 'pre', apply: 'serve', transform(code: string, id: string) { // if (id.endsWith('.scss') && /\/_[^\/]+\.scss$/.test(id)) { // const markdowns: Array = []; // code.replace( // /\/\*\!markdown\n([\s\S]+?)\*\//g, // (_: string, md: string) => { // markdowns.push(md.trim()); // return _; // } // ); // if (markdowns.length) { // return {code: markdown2js(markdowns.join('\n'), id) as string}; // } // return null; // } if (!id.endsWith('.md')) return null; return {code: markdown2js(code, id) as string}; } }; }