2020-08-13 15:18:26 +08:00
|
|
|
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
|
|
|
const { compileTemplate, TemplateCompiler } = require('@vue/compiler-sfc')
|
|
|
|
|
|
|
|
|
|
function stripScript(content) {
|
|
|
|
|
const result = content.match(/<(script)>([\s\S]+)<\/\1>/)
|
|
|
|
|
return result && result[2] ? result[2].trim() : ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stripStyle(content) {
|
|
|
|
|
const result = content.match(/<(style)\s*>([\s\S]+)<\/\1>/)
|
|
|
|
|
return result && result[2] ? result[2].trim() : ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 编写例子时不一定有 template。所以采取的方案是剔除其他的内容
|
|
|
|
|
function stripTemplate(content) {
|
|
|
|
|
content = content.trim()
|
|
|
|
|
if (!content) {
|
|
|
|
|
return content
|
|
|
|
|
}
|
|
|
|
|
return content.replace(/<(script|style)[\s\S]+<\/\1>/g, '').trim()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function pad(source) {
|
|
|
|
|
return source
|
|
|
|
|
.split(/\r?\n/)
|
|
|
|
|
.map(line => ` ${line}`)
|
|
|
|
|
.join('\n')
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-13 22:17:53 +08:00
|
|
|
|
const templateReplaceRegex = /<template>([\s\S]+)<\/template>/g
|
2020-08-13 15:18:26 +08:00
|
|
|
|
function genInlineComponentText(template, script) {
|
|
|
|
|
// https://github.com/vuejs/vue-loader/blob/423b8341ab368c2117931e909e2da9af74503635/lib/loaders/templateLoader.js#L46
|
2020-08-13 22:17:53 +08:00
|
|
|
|
let source = template
|
|
|
|
|
if (templateReplaceRegex.test(source)) {
|
|
|
|
|
source = source.replace(templateReplaceRegex, '$1')
|
|
|
|
|
}
|
2020-08-13 15:18:26 +08:00
|
|
|
|
const finalOptions = {
|
2020-08-13 22:17:53 +08:00
|
|
|
|
source: `<div>${source}</div>`,
|
2020-08-13 15:18:26 +08:00
|
|
|
|
filename: 'inline-component', // TODO:这里有待调整
|
|
|
|
|
compiler: TemplateCompiler,
|
|
|
|
|
compilerOptions: {
|
|
|
|
|
mode: 'function',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
const compiled = compileTemplate(finalOptions)
|
|
|
|
|
// tips
|
|
|
|
|
if (compiled.tips && compiled.tips.length) {
|
|
|
|
|
compiled.tips.forEach(tip => {
|
|
|
|
|
console.warn(tip)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// errors
|
|
|
|
|
if (compiled.errors && compiled.errors.length) {
|
|
|
|
|
console.error(
|
|
|
|
|
`\n Error compiling template:\n${pad(compiled.source)}\n` +
|
|
|
|
|
compiled.errors.map(e => ` - ${e}`).join('\n') +
|
|
|
|
|
'\n',
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
let demoComponentContent = `
|
|
|
|
|
${(compiled.code).replace('return function render','function render')}
|
|
|
|
|
`
|
|
|
|
|
// todo: 这里采用了硬编码有待改进
|
|
|
|
|
script = script.trim()
|
|
|
|
|
if (script) {
|
2020-10-22 16:05:52 +08:00
|
|
|
|
script = script
|
|
|
|
|
.replace(/export\s+default/, 'const democomponentExport =')
|
|
|
|
|
.replace(/import ({.*}) from 'vue'/g, (s, s1) => `const ${s1} = Vue`)
|
2020-08-13 15:18:26 +08:00
|
|
|
|
} else {
|
|
|
|
|
script = 'const democomponentExport = {}'
|
|
|
|
|
}
|
|
|
|
|
demoComponentContent = `(function() {
|
|
|
|
|
${demoComponentContent}
|
|
|
|
|
${script}
|
|
|
|
|
return {
|
|
|
|
|
render,
|
|
|
|
|
...democomponentExport
|
|
|
|
|
}
|
|
|
|
|
})()`
|
|
|
|
|
return demoComponentContent
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
stripScript,
|
|
|
|
|
stripStyle,
|
|
|
|
|
stripTemplate,
|
|
|
|
|
genInlineComponentText,
|
|
|
|
|
}
|