206 lines
6.6 KiB
JavaScript
206 lines
6.6 KiB
JavaScript
/**
|
|
* @fileoverview 将微信端的代码转换到各个平台
|
|
*/
|
|
const through2 = require('through2')
|
|
|
|
// api 前缀
|
|
const prefix = {
|
|
weixin: {
|
|
wxml: 'wx:',
|
|
js: 'wx.'
|
|
},
|
|
qq: {
|
|
wxml: 'qq:',
|
|
js: 'qq.'
|
|
},
|
|
baidu: {
|
|
wxml: 's-',
|
|
js: 'swan.'
|
|
},
|
|
alipay: {
|
|
wxml: 'a:',
|
|
js: 'my.'
|
|
},
|
|
toutiao: {
|
|
wxml: 'tt:',
|
|
js: 'tt.'
|
|
}
|
|
}
|
|
// 文件名后缀
|
|
const suffix = {
|
|
weixin: {
|
|
wxml: '.wxml',
|
|
wxss: '.wxss'
|
|
},
|
|
qq: {
|
|
wxml: '.qml',
|
|
wxss: '.qss'
|
|
},
|
|
baidu: {
|
|
wxml: '.swan',
|
|
wxss: '.css'
|
|
},
|
|
alipay: {
|
|
wxml: '.axml',
|
|
wxss: '.acss'
|
|
},
|
|
toutiao: {
|
|
wxml: '.ttml',
|
|
wxss: '.ttss'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @description 取出两个括号之间的内容
|
|
* @param {string} content 总内容
|
|
* @param {number} i 开始位置
|
|
*/
|
|
function getSection (content, i) {
|
|
let j = i + 1
|
|
let num = 1
|
|
const start = content[i]
|
|
const end = start === '(' ? ')' : '}'
|
|
while (num) {
|
|
if (content[j] === start) {
|
|
num++
|
|
} else if (content[j] === end) {
|
|
num--
|
|
}
|
|
j++
|
|
}
|
|
return content.substring(i, j)
|
|
}
|
|
|
|
/**
|
|
* @description 处理不同小程序平台间的差异
|
|
* @param {string} platform 使用平台
|
|
*/
|
|
module.exports = function (platform) {
|
|
if (platform !== 'uni-app') {
|
|
platform = platform.split('-')[1]
|
|
}
|
|
return through2.obj(function (file, _, callback) {
|
|
if (file.isBuffer()) {
|
|
let content = file.contents.toString()
|
|
if (platform === 'uni-app') {
|
|
if (file.extname === '.js') {
|
|
content = content.replace(/\.properties/g, '')
|
|
}
|
|
} else {
|
|
// wxml 文件处理
|
|
if (file.extname === '.wxml') {
|
|
content = content.replace(/wx:/g, prefix[platform].wxml) // 替换 api 前缀
|
|
file.extname = suffix[platform].wxml // 修改后缀名
|
|
if (platform === 'qq') {
|
|
// wxs 转为 qs
|
|
content = content.replace(/<wxs/g, '<qs').replace(/<\/wxs/g, '</qs')
|
|
} else if (platform === 'baidu') {
|
|
content = content.replace(/s-if=['"]{{(\S+)}}['"]/g, 's-if="$1"') // s-if 和 s-for 后不加 {{}}
|
|
.replace(/s-for=['"]{{(\S+)}}['"]/g, 's-for="$1"')
|
|
.replace(/data="(.*?)"/g, 'data="{$1}"')
|
|
} else if (platform === 'alipay') {
|
|
content = content.replace('block-size', 'handle-size')
|
|
.replace(/longpress/g, 'longTap')
|
|
.replace(/bind([\S])/g, (_, $1) => { // bindevent 转为 onEvent
|
|
return 'on' + $1.toUpperCase()
|
|
}).replace(/catch([\S])/g, (_, $1) => { // catchevent 转为 catchEvent
|
|
return 'catch' + $1.toUpperCase()
|
|
})
|
|
}
|
|
} else if (file.extname === '.js') {
|
|
// js 文件处理
|
|
// 替换 api 前缀
|
|
content = content.replace(/wx\./g, prefix[platform].js)
|
|
|
|
// 支付宝格式转换
|
|
if (platform === 'alipay') {
|
|
// 将 aa.triggerEvent('bb', cc) 替换为 aa.props.onBb && aa.props.onBb(cc)
|
|
content = content.replace(/([a-zA-Z0-9._]+).triggerEvent\(['"](\S+?)['"],*/g, function (_, $1, $2) {
|
|
const method = `${$1}.props.on${$2[0].toUpperCase()}${$2.slice(1)}`
|
|
return `${method}&&${method}(`
|
|
})
|
|
|
|
// 转换 showToast
|
|
let i = content.indexOf('.showToast')
|
|
while (i !== -1) {
|
|
i += 10
|
|
const section = getSection(content, i)
|
|
content = content.substr(0, i) + section.replace('title', 'content') + content.substr(i + section.length)
|
|
i = content.indexOf('.showToast', i)
|
|
}
|
|
// 转换 showActionSheet
|
|
i = content.indexOf('.showActionSheet')
|
|
while (i !== -1) {
|
|
i += 16
|
|
const section = getSection(content, i)
|
|
content = content.substr(0, i) + section.replace('itemList', 'items') + content.substr(i + section.length)
|
|
i = content.indexOf('.showActionSheet', i)
|
|
}
|
|
// 转换 setClipboardData
|
|
i = content.indexOf('.setClipboardData')
|
|
while (i !== -1) {
|
|
i += 17
|
|
const section = getSection(content, i)
|
|
content = content.substr(0, i - 4) + section.replace('data', 'text') + content.substr(i + section.length)
|
|
i = content.indexOf('.setClipboardData', i)
|
|
}
|
|
// 组件格式转换
|
|
if (content.includes('Component({')) {
|
|
// 替换生命周期
|
|
content = content.replace('created:', 'didMount:')
|
|
.replace('attached:', 'didMount:')
|
|
.replace('detached:', 'didUnmount:')
|
|
// 将 properties 字段转为 props 格式
|
|
i = content.indexOf('{', content.indexOf('properties:'))
|
|
let props
|
|
let propsStr = '{'
|
|
const objStr = getSection(content, i)
|
|
// 取出整个 properties 字段
|
|
eval('props = ' + objStr) // eslint-disable-line
|
|
for (const item in props) {
|
|
if (!props[item]) continue
|
|
propsStr += item + ':'
|
|
if (props[item].value) {
|
|
// 设置了默认值
|
|
if (typeof props[item].value === 'boolean') {
|
|
propsStr += props[item].value ? '!0' : '!1'
|
|
} else {
|
|
propsStr += props[item].value
|
|
}
|
|
} else {
|
|
// 没有设置默认值
|
|
const type = props[item].type || props[item]
|
|
if (type === String) {
|
|
propsStr += '""'
|
|
} else if (type === Boolean) {
|
|
propsStr += '!1'
|
|
} else if (type === Number) {
|
|
propsStr += '0'
|
|
} else if (type === Object) {
|
|
propsStr += '{}'
|
|
} else if (type === Array) {
|
|
propsStr += '[]'
|
|
}
|
|
}
|
|
propsStr += ','
|
|
}
|
|
content = content.substr(0, i) + propsStr.substring(0, propsStr.length - 1) + '}' + content.substr(i + objStr.length)
|
|
}
|
|
|
|
content = content.replace(/properties/g, 'props')
|
|
.replace(/\.setNavigationBarTitle/g, '.setNavigationBar')
|
|
} else {
|
|
content = content.replace(/\.properties/g, '.data')
|
|
}
|
|
} else if (file.extname === '.wxss') {
|
|
// wxss 文件处理
|
|
file.extname = suffix[platform].wxss // 修改后缀名
|
|
}
|
|
}
|
|
file.contents = Buffer.from(content)
|
|
}
|
|
this.push(file)
|
|
callback()
|
|
})
|
|
}
|