feat(compiler): add isNativeTag option for determining element type (#139)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user