diff --git a/packages/compiler-sfc/__tests__/rewriteDefault.spec.ts b/packages/compiler-sfc/__tests__/rewriteDefault.spec.ts new file mode 100644 index 00000000..8bce2ab8 --- /dev/null +++ b/packages/compiler-sfc/__tests__/rewriteDefault.spec.ts @@ -0,0 +1,29 @@ +import { rewriteDefault } from '../src' + +describe('compiler sfc: rewriteDefault', () => { + test('without export default', () => { + expect(rewriteDefault(`export a = {}`, 'script')).toMatchInlineSnapshot(` + "export a = {} + const script = {}" + `) + }) + + test('rewrite export default', () => { + expect( + rewriteDefault(`export default {}`, 'script') + ).toMatchInlineSnapshot(`"const script = {}"`) + }) + + test('rewrite export named default', () => { + expect( + rewriteDefault( + `const a = 1 \n export { a as b, a as default, a as c}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const a = 1 + export { a as b, a as c} + const script = a" + `) + }) +}) diff --git a/packages/compiler-sfc/src/rewriteDefault.ts b/packages/compiler-sfc/src/rewriteDefault.ts index 04f783d2..9d6daed7 100644 --- a/packages/compiler-sfc/src/rewriteDefault.ts +++ b/packages/compiler-sfc/src/rewriteDefault.ts @@ -1,7 +1,8 @@ import { parse, ParserPlugin } from '@babel/parser' import MagicString from 'magic-string' -const defaultExportRE = /((?:^|\n|;)\s*)export default/ +const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/ +const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/ /** * Utility for rewriting `export default` in a script block into a varaible @@ -12,12 +13,12 @@ export function rewriteDefault( as: string, parserPlugins?: ParserPlugin[] ): string { - if (!defaultExportRE.test(input)) { + if (!hasDefaultExport(input)) { return input + `\nconst ${as} = {}` } const replaced = input.replace(defaultExportRE, `$1const ${as} =`) - if (!defaultExportRE.test(replaced)) { + if (!hasDefaultExport(replaced)) { return replaced } @@ -25,12 +26,33 @@ export function rewriteDefault( // multi-line comments or template strings. fallback to a full parse. const s = new MagicString(input) const ast = parse(input, { + sourceType: 'module', plugins: parserPlugins }).program.body ast.forEach(node => { if (node.type === 'ExportDefaultDeclaration') { s.overwrite(node.start!, node.declaration.start!, `const ${as} = `) } + if (node.type === 'ExportNamedDeclaration') { + node.specifiers.forEach(specifier => { + if ( + specifier.type === 'ExportSpecifier' && + specifier.exported.name === 'default' + ) { + const end = specifier.end! + s.overwrite( + specifier.start!, + input.charAt(end) === ',' ? end + 1 : end, + `` + ) + s.append(`\nconst ${as} = ${specifier.local.name}`) + } + }) + } }) return s.toString() } + +export function hasDefaultExport(input: string): boolean { + return defaultExportRE.test(input) || namedDefaultExportRE.test(input) +}