Skip to content

Instantly share code, notes, and snippets.

@akira-cn
Last active July 24, 2023 09:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akira-cn/a681c8b989a1cba30188a6dcd9b47fd7 to your computer and use it in GitHub Desktop.
Save akira-cn/a681c8b989a1cba30188a6dcd9b47fd7 to your computer and use it in GitHub Desktop.
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