wip: parser support for script setup

This commit is contained in:
Evan You 2020-07-03 15:08:41 -04:00
parent 23b0d5adc0
commit 1ad3f975ed
2 changed files with 39 additions and 10 deletions

View File

@ -146,15 +146,33 @@ h1 { color: red }
test('should only allow single template element', () => { test('should only allow single template element', () => {
parse(`<template><div/></template><template><div/></template>`) parse(`<template><div/></template><template><div/></template>`)
expect( expect(
`Single file component can contain only one template element` `Single file component can contain only one <template> element`
).toHaveBeenWarned() ).toHaveBeenWarned()
}) })
test('should only allow single script element', () => { test('should only allow single script element', () => {
parse(`<script>console.log(1)</script><script>console.log(1)</script>`) parse(`<script>console.log(1)</script><script>console.log(1)</script>`)
expect( expect(
`Single file component can contain only one script element` `Single file component can contain only one <script> element`
).toHaveBeenWarned() ).toHaveBeenWarned()
}) })
test('should only allow single script setup element', () => {
parse(
`<script setup>console.log(1)</script><script setup>console.log(1)</script>`
)
expect(
`Single file component can contain only one <script setup> element`
).toHaveBeenWarned()
})
test('should not warn script & script setup', () => {
parse(
`<script setup>console.log(1)</script><script>console.log(1)</script>`
)
expect(
`Single file component can contain only one`
).not.toHaveBeenWarned()
})
}) })
}) })

View File

@ -35,6 +35,7 @@ export interface SFCTemplateBlock extends SFCBlock {
export interface SFCScriptBlock extends SFCBlock { export interface SFCScriptBlock extends SFCBlock {
type: 'script' type: 'script'
setup?: boolean
} }
export interface SFCStyleBlock extends SFCBlock { export interface SFCStyleBlock extends SFCBlock {
@ -47,6 +48,7 @@ export interface SFCDescriptor {
filename: string filename: string
template: SFCTemplateBlock | null template: SFCTemplateBlock | null
script: SFCScriptBlock | null script: SFCScriptBlock | null
scriptSetup: SFCScriptBlock | null
styles: SFCStyleBlock[] styles: SFCStyleBlock[]
customBlocks: SFCBlock[] customBlocks: SFCBlock[]
} }
@ -86,6 +88,7 @@ export function parse(
filename, filename,
template: null, template: null,
script: null, script: null,
scriptSetup: null,
styles: [], styles: [],
customBlocks: [] customBlocks: []
} }
@ -140,11 +143,16 @@ export function parse(
} }
break break
case 'script': case 'script':
if (!descriptor.script) { const block = createBlock(node, source, pad) as SFCScriptBlock
descriptor.script = createBlock(node, source, pad) as SFCScriptBlock if (block.setup && !descriptor.scriptSetup) {
} else { descriptor.scriptSetup = block
warnDuplicateBlock(source, filename, node) break
} }
if (!block.setup && !descriptor.script) {
descriptor.script = block
break
}
warnDuplicateBlock(source, filename, node, block.setup)
break break
case 'style': case 'style':
descriptor.styles.push(createBlock(node, source, pad) as SFCStyleBlock) descriptor.styles.push(createBlock(node, source, pad) as SFCStyleBlock)
@ -183,7 +191,8 @@ export function parse(
function warnDuplicateBlock( function warnDuplicateBlock(
source: string, source: string,
filename: string, filename: string,
node: ElementNode node: ElementNode,
isScriptSetup = false
) { ) {
const codeFrame = generateCodeFrame( const codeFrame = generateCodeFrame(
source, source,
@ -192,9 +201,9 @@ function warnDuplicateBlock(
) )
const location = `${filename}:${node.loc.start.line}:${node.loc.start.column}` const location = `${filename}:${node.loc.start.line}:${node.loc.start.column}`
console.warn( console.warn(
`Single file component can contain only one ${ `Single file component can contain only one <${node.tag}${
node.tag isScriptSetup ? ` setup` : ``
} element (${location}):\n\n${codeFrame}` }> element (${location}):\n\n${codeFrame}`
) )
} }
@ -241,6 +250,8 @@ function createBlock(
} }
} else if (type === 'template' && p.name === 'functional') { } else if (type === 'template' && p.name === 'functional') {
;(block as SFCTemplateBlock).functional = true ;(block as SFCTemplateBlock).functional = true
} else if (type === 'script' && p.name === 'setup') {
;(block as SFCScriptBlock).setup = true
} }
} }
}) })