naive-ui/demo/loaders/convertMd2Doc.js

177 lines
6.0 KiB
JavaScript
Raw Normal View History

const marked = require('marked')
2019-09-25 12:19:57 +08:00
const camelCase = require('lodash/camelCase')
2019-12-22 15:31:04 +08:00
const mdLoader = require('./NaiveUIMdLoader')
2019-12-22 23:19:08 +08:00
const createRenderer = require('./mdRenderer')
const mdRenderer = createRenderer()
2019-10-14 17:49:23 +08:00
function template (demos, demosLiteral, isSingleColumn = false) {
// return `<component-demos :single-column="${isSingleColumn}">
// ${demos}
// <template v-slot:anchor>
// ${parseDemosAsAnchor(demosLiteral)}
// </template>
// </component-demos>`
return `<component-demos :single-column="${isSingleColumn}">
${demos}
</component-demos>`
}
function parseDemos (demosLiteral, env) {
const demoFileNames = demosLiteral
.split('\n')
.map(demoFileName => demoFileName.trim())
.filter((demoFileName) => {
if (env === 'production') {
return demoFileName.length && demoFileName.indexOf('debug') < 0 && demoFileName.indexOf('Debug') < 0
}
return demoFileName.length
})
2020-09-03 23:40:38 +08:00
const demoTags = demoFileNames.map(demoFileName => `<${demoFileName}Demo id="${demoFileName}" demo-id="${demoFileName}"/>`)
return demoTags.join('\n')
}
2019-10-14 17:49:23 +08:00
function parseDemosAsAnchor (demosLiteral) {
const demoFileNames = demosLiteral
2019-10-14 17:49:23 +08:00
.split('\n')
.map(demoFileName => demoFileName.trim())
.filter(demoFileName => demoFileName.length)
const linkTags = demoFileNames.map(demoFileName => (
2020-03-05 13:46:19 +08:00
`
<n-anchor-link
2020-09-03 23:40:38 +08:00
v-if="anchorLinkMap.has('${demoFileName}')"
:title="anchorLinkMap.get('${demoFileName}')"
href="#${demoFileName}"
2020-03-05 13:46:19 +08:00
/>`))
2020-03-05 22:31:20 +08:00
return `<n-anchor :top="32" :bound="16" position="absolute" affix style="width: 144px;">${linkTags.join('\n')}</n-anchor>`
2019-10-14 17:49:23 +08:00
}
2020-03-19 13:26:06 +08:00
function generateScript (demosLiteral, components = [], url) {
const demoFileNames = demosLiteral
.split('\n')
.map(demoFileName => demoFileName.trim())
.filter(demoFileName => demoFileName.length)
const importStatements = demoFileNames
2020-09-03 23:40:38 +08:00
.map(demoFileName => `import ${camelCase(demoFileName)}Demo from './${demoFileName}.demo.md'`)
.concat(components.map(component => `import ${camelCase(component)} from './${component}'`))
2019-10-25 15:43:06 +08:00
.join('\n')
2020-09-03 23:40:38 +08:00
const componentStatements = demoFileNames.map(demoFileName => camelCase(demoFileName) + 'Demo').concat(components).join(', ')
const script = `<script>
${importStatements}
export default {
components: {
${componentStatements}
2019-10-14 17:49:23 +08:00
},
provide () {
return {
NDocumentation: this
}
},
data () {
return {
2020-03-09 17:18:01 +08:00
anchorLinkMap: new Map(),
2020-03-19 13:26:06 +08:00
url: ${JSON.stringify(url)}
2019-10-14 17:49:23 +08:00
}
}
}
</script>`
return script
}
2020-03-09 17:18:01 +08:00
function convertMd2ComponentDocumentation (text, env = 'development', url) {
2019-12-22 15:31:04 +08:00
const isNoDemo = !!~text.search('<!--no-demo-->')
if (isNoDemo) {
2020-03-19 13:26:06 +08:00
return mdLoader(text, url)
2019-12-22 15:31:04 +08:00
}
2019-10-12 19:08:11 +08:00
const isSingleColumn = !!~text.search('<!--single-column-->')
const tokens = marked.lexer(text)
2019-10-25 15:43:06 +08:00
const componentsIndex = tokens.findIndex(token => token.type === 'code' && token.lang === 'component')
let components = []
if (~componentsIndex) {
components = tokens[componentsIndex].text
components = components.split('\n').map(component => component.trim()).filter(component => component.length)
tokens.splice(componentsIndex, 1)
}
const demosIndex = tokens.findIndex(token => token.type === 'code' && token.lang === 'demo')
let demos = { text: '' }
let demosLiteral = ''
let headerPart = tokens
let footerPart = []
// console.log(tokens)
if (~demosIndex) {
headerPart = tokens.slice(0, demosIndex)
footerPart = tokens.slice(demosIndex + 1)
demos = tokens[demosIndex]
demosLiteral = demos.text
tokens.splice(demosIndex, 1, {
type: 'html',
pre: false,
text: '<!--demos-->\n'
})
}
headerPart.links = {}
footerPart.links = {}
2020-02-21 15:26:51 +08:00
const documentationHTML = `${marked.parser(headerPart, {
2019-12-22 15:31:04 +08:00
gfm: true,
renderer: mdRenderer
2020-02-21 15:26:51 +08:00
})}\n` + '<!--demos-->\n' + `${marked.parser(footerPart, {
2019-12-22 15:31:04 +08:00
gfm: true,
renderer: mdRenderer
2020-02-21 15:26:51 +08:00
})}\n`
// console.log(documentationHTML)
// const classedDocumentationHTML = addClassToHTML(documentationHTML, 'markdown')
const demosReg = /<!--demos-->/
const demoTags = parseDemos(demosLiteral, env)
2020-03-19 13:26:06 +08:00
let documentationContent = documentationHTML
2020-03-16 13:01:13 +08:00
.replace(demosReg, template(demoTags, demosLiteral, isSingleColumn))
2020-03-19 13:26:06 +08:00
const titleIndex = tokens.findIndex(token => token.type === 'heading' && token.depth === 1)
if (titleIndex > -1) {
const titleText = JSON.stringify(tokens[titleIndex].text)
const gheButton = `<edit-on-github-header url=${url} text=${titleText}></edit-on-github-header>`
const titleReg = /(<n-h1[^>]*>)(.*?)(<\/n-h1>)/
documentationContent = documentationContent.replace(titleReg, `${gheButton}`)
2020-03-16 13:01:13 +08:00
}
2020-03-19 13:26:06 +08:00
const documentationTemplate = `s
2019-10-14 17:49:23 +08:00
<template>
<component-documentation>
<div style="display: flex; flex-wrap: nowrap;">
2020-02-24 16:25:02 +08:00
<div style="width: calc(100% - 180px); margin-right: 36px;">
2019-10-14 17:49:23 +08:00
${documentationContent}
</div>
2020-02-24 16:25:02 +08:00
<div style="width: 144px;">
2019-10-14 17:49:23 +08:00
${parseDemosAsAnchor(demosLiteral)}
</div>
</div>
</component-documentation>
</template>`
2020-03-19 13:26:06 +08:00
const documentationScript = generateScript(demosLiteral, components, url)
2019-10-25 15:43:06 +08:00
// if (components.length) console.log(`${documentationTemplate}\n\n${documentationScript}`)
return `${documentationTemplate}\n\n${documentationScript}`
// console.log(vueComponent)
// return vueComponent
// console.log(marked.parser(tokens))
// const parts = getPartsOfDemo(tokens)
// const mergedParts = mergeParts(parts)
// const vueComponent = genVueComponent(mergedParts)
// console.log(vueComponent)
// return vueComponent
}
// function addClassToHTML (html, className) {
// const classReg = /<[^!/][^>]*>/g
// return html.replace(classReg, (openTag) => {
// return openTag.replace(/>/, ` class="${className}">`)
// })
// }
module.exports = convertMd2ComponentDocumentation
// const startTime = new Date()
// for (let i = 0; i < 100; ++i) {
// const fs = require('fs')
// const md = fs.readFileSync('./marked/component.md').toString()
// console.log(convertMd2ComponentDocumentation(md))
// }
// const endTime = new Date()
// console.log(endTime - startTime)