116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			116 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | /** | |||
|  |  * @fileoverview 条件编译 | |||
|  |  */ | |||
|  | const through2 = require('through2') | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 条件编译 | |||
|  |  * @param {string} platform 平台 | |||
|  |  */ | |||
|  | module.exports = function (platform) { | |||
|  |   return through2.obj(function (file, _, callback) { | |||
|  |     if (file.isBuffer()) { | |||
|  |       // 文件夹级别的处理
 | |||
|  |       if (file.relative.includes('miniprogram')) { | |||
|  |         if (platform !== 'uni-app') { | |||
|  |           // 去掉这一层
 | |||
|  |           file.path = file.path.replace(/(.*)[/\\]miniprogram/, '$1') | |||
|  |         } else { | |||
|  |           // 不用于本平台的文件
 | |||
|  |           callback() | |||
|  |           return | |||
|  |         } | |||
|  |       } else if (file.relative.includes('uni-app')) { | |||
|  |         if (platform === 'uni-app') { | |||
|  |           file.path = file.path.replace(/(.*)[/\\]uni-app/, '$1') | |||
|  |         } else { | |||
|  |           callback() | |||
|  |           return | |||
|  |         } | |||
|  |       } | |||
|  |       if (platform === 'uni-app') { | |||
|  |         // uni-app 平台 vue3 要求使用 es6 模块
 | |||
|  |         let content = file.contents.toString() | |||
|  |         if (file.basename === 'prism.min.js') { | |||
|  |           content = content.replace('"undefined"!=typeof module&&module.exports&&(module.exports=Prism),', 'export default Prism;') | |||
|  |         } else if (file.extname === '.js' && !file.relative.includes('static')) { | |||
|  |           content = content.replace(/module.exports\s*=\s*/, 'export default ') | |||
|  |             .replace(/const\s+([^\s=]+)\s*=\s*require\(([^)]+)\)/g, 'import $1 from $2') | |||
|  |         } | |||
|  |         file.contents = Buffer.from(content) | |||
|  |       } else { | |||
|  |         // 小程序平台进行进一步处理
 | |||
|  |         let content = file.contents.toString() | |||
|  |         /** | |||
|  |          * 方式1: | |||
|  |          * 在注释 #if(n)def xxx 和 #endif 之间的内容会根据是否定义 xxx 决定是否保留 | |||
|  |          */ | |||
|  |         const commentReg = /\/\*[\s\S]*?\*\/|\/\/[^\n]*|<!--[\s\S]*?-->/g // 提取所有注释
 | |||
|  |         const copy = content // 拷贝一个副本用于搜索
 | |||
|  |         let match = commentReg.exec(copy) | |||
|  |         const stack = [] | |||
|  |         while (match) { | |||
|  |           if (match[0].includes('#if')) { | |||
|  |             stack.push([match[0], match.index]) | |||
|  |           } else if (match[0].includes('#endif')) { | |||
|  |             const item = stack.pop() | |||
|  |             if (!item) { | |||
|  |               throw Error('条件编译错误:存在多余的 #endif,path:' + file.path + ',content: ' + content.substr(match.index, 100)) | |||
|  |             } | |||
|  |             const def = item[0].match(/MP-[A-Z]+/gi) || [] // 取出定义条件
 | |||
|  |             let hit = false | |||
|  |             for (let i = 0; i < def.length; i++) { | |||
|  |               if (def[i] && platform === def[i].toLowerCase()) { | |||
|  |                 hit = true // 命中
 | |||
|  |                 break | |||
|  |               } | |||
|  |             } | |||
|  |             // 不匹配
 | |||
|  |             if ((item[0].includes('#ifdef') && !hit) || (item[0].includes('#ifndef') && hit)) { | |||
|  |               let fill = '' | |||
|  |               // 用空格填充
 | |||
|  |               for (let j = item[1] + item[0].length; j < match.index; j++) { | |||
|  |                 if (content[j] === '\n') { | |||
|  |                   fill += '\n' | |||
|  |                 } else { | |||
|  |                   fill += ' ' | |||
|  |                 } | |||
|  |               } | |||
|  |               content = content.substr(0, item[1] + item[0].length) + fill + content.substr(match.index) | |||
|  |             } | |||
|  |           } | |||
|  |           match = commentReg.exec(copy) | |||
|  |         } | |||
|  |         if (stack.length) { | |||
|  |           throw Error('条件编译错误:存在未闭合的 #ifdef,path:' + file.path + ',content: ' + content.substr(stack[0][1], 100)) | |||
|  |         } | |||
|  | 
 | |||
|  |         /** | |||
|  |          * 方式2: | |||
|  |          * wxml 中属性前加平台名将仅编译到该平台,如 mp-weixin:attr | |||
|  |          */ | |||
|  |         if (file.extname === '.wxml') { | |||
|  |           content = content.replace(/([^:\s]+:[^=\s]+)\s*=\s*"(.*?)"/g, ($, $1, $2) => { | |||
|  |             const platforms = $1.split(':') | |||
|  |             let name = platforms.pop() | |||
|  |             const last = platforms[platforms.length - 1] | |||
|  |             if (last && !last.includes('mp')) { | |||
|  |               name = platforms.pop() + ':' + name | |||
|  |             } | |||
|  |             if (!platforms.length) return $ | |||
|  |             let i | |||
|  |             for (i = platforms.length; i--;) { | |||
|  |               if (platform === platforms[i].toLowerCase()) break | |||
|  |             } | |||
|  |             if (i >= 0) return `${name}="${$2}"` | |||
|  |             return '' | |||
|  |           }) | |||
|  |         } | |||
|  |         file.contents = Buffer.from(content) | |||
|  |       } | |||
|  |     } | |||
|  |     this.push(file) | |||
|  |     callback() | |||
|  |   }) | |||
|  | } |