From 7f6abda6ddb9629695f48a2d68206194324b91e7 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Fri, 15 Nov 2019 00:50:13 +0800 Subject: [PATCH] feat(compiler-sfc): warn duplicate block (#451) --- packages/compiler-sfc/__tests__/parse.spec.ts | 21 +++++++++++++++++ packages/compiler-sfc/src/parse.ts | 23 +++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 packages/compiler-sfc/__tests__/parse.spec.ts diff --git a/packages/compiler-sfc/__tests__/parse.spec.ts b/packages/compiler-sfc/__tests__/parse.spec.ts new file mode 100644 index 000000000..14cb9dcc9 --- /dev/null +++ b/packages/compiler-sfc/__tests__/parse.spec.ts @@ -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(``) + expect( + `Single file component can contain only one template element` + ).toHaveBeenWarned() + }) + + test('should only allow single script element', () => { + parse(``) + expect( + `Single file component can contain only one script element` + ).toHaveBeenWarned() + }) + }) +}) diff --git a/packages/compiler-sfc/src/parse.ts b/packages/compiler-sfc/src/parse.ts index 9cfded626..de8945dda 100644 --- a/packages/compiler-sfc/src/parse.ts +++ b/packages/compiler-sfc/src/parse.ts @@ -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