feat(compiler): add isNativeTag option for determining element type (#139)

This commit is contained in:
月迷津渡
2019-10-11 02:54:06 +08:00
committed by Evan You
parent 46d875f4e8
commit 78f60347dc
7 changed files with 275 additions and 13 deletions

View File

@@ -564,6 +564,52 @@ describe('compiler: parse', () => {
})
})
test('native element with `isNativeTag`', () => {
const ast = parse('<div></div><comp></comp><Comp></Comp>', {
isNativeTag: tag => tag === 'div'
})
expect(ast.children[0]).toMatchObject({
type: NodeTypes.ELEMENT,
tag: 'div',
tagType: ElementTypes.ELEMENT
})
expect(ast.children[1]).toMatchObject({
type: NodeTypes.ELEMENT,
tag: 'comp',
tagType: ElementTypes.COMPONENT
})
expect(ast.children[2]).toMatchObject({
type: NodeTypes.ELEMENT,
tag: 'Comp',
tagType: ElementTypes.COMPONENT
})
})
test('native element without `isNativeTag`', () => {
const ast = parse('<div></div><comp></comp><Comp></Comp>')
expect(ast.children[0]).toMatchObject({
type: NodeTypes.ELEMENT,
tag: 'div',
tagType: ElementTypes.ELEMENT
})
expect(ast.children[1]).toMatchObject({
type: NodeTypes.ELEMENT,
tag: 'comp',
tagType: ElementTypes.ELEMENT
})
expect(ast.children[2]).toMatchObject({
type: NodeTypes.ELEMENT,
tag: 'Comp',
tagType: ElementTypes.COMPONENT
})
})
test('attribute with no value', () => {
const ast = parse('<div id></div>')
const element = ast.children[0] as ElementNode

View File

@@ -1,3 +1,4 @@
import { NO } from '@vue/shared'
import {
ErrorCodes,
createCompilerError,
@@ -30,6 +31,7 @@ import { extend } from '@vue/shared'
export interface ParserOptions {
isVoidTag?: (tag: string) => boolean // e.g. img, br, hr
isNativeTag?: (tag: string) => boolean // e.g. loading-indicator in weex
getNamespace?: (tag: string, parent: ElementNode | undefined) => Namespace
getTextMode?: (tag: string, ns: Namespace) => TextModes
delimiters?: [string, string] // ['{{', '}}']
@@ -42,12 +44,19 @@ export interface ParserOptions {
onError?: (error: CompilerError) => void
}
export const defaultParserOptions: Required<ParserOptions> = {
// `isNativeTag` is optional, others are required
type MergedParserOptions = Pick<
Required<ParserOptions>,
Exclude<keyof ParserOptions, 'isNativeTag'>
> &
Pick<ParserOptions, 'isNativeTag'>
export const defaultParserOptions: MergedParserOptions = {
delimiters: [`{{`, `}}`],
ignoreSpaces: true,
getNamespace: () => Namespaces.HTML,
getTextMode: () => TextModes.DATA,
isVoidTag: () => false,
isVoidTag: NO,
namedCharacterReferences: {
'gt;': '>',
'lt;': '<',
@@ -68,7 +77,7 @@ export const enum TextModes {
}
interface ParserContext {
options: Required<ParserOptions>
options: MergedParserOptions
readonly originalSource: string
source: string
offset: number
@@ -428,9 +437,14 @@ function parseTag(
let tagType = ElementTypes.ELEMENT
if (!context.inPre) {
if (context.options.isNativeTag) {
if (!context.options.isNativeTag(tag)) tagType = ElementTypes.COMPONENT
} else {
if (/^[A-Z]/.test(tag)) tagType = ElementTypes.COMPONENT
}
if (tag === 'slot') tagType = ElementTypes.SLOT
else if (tag === 'template') tagType = ElementTypes.TEMPLATE
else if (/[A-Z-]/.test(tag)) tagType = ElementTypes.COMPONENT
}
return {