diff --git a/packages/compiler-sfc/__tests__/parse.spec.ts b/packages/compiler-sfc/__tests__/parse.spec.ts
index d7d8ca6b..1378e64a 100644
--- a/packages/compiler-sfc/__tests__/parse.spec.ts
+++ b/packages/compiler-sfc/__tests__/parse.spec.ts
@@ -146,15 +146,33 @@ h1 { color: red }
test('should only allow single template element', () => {
parse(``)
expect(
- `Single file component can contain only one template element`
+ `Single file component can contain only one element`
).toHaveBeenWarned()
})
test('should only allow single script element', () => {
parse(``)
expect(
- `Single file component can contain only one script element`
+ `Single file component can contain only one `
+ )
+ expect(
+ `Single file component can contain only one `
+ )
+ expect(
+ `Single file component can contain only one`
+ ).not.toHaveBeenWarned()
+ })
})
})
diff --git a/packages/compiler-sfc/src/parse.ts b/packages/compiler-sfc/src/parse.ts
index 2e8bd719..6e92acaa 100644
--- a/packages/compiler-sfc/src/parse.ts
+++ b/packages/compiler-sfc/src/parse.ts
@@ -35,6 +35,7 @@ export interface SFCTemplateBlock extends SFCBlock {
export interface SFCScriptBlock extends SFCBlock {
type: 'script'
+ setup?: boolean
}
export interface SFCStyleBlock extends SFCBlock {
@@ -47,6 +48,7 @@ export interface SFCDescriptor {
filename: string
template: SFCTemplateBlock | null
script: SFCScriptBlock | null
+ scriptSetup: SFCScriptBlock | null
styles: SFCStyleBlock[]
customBlocks: SFCBlock[]
}
@@ -86,6 +88,7 @@ export function parse(
filename,
template: null,
script: null,
+ scriptSetup: null,
styles: [],
customBlocks: []
}
@@ -140,11 +143,16 @@ export function parse(
}
break
case 'script':
- if (!descriptor.script) {
- descriptor.script = createBlock(node, source, pad) as SFCScriptBlock
- } else {
- warnDuplicateBlock(source, filename, node)
+ const block = createBlock(node, source, pad) as SFCScriptBlock
+ if (block.setup && !descriptor.scriptSetup) {
+ descriptor.scriptSetup = block
+ break
}
+ if (!block.setup && !descriptor.script) {
+ descriptor.script = block
+ break
+ }
+ warnDuplicateBlock(source, filename, node, block.setup)
break
case 'style':
descriptor.styles.push(createBlock(node, source, pad) as SFCStyleBlock)
@@ -183,7 +191,8 @@ export function parse(
function warnDuplicateBlock(
source: string,
filename: string,
- node: ElementNode
+ node: ElementNode,
+ isScriptSetup = false
) {
const codeFrame = generateCodeFrame(
source,
@@ -192,9 +201,9 @@ function warnDuplicateBlock(
)
const location = `${filename}:${node.loc.start.line}:${node.loc.start.column}`
console.warn(
- `Single file component can contain only one ${
- node.tag
- } element (${location}):\n\n${codeFrame}`
+ `Single file component can contain only one <${node.tag}${
+ isScriptSetup ? ` setup` : ``
+ }> element (${location}):\n\n${codeFrame}`
)
}
@@ -241,6 +250,8 @@ function createBlock(
}
} else if (type === 'template' && p.name === 'functional') {
;(block as SFCTemplateBlock).functional = true
+ } else if (type === 'script' && p.name === 'setup') {
+ ;(block as SFCScriptBlock).setup = true
}
}
})