feat(compiler-sfc): warn duplicate block (#451)

This commit is contained in:
likui 2019-11-15 00:50:13 +08:00 committed by Evan You
parent 8688acc36f
commit 7f6abda6dd
2 changed files with 42 additions and 2 deletions

View File

@ -0,0 +1,21 @@
import { parse } from '../src'
import { mockWarn } from '@vue/runtime-test'
describe('compiler:sfc', () => {
mockWarn()
describe('error', () => {
test('should only allow single template element', () => {
parse(`<template><div/></template><template><div/></template>`)
expect(
`Single file component can contain only one template element`
).toHaveBeenWarned()
})
test('should only allow single script element', () => {
parse(`<script>console.log(1)</script><script>console.log(1)</script>`)
expect(
`Single file component can contain only one script element`
).toHaveBeenWarned()
})
})
})

View File

@ -7,6 +7,7 @@ import {
SourceLocation
} from '@vue/compiler-core'
import { RawSourceMap } from 'source-map'
import { generateCodeFrame } from '@vue/shared'
export interface SFCParseOptions {
needMap?: boolean
@ -78,14 +79,14 @@ export function parse(
if (!sfc.template) {
sfc.template = createBlock(node) as SFCTemplateBlock
} else {
// TODO warn duplicate template
warnDuplicateBlock(source, filename, node)
}
break
case 'script':
if (!sfc.script) {
sfc.script = createBlock(node) as SFCScriptBlock
} else {
// TODO warn duplicate script
warnDuplicateBlock(source, filename, node)
}
break
case 'style':
@ -105,6 +106,24 @@ export function parse(
return sfc
}
function warnDuplicateBlock(
source: string,
filename: string,
node: ElementNode
) {
const codeFrame = generateCodeFrame(
source,
node.loc.start.offset,
node.loc.end.offset
)
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}`
)
}
function createBlock(node: ElementNode): SFCBlock {
const type = node.tag
const text = node.children[0] as TextNode