wip: refine element type
This commit is contained in:
parent
c342433cb5
commit
a12abe72bc
|
@ -18,6 +18,7 @@ import Tokenizer, { CharCodes, QuoteType, isWhitespace } from './Tokenizer'
|
||||||
import { CompilerCompatOptions } from '../compat/compatConfig'
|
import { CompilerCompatOptions } from '../compat/compatConfig'
|
||||||
import { NO, extend } from '@vue/shared'
|
import { NO, extend } from '@vue/shared'
|
||||||
import { defaultOnError, defaultOnWarn } from '../errors'
|
import { defaultOnError, defaultOnWarn } from '../errors'
|
||||||
|
import { isCoreComponent } from '../utils'
|
||||||
|
|
||||||
type OptionalOptions =
|
type OptionalOptions =
|
||||||
| 'getTextMode' // TODO
|
| 'getTextMode' // TODO
|
||||||
|
@ -113,8 +114,7 @@ const tokenizer = new Tokenizer({
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: name,
|
tag: name,
|
||||||
ns: currentOptions.getNamespace(name, getParent()),
|
ns: currentOptions.getNamespace(name, getParent()),
|
||||||
// TODO refine tag type
|
tagType: ElementTypes.ELEMENT, // will be refined on tag close
|
||||||
tagType: ElementTypes.ELEMENT,
|
|
||||||
props: [],
|
props: [],
|
||||||
children: [],
|
children: [],
|
||||||
loc: {
|
loc: {
|
||||||
|
@ -188,8 +188,6 @@ const tokenizer = new Tokenizer({
|
||||||
if (name === 'pre') {
|
if (name === 'pre') {
|
||||||
inVPre = true
|
inVPre = true
|
||||||
currentElementIsVPreBoundary = true
|
currentElementIsVPreBoundary = true
|
||||||
// force current element type
|
|
||||||
currentElement!.tagType = ElementTypes.ELEMENT
|
|
||||||
// convert dirs before this one to attributes
|
// convert dirs before this one to attributes
|
||||||
const props = currentElement!.props
|
const props = currentElement!.props
|
||||||
for (let i = 0; i < props.length; i++) {
|
for (let i = 0; i < props.length; i++) {
|
||||||
|
@ -362,9 +360,23 @@ function onCloseTag(el: ElementNode, end: number) {
|
||||||
offset++
|
offset++
|
||||||
}
|
}
|
||||||
el.loc.end = tokenizer.getPos(end + offset + 1)
|
el.loc.end = tokenizer.getPos(end + offset + 1)
|
||||||
|
|
||||||
|
// refine element type
|
||||||
|
const tag = el.tag
|
||||||
|
if (!inVPre) {
|
||||||
|
if (tag === 'slot') {
|
||||||
|
el.tagType = ElementTypes.SLOT
|
||||||
|
} else if (isFragmentTemplate(el)) {
|
||||||
|
el.tagType = ElementTypes.TEMPLATE
|
||||||
|
} else if (isComponent(el)) {
|
||||||
|
el.tagType = ElementTypes.COMPONENT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// whitepsace management
|
// whitepsace management
|
||||||
el.children = condenseWhitespace(el.children)
|
el.children = condenseWhitespace(el.children)
|
||||||
if (currentOptions.isPreTag(el.tag)) {
|
|
||||||
|
if (currentOptions.isPreTag(tag)) {
|
||||||
inPre--
|
inPre--
|
||||||
}
|
}
|
||||||
if (currentElementIsVPreBoundary) {
|
if (currentElementIsVPreBoundary) {
|
||||||
|
@ -373,8 +385,77 @@ function onCloseTag(el: ElementNode, end: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const windowsNewlineRE = /\r\n/g
|
const specialTemplateDir = new Set(['if', 'else', 'else-if', 'for', 'slot'])
|
||||||
|
function isFragmentTemplate({ tag, props }: ElementNode): boolean {
|
||||||
|
if (tag === 'template') {
|
||||||
|
for (let i = 0; i < props.length; i++) {
|
||||||
|
if (
|
||||||
|
props[i].type === NodeTypes.DIRECTIVE &&
|
||||||
|
specialTemplateDir.has(props[i].name)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function isComponent({ tag, props }: ElementNode): boolean {
|
||||||
|
if (currentOptions.isCustomElement(tag)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
tag === 'component' ||
|
||||||
|
isUpperCase(tag.charCodeAt(0)) ||
|
||||||
|
isCoreComponent(tag) ||
|
||||||
|
currentOptions.isBuiltInComponent?.(tag) ||
|
||||||
|
!currentOptions.isNativeTag?.(tag)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// at this point the tag should be a native tag, but check for potential "is"
|
||||||
|
// casting
|
||||||
|
for (let i = 0; i < props.length; i++) {
|
||||||
|
const p = props[i]
|
||||||
|
if (p.type === NodeTypes.ATTRIBUTE) {
|
||||||
|
if (p.name === 'is' && p.value) {
|
||||||
|
if (p.value.content.startsWith('vue:')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// TODO else if (
|
||||||
|
// __COMPAT__ &&
|
||||||
|
// checkCompatEnabled(
|
||||||
|
// CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
|
// context,
|
||||||
|
// p.loc
|
||||||
|
// )
|
||||||
|
// ) {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO else if (
|
||||||
|
// __COMPAT__ &&
|
||||||
|
// // :is on plain element - only treat as component in compat mode
|
||||||
|
// p.name === 'bind' &&
|
||||||
|
// isStaticArgOf(p.arg, 'is') &&
|
||||||
|
// checkCompatEnabled(
|
||||||
|
// CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
|
// context,
|
||||||
|
// p.loc
|
||||||
|
// )
|
||||||
|
// ) {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function isUpperCase(c: number) {
|
||||||
|
return c > 64 && c < 91
|
||||||
|
}
|
||||||
|
|
||||||
|
const windowsNewlineRE = /\r\n/g
|
||||||
function condenseWhitespace(nodes: TemplateChildNode[]): TemplateChildNode[] {
|
function condenseWhitespace(nodes: TemplateChildNode[]): TemplateChildNode[] {
|
||||||
const shouldCondense = currentOptions.whitespace !== 'preserve'
|
const shouldCondense = currentOptions.whitespace !== 'preserve'
|
||||||
let removedWhitespace = false
|
let removedWhitespace = false
|
||||||
|
|
|
@ -49,14 +49,19 @@ export const isBuiltInType = (tag: string, expected: string): boolean =>
|
||||||
tag === expected || tag === hyphenate(expected)
|
tag === expected || tag === hyphenate(expected)
|
||||||
|
|
||||||
export function isCoreComponent(tag: string): symbol | void {
|
export function isCoreComponent(tag: string): symbol | void {
|
||||||
if (isBuiltInType(tag, 'Teleport')) {
|
switch (tag) {
|
||||||
return TELEPORT
|
case 'Teleport':
|
||||||
} else if (isBuiltInType(tag, 'Suspense')) {
|
case 'teleport':
|
||||||
return SUSPENSE
|
return TELEPORT
|
||||||
} else if (isBuiltInType(tag, 'KeepAlive')) {
|
case 'Suspense':
|
||||||
return KEEP_ALIVE
|
case 'suspense':
|
||||||
} else if (isBuiltInType(tag, 'BaseTransition')) {
|
return SUSPENSE
|
||||||
return BASE_TRANSITION
|
case 'KeepAlive':
|
||||||
|
case 'keep-alive':
|
||||||
|
return KEEP_ALIVE
|
||||||
|
case 'BaseTransition':
|
||||||
|
case 'base-transition':
|
||||||
|
return BASE_TRANSITION
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue