You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.7 KiB
139 lines
3.7 KiB
const t = require('@babel/types')
|
|
const traverse = require('@babel/traverse').default
|
|
|
|
function cached (fn) {
|
|
const cache = Object.create(null)
|
|
return function cachedFn (str) {
|
|
const hit = cache[str]
|
|
return hit || (cache[str] = fn(str))
|
|
}
|
|
}
|
|
|
|
const capitalize = cached(str => {
|
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
})
|
|
|
|
const EVENTS = {
|
|
click: 'tap',
|
|
touchstart: 'touchStart',
|
|
touchmove: 'touchMove',
|
|
touchend: 'touchEnd',
|
|
touchcancel: 'touchCancel',
|
|
longtap: 'longTap',
|
|
longpress: 'longTap',
|
|
transitionend: 'transitionEnd',
|
|
animationstart: 'animationStart',
|
|
animationiteration: 'animationIteration',
|
|
animationend: 'animationEnd',
|
|
firstappear: 'firstAppear',
|
|
// map
|
|
markertap: 'markerTap',
|
|
callouttap: 'calloutTap',
|
|
controltap: 'controlTap',
|
|
regionchange: 'regionChange',
|
|
// scroll-view
|
|
scrolltoupper: 'scrollToUpper',
|
|
scrolltolower: 'scrollToLower',
|
|
// movable-view
|
|
changeend: 'changeEnd'
|
|
}
|
|
|
|
module.exports = {
|
|
directive: 'a:',
|
|
specialEvents: {
|
|
form: {
|
|
reset: 'onReset'
|
|
},
|
|
map: {
|
|
markertap: 'onMarkerTap',
|
|
controltap: 'onControlTap',
|
|
callouttap: 'onCalloutTap',
|
|
regionchange: 'onRegionChange'
|
|
}
|
|
},
|
|
createFilterTag (filterTag, {
|
|
attrs
|
|
}) {
|
|
return `<import-sjs name="${attrs.module}" from="${attrs.src}"></import-sjs>`
|
|
},
|
|
getEventType (eventType) {
|
|
return EVENTS[eventType] || eventType
|
|
},
|
|
formatEventType: function (eventName, isCatch) {
|
|
return `${isCatch ? 'catch' : 'on'}${capitalize(eventName)}`
|
|
},
|
|
createScopedSlots (slotName, props, state) {
|
|
const node = {
|
|
type: 'slot',
|
|
attr: {
|
|
name: slotName
|
|
},
|
|
children: []
|
|
}
|
|
Object.keys(props).forEach(name => {
|
|
node.attr[name] = props[name]
|
|
})
|
|
return node
|
|
},
|
|
resolveScopedSlots (slotName, {
|
|
paramExprNode,
|
|
returnExprNodes,
|
|
traverseExpr,
|
|
normalizeChildren
|
|
}, state) {
|
|
const node = {
|
|
type: 'view',
|
|
attr: {
|
|
slot: slotName
|
|
}
|
|
}
|
|
if (paramExprNode) {
|
|
if (t.isIdentifier(paramExprNode)) {
|
|
const scoped = paramExprNode.name
|
|
node.attr['slot-scope'] = scoped
|
|
} else if (t.isObjectPattern(paramExprNode)) {
|
|
const paramName = '__SCOPED__'
|
|
node.attr['slot-scope'] = paramName
|
|
const start = returnExprNodes.start
|
|
const end = returnExprNodes.end
|
|
const names = []
|
|
paramExprNode.properties.forEach(property => {
|
|
const key = property.key
|
|
const value = property.value
|
|
if (t.isIdentifier(value)) {
|
|
if (value.name !== key.name) {
|
|
state.errors.add(`解构插槽 Prop 时,不支持将${key.name}重命名为${value.name},重命名后会影响性能`)
|
|
return
|
|
}
|
|
} else if (t.isAssignmentPattern(value)) {
|
|
state.errors.add(`解构插槽 Prop 时,不支持为${key.name}设置默认值`)
|
|
return
|
|
}
|
|
names.push(key.name)
|
|
})
|
|
traverse({
|
|
type: 'Program',
|
|
start,
|
|
end,
|
|
body: [{
|
|
type: 'ExpressionStatement',
|
|
start,
|
|
end,
|
|
expression: returnExprNodes
|
|
}],
|
|
sourceType: 'module'
|
|
}, {
|
|
Identifier (path) {
|
|
const node = path.node
|
|
const name = node.name
|
|
if (names.includes(name) && path.key !== 'key' && (path.key !== 'property' || path.parent.computed) && !(path.scope && path.scope.hasBinding(name))) {
|
|
path.replaceWithSourceString(`${paramName}.${name}`)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
node.children = normalizeChildren(traverseExpr(returnExprNodes, state))
|
|
return node
|
|
}
|
|
}
|
|
|