Last active
July 24, 2023 09:31
-
-
Save akira-cn/a681c8b989a1cba30188a6dcd9b47fd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const compiler = require('@vue/compiler-sfc'); | |
function generateID() { | |
return Math.random().toString(36).slice(2, 12); | |
} | |
module.exports = function transformVueSFC(source, filename) { | |
const {descriptor, errors} = compiler.parse(source, {filename}); | |
if(errors.length) throw new Error(errors.toString()); | |
const id = generateID(); | |
const hasScoped = descriptor.styles.some(e => e.scoped); | |
const scopeId = hasScoped ? `data-v-${id}` : undefined; | |
const templateOptions = { | |
id, | |
source: descriptor.template.content, | |
filename: descriptor.filename, | |
scoped: hasScoped, | |
slotted: descriptor.slotted, | |
compilerOptions: { | |
scopeId: hasScoped ? scopeId : undefined, | |
mode: 'module', | |
}, | |
}; | |
let script = {content: 'const script={}'}; | |
try { | |
script = compiler.compileScript(descriptor, {id, templateOptions, sourceMap:true}); | |
} catch(ex) { | |
// do nothing | |
// console.error(ex); | |
} | |
// if(script.map) { | |
// script.content = `${script.content}\n//# sourceMappingURL=data:application/json;base64,${btoa(JSON.stringify(script.map))}`; | |
// } | |
const template = compiler.compileTemplate({...templateOptions, sourceMap: true}); | |
// if(template.map) { | |
// template.map.sources[0] = `${template.map.sources[0]}?template`; | |
// template.code = `${template.code}\n//# sourceMappingURL=data:application/json;base64,${btoa(JSON.stringify(template.map))}`; | |
// } | |
let cssInJS = ''; | |
if(descriptor.styles) { | |
const styled = descriptor.styles.map((style) => { | |
return compiler.compileStyle({ | |
id, | |
source: style.content, | |
scoped: style.scoped, | |
preprocessLang: style.lang, | |
}); | |
}); | |
if(styled.length) { | |
const cssCode = styled.map(s => s.code).join('\n'); | |
cssInJS = `(function(){const el = document.createElement('style'); | |
el.innerHTML = \`${cssCode}\`; | |
document.body.appendChild(el);}());`; | |
} | |
} | |
const moduleCode = ` | |
${script.content.replace(/^\s*export default\s*/mg, 'const script = ')}; | |
${template.code.replace(/^\s*export function render\s*\([^()]+\)\s*{/mg, 'script.render = function(_ctx, _cache, $props, $setup, $data, $options) {')}; | |
${filename ? `script.__file = '${filename}'` : ''}; | |
${scopeId ? `script.__scopeId = '${scopeId}'` : ''}; | |
${cssInJS} | |
export default script; | |
`; | |
return moduleCode.replace(/_resolveComponent\(("\w+")\)/g, '\$setup[$1]'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment