const path = require('path') const hljs = require('highlight.js') const Token = require('markdown-it/lib/token') const cheerio = require('cheerio') const getBabelCommonConfig = require('./antd-tools/getBabelCommonConfig') const babelConfig = getBabelCommonConfig(false) babelConfig.plugins.push(require.resolve('babel-plugin-syntax-dynamic-import')) const fetch = (str, tag, scoped) => { const $ = cheerio.load(str, { decodeEntities: false, xmlMode: true, }) if (!tag) { return str } if (tag === 'style') { return scoped ? $(`${tag}[scoped]`).html() : $(`${tag}`).not(`${tag}[scoped]`).html() } return $(tag).html() } /** * `{{ }}` => `{{ }}` * @param {string} str * @return {string} */ const replaceDelimiters = function (str) { return str.replace(/({{|}})/g, '$1') } /** * renderHighlight * @param {string} str * @param {string} lang */ const renderHighlight = function (str, lang) { if (!(lang && hljs.getLanguage(lang))) { return '' } try { return replaceDelimiters(hljs.highlight(lang, str, true).value) } catch (err) {} } const md = require('markdown-it')('default', { html: true, breaks: true, highlight: renderHighlight, }).use(require('markdown-it-anchor'), { level: 2, slugify: string => string.trim().split(' ').join('-'), permalink: true, // renderPermalink: (slug, opts, state, permalink) => {}, permalinkClass: 'anchor', permalinkSymbol: '#', permalinkBefore: false, }) // md.renderer.rules.fence = wrap(md.renderer.rules.fence) const cnReg = new RegExp('<(cn)(?:[^<]|<)+', 'g') const usReg = new RegExp('<(us)(?:[^<]|<)+', 'g') md.core.ruler.push('update_template', function replace ({ tokens }) { let cn = '' let us = '' let template = '' let script = '' let style = '' let scopedStyle = '' let code = '' let sourceCode = '' tokens.forEach(token => { if (token.type === 'html_block') { if (token.content.match(cnReg)) { cn = fetch(token.content, 'cn') token.content = '' } if (token.content.match(usReg)) { us = fetch(token.content, 'us') token.content = '' } } if (token.type === 'fence' && token.info === 'html' && token.markup === '```') { sourceCode = token.content code = '````html\n' + token.content + '````' template = fetch(token.content, 'template') script = fetch(token.content, 'script') style = fetch(token.content, 'style') scopedStyle = fetch(token.content, 'style', true) token.content = '' token.type = 'html_block' } }) if (template) { let jsfiddle = { html: template, script, style, us, cn, sourceCode, } jsfiddle = md .utils .escapeHtml(JSON.stringify(jsfiddle)) const codeHtml = code ? md.render(code) : '' const cnHtml = cn ? md.render(cn) : '' let newContent = ` ` newContent += script ? ` ` : '' newContent += style ? ` ` : '' newContent += scopedStyle ? ` ` : '' const t = new Token('html_block', '', 0) t.content = newContent tokens.push(t) } }) module.exports = { entry: { index: [`./site/${process.env.ENTRY_INDEX || 'index'}.js`], }, module: { rules: [ { test: /\.md/, use: [ { loader: 'vue-antd-md-loader', options: Object.assign(md, { wrapper: 'div', vueLoaderOptions: { loaders: { js: [ { loader: 'babel-loader', options: { presets: ['env'], plugins: ['transform-vue-jsx', 'transform-object-rest-spread'], }, }, ], }, }, }), }, ], }, { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { js: [ { loader: 'babel-loader', options: { presets: ['env'], plugins: ['transform-vue-jsx', 'transform-object-rest-spread', 'syntax-dynamic-import'], }, }, ], }, }, }, { test: /\.(js|jsx)$/, loader: 'babel-loader', exclude: /node_modules/, options: babelConfig, }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]', }, }, ], }, resolve: { modules: [ 'node_modules', path.join(__dirname, '../node_modules'), ], extensions: [ '.js', '.jsx', '.vue', '.md', ], alias: { 'vue$': 'vue/dist/vue.esm.js', 'antd': path.join(__dirname, 'components'), 'ant-design-vue': path.join(__dirname, 'components'), '@': path.join(__dirname, ''), }, }, }