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