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()
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 |