/** * @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(/ { // 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() }) }