2019-09-17 19:24:39 +08:00
|
|
|
const hljs = require('highlight.js')
|
|
|
|
const marked = require('marked')
|
|
|
|
const fs = require('fs')
|
|
|
|
const path = require('path')
|
2019-09-18 09:41:40 +08:00
|
|
|
// const prettier = require('prettier')
|
2019-09-17 19:24:39 +08:00
|
|
|
|
|
|
|
const escapeMap = {
|
|
|
|
'&': '&',
|
|
|
|
'<': '<',
|
|
|
|
'>': '>',
|
|
|
|
'"': '"',
|
|
|
|
"'": '''
|
|
|
|
}
|
|
|
|
|
|
|
|
function escapeForHTML (input) {
|
|
|
|
return input.replace(/([&<>'"])/g, char => escapeMap[char])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create your custom renderer.
|
|
|
|
const renderer = new marked.Renderer()
|
|
|
|
renderer.code = (code, language) => {
|
|
|
|
// Check whether the given language is valid for highlight.js.
|
|
|
|
const validLang = !!(language && hljs.getLanguage(language))
|
|
|
|
|
|
|
|
// Highlight only if the language is valid.
|
|
|
|
// highlight.js escapes HTML in the code, but we need to escape by ourselves
|
|
|
|
// when we don't use it.
|
|
|
|
const highlighted = validLang
|
|
|
|
? hljs.highlight(language, code).value
|
|
|
|
: escapeForHTML(code)
|
|
|
|
|
|
|
|
// Render the highlighted code with `hljs` class.
|
2019-09-25 12:19:57 +08:00
|
|
|
return `<pre v-pre><code class="${language}">${highlighted}</code></pre>`
|
2019-09-17 19:24:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
marked.setOptions({
|
|
|
|
renderer
|
|
|
|
})
|
|
|
|
|
2019-09-23 15:04:57 +08:00
|
|
|
const demoBlock = fs.readFileSync(path.resolve(__dirname, 'ComponentDemoTemplate.vue')).toString()
|
2019-09-17 19:24:39 +08:00
|
|
|
|
|
|
|
function getPartsOfDemo (tokens) {
|
|
|
|
let template = null
|
|
|
|
let script = null
|
|
|
|
let style = null
|
|
|
|
let title = null
|
2019-10-30 16:22:49 +08:00
|
|
|
// let content = null
|
|
|
|
const contentTokens = []
|
|
|
|
contentTokens.links = tokens.links
|
2019-09-17 19:24:39 +08:00
|
|
|
for (const token of tokens) {
|
|
|
|
if (token.type === 'heading' && token.depth === 1) {
|
|
|
|
title = token.text
|
2019-10-30 16:22:49 +08:00
|
|
|
} else if (token.type === 'code' && (token.lang === 'template' || token.lang === 'html')) {
|
2019-09-17 19:24:39 +08:00
|
|
|
template = token.text
|
2019-10-30 16:22:49 +08:00
|
|
|
} else if (token.type === 'code' && (token.lang === 'script' || token.lang === 'js')) {
|
2019-09-17 19:24:39 +08:00
|
|
|
script = token.text
|
2019-10-30 16:22:49 +08:00
|
|
|
} else if (token.type === 'code' && (token.lang === 'style' || token.lang === 'css')) {
|
2019-09-17 19:24:39 +08:00
|
|
|
style = token.text
|
2019-10-30 16:22:49 +08:00
|
|
|
} else {
|
|
|
|
contentTokens.push(token)
|
2019-09-17 19:24:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
2019-09-20 00:23:21 +08:00
|
|
|
template: template,
|
|
|
|
script: script,
|
|
|
|
style: style,
|
|
|
|
title: title,
|
2019-10-30 16:22:49 +08:00
|
|
|
content: marked.parser(contentTokens)
|
2019-09-17 19:24:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function mergeParts (parts) {
|
|
|
|
const mergedParts = {
|
|
|
|
...parts
|
|
|
|
}
|
|
|
|
mergedParts.title = parts.title
|
2019-09-25 12:19:57 +08:00
|
|
|
mergedParts.content = marked(parts.content || '')
|
2019-09-17 19:24:39 +08:00
|
|
|
mergedParts.code = ''
|
2019-09-20 00:23:21 +08:00
|
|
|
// console.log(parts)
|
2019-09-17 19:24:39 +08:00
|
|
|
if (parts.template) {
|
|
|
|
mergedParts.code += parts.template
|
|
|
|
}
|
|
|
|
if (parts.script) {
|
|
|
|
if (parts.template) mergedParts.code += '\n\n'
|
|
|
|
mergedParts.code += `<script>
|
|
|
|
${parts.script}
|
|
|
|
</script>`
|
|
|
|
}
|
|
|
|
if (parts.style) {
|
2019-09-20 00:33:13 +08:00
|
|
|
if (parts.template || parts.script) mergedParts.code += '\n\n'
|
2019-09-17 19:24:39 +08:00
|
|
|
mergedParts.code += `<style>
|
|
|
|
${parts.style}
|
|
|
|
</style>`
|
|
|
|
}
|
|
|
|
mergedParts.code = marked(`\`\`\`html
|
|
|
|
${mergedParts.code}
|
|
|
|
\`\`\``)
|
|
|
|
// console.log(mergedParts.code)
|
|
|
|
return mergedParts
|
|
|
|
}
|
|
|
|
|
|
|
|
function genVueComponent (parts) {
|
|
|
|
const titleReg = /<!--TITLE_SLOT-->/
|
|
|
|
const contentReg = /<!--CONTENT_SLOT-->/
|
|
|
|
const codeReg = /<!--CODE_SLOT-->/
|
|
|
|
const scriptReg = /\/\*\*\sSCRIPT_SLOT\s\*\//
|
|
|
|
const styleReg = /\/\*\*STYLE_SLOT\*\//
|
|
|
|
const demoReg = /<!--DEMO_SLOT-->/
|
|
|
|
let src = demoBlock
|
|
|
|
// console.log(src)
|
2019-09-20 00:23:21 +08:00
|
|
|
if (parts.content) {
|
|
|
|
src = src.replace(contentReg, parts.content)
|
|
|
|
}
|
|
|
|
if (parts.title) {
|
|
|
|
src = src.replace(titleReg, parts.title)
|
|
|
|
}
|
|
|
|
if (parts.code) {
|
|
|
|
src = src.replace(codeReg, parts.code)
|
|
|
|
}
|
|
|
|
if (parts.script) {
|
|
|
|
src = src.replace(scriptReg, parts.script)
|
|
|
|
}
|
|
|
|
if (parts.style) {
|
|
|
|
src = src.replace(styleReg, parts.style)
|
|
|
|
}
|
|
|
|
if (parts.template) {
|
|
|
|
src = src.replace(demoReg, parts.template)
|
|
|
|
}
|
2019-09-18 09:41:40 +08:00
|
|
|
return src.trim()
|
2019-09-17 19:24:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function convertMd2Demo (text) {
|
|
|
|
const tokens = marked.lexer(text)
|
|
|
|
const parts = getPartsOfDemo(tokens)
|
|
|
|
const mergedParts = mergeParts(parts)
|
|
|
|
const vueComponent = genVueComponent(mergedParts)
|
2019-09-20 00:23:21 +08:00
|
|
|
// console.log(vueComponent)
|
2019-09-17 19:24:39 +08:00
|
|
|
return vueComponent
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = convertMd2Demo
|
2019-09-18 00:02:57 +08:00
|
|
|
// const startTime = new Date()
|
|
|
|
// for (let i = 0; i < 100; ++i) {
|
2019-10-30 16:22:49 +08:00
|
|
|
// const md = fs.readFileSync('./demo/documentation/components/input/enUS/lazyFocus.md').toString()
|
2019-09-20 00:23:21 +08:00
|
|
|
// convertMd2Demo(md)
|
2019-09-18 00:02:57 +08:00
|
|
|
// }
|
|
|
|
// const endTime = new Date()
|
|
|
|
// console.log(endTime - startTime)
|