150 lines
4.1 KiB
TypeScript
150 lines
4.1 KiB
TypeScript
import {
|
|
transformOn as baseTransform,
|
|
DirectiveTransform,
|
|
createObjectProperty,
|
|
createCallExpression,
|
|
createSimpleExpression,
|
|
NodeTypes,
|
|
createCompoundExpression,
|
|
ExpressionNode,
|
|
SimpleExpressionNode,
|
|
isStaticExp,
|
|
warnDeprecation,
|
|
CompilerDeprecationTypes
|
|
} from '@vue/compiler-core'
|
|
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
|
|
import { makeMap, capitalize } from '@vue/shared'
|
|
|
|
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
|
|
const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
|
// event propagation management
|
|
`stop,prevent,self,` +
|
|
// system modifiers + exact
|
|
`ctrl,shift,alt,meta,exact,` +
|
|
// mouse
|
|
`middle`
|
|
)
|
|
// left & right could be mouse or key modifiers based on event type
|
|
const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right')
|
|
const isKeyboardEvent = /*#__PURE__*/ makeMap(
|
|
`onkeyup,onkeydown,onkeypress`,
|
|
true
|
|
)
|
|
|
|
const resolveModifiers = (key: ExpressionNode, modifiers: string[]) => {
|
|
const keyModifiers = []
|
|
const nonKeyModifiers = []
|
|
const eventOptionModifiers = []
|
|
|
|
for (let i = 0; i < modifiers.length; i++) {
|
|
const modifier = modifiers[i]
|
|
|
|
if (isEventOptionModifier(modifier)) {
|
|
// eventOptionModifiers: modifiers for addEventListener() options,
|
|
// e.g. .passive & .capture
|
|
eventOptionModifiers.push(modifier)
|
|
} else {
|
|
// runtimeModifiers: modifiers that needs runtime guards
|
|
if (maybeKeyModifier(modifier)) {
|
|
if (isStaticExp(key)) {
|
|
if (isKeyboardEvent((key as SimpleExpressionNode).content)) {
|
|
keyModifiers.push(modifier)
|
|
} else {
|
|
nonKeyModifiers.push(modifier)
|
|
}
|
|
} else {
|
|
keyModifiers.push(modifier)
|
|
nonKeyModifiers.push(modifier)
|
|
}
|
|
} else {
|
|
if (isNonKeyModifier(modifier)) {
|
|
nonKeyModifiers.push(modifier)
|
|
} else {
|
|
keyModifiers.push(modifier)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
keyModifiers,
|
|
nonKeyModifiers,
|
|
eventOptionModifiers
|
|
}
|
|
}
|
|
|
|
const transformClick = (key: ExpressionNode, event: string) => {
|
|
const isStaticClick =
|
|
isStaticExp(key) && key.content.toLowerCase() === 'onclick'
|
|
return isStaticClick
|
|
? createSimpleExpression(event, true)
|
|
: key.type !== NodeTypes.SIMPLE_EXPRESSION
|
|
? createCompoundExpression([
|
|
`(`,
|
|
key,
|
|
`) === "onClick" ? "${event}" : (`,
|
|
key,
|
|
`)`
|
|
])
|
|
: key
|
|
}
|
|
|
|
export const transformOn: DirectiveTransform = (dir, node, context) => {
|
|
return baseTransform(dir, node, context, baseResult => {
|
|
const { modifiers } = dir
|
|
if (!modifiers.length) return baseResult
|
|
|
|
if (__COMPAT__ && __DEV__ && modifiers.includes('native')) {
|
|
warnDeprecation(
|
|
CompilerDeprecationTypes.V_ON_NATIVE_MODIFIER,
|
|
context,
|
|
dir.loc
|
|
)
|
|
}
|
|
|
|
let { key, value: handlerExp } = baseResult.props[0]
|
|
const {
|
|
keyModifiers,
|
|
nonKeyModifiers,
|
|
eventOptionModifiers
|
|
} = resolveModifiers(key, modifiers)
|
|
|
|
// normalize click.right and click.middle since they don't actually fire
|
|
if (nonKeyModifiers.includes('right')) {
|
|
key = transformClick(key, `onContextmenu`)
|
|
}
|
|
if (nonKeyModifiers.includes('middle')) {
|
|
key = transformClick(key, `onMouseup`)
|
|
}
|
|
|
|
if (nonKeyModifiers.length) {
|
|
handlerExp = createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [
|
|
handlerExp,
|
|
JSON.stringify(nonKeyModifiers)
|
|
])
|
|
}
|
|
|
|
if (
|
|
keyModifiers.length &&
|
|
// if event name is dynamic, always wrap with keys guard
|
|
(!isStaticExp(key) || isKeyboardEvent(key.content))
|
|
) {
|
|
handlerExp = createCallExpression(context.helper(V_ON_WITH_KEYS), [
|
|
handlerExp,
|
|
JSON.stringify(keyModifiers)
|
|
])
|
|
}
|
|
|
|
if (eventOptionModifiers.length) {
|
|
const modifierPostfix = eventOptionModifiers.map(capitalize).join('')
|
|
key = isStaticExp(key)
|
|
? createSimpleExpression(`${key.content}${modifierPostfix}`, true)
|
|
: createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`])
|
|
}
|
|
|
|
return {
|
|
props: [createObjectProperty(key, handlerExp)]
|
|
}
|
|
})
|
|
}
|