UNPKG

magix-combine

Version:

合并Magix View的html,js,css成一个js文件,并检测html,js,css中可能存在的问题

191 lines (189 loc) 8.3 kB
/* mx事件处理 1. 检测是否按要求书写的事件 2. 检测单双引号的实体转义 3. 检测不支持的写法 */ let chalk = require('chalk'); let configs = require('./util-config'); let checker = require('./checker'); let slog = require('./util-log'); let utils = require('./util'); let jsGeneric = require('./js-generic'); let tmplCmd = require('./tmpl-cmd'); //let md5 = require('./util-md5'); //let regexp = require('./util-rcache'); let acorn = require('./js-acorn'); let tmplChecker = checker.Tmpl; let removeTempReg = /[\u0002\u0001\u0003\u0006]\.?/g; let cmdReg = /\u0007\d+\u0007/g; let onlyCmdReg = /^(?:\u0007\d+\u0007)+$/; let dOutCmdReg = /<%([=!@])([\s\S]+?)%>/g; let unsupportOutCmdReg = /<%@[\s\S]+?%>/g; let stringReg = /^['"]/; let magixHolder = '\u001e'; let holder = '\u001f'; //let revisableReg = /@\{[^\{\}]+\}/g; //let eventPrefixReg = /^[^\(\)]+/; let processQuot = (str, refTmplCommands, mxEvent, e, toSrc) => { str.replace(cmdReg, cm => { let cmd = refTmplCommands[cm]; if (cmd) { cmd = cmd.replace(dOutCmdReg, (m, o, c) => { if (!onlyCmdReg.test(str)) { tmplChecker.checkMxEventParamsCMD(o, mxEvent, e, toSrc(str)); } if (o == '=') { return '<%=$eq(' + c + ')%>'; } return m; }); refTmplCommands[cm] = cmd; } }); }; let htmlQEntityReg = /(\\*)(&quot;?|&#x22;?|&#x27;?|&#34;?|&#39;?)/g; let encodeParams = (params, refTmplCommands, mxEvent, e, toSrc) => { let index = 0; let store = Object.create(null); let cmdKey = utils.uId('\u00aa', params); let cmdPHReg = new RegExp(cmdKey + '\\d+' + cmdKey, 'g'); //console.log(JSON.stringify(params)); params = '(' + params.replace(cmdReg, m => { let k = cmdKey + index++ + cmdKey; store[k] = m; return k; }) + ')'; //console.log(JSON.stringify(params)); let ast; try { ast = acorn.parse(params); } catch (ex) { //console.log(e); let origin = params.substring(1, params.length - 1).replace(cmdPHReg, m => store[m]).replace(cmdReg, m => refTmplCommands[m]); let src = toSrc(origin); slog.ever(chalk.red('[MXC Error(tmpl-attr-mxevent)] encode mx-event params error'), 'origin', chalk.magenta(src), (src != origin ? 'translate to ' + chalk.magenta(origin) : ''), chalk.red('mx-event params with template syntax must be a legal object literal'), 'e.g.', chalk.magenta('{id:{{=id}},name:\'{{if gender==\'male\'}}David{{else}}Lily{{/if}}\'}'), 'at', chalk.red(e.shortHTMLFile)); throw ex; } let modifiers = []; let processString = node => { //存储字符串,减少分析干扰 if (stringReg.test(node.raw)) { let q = node.raw.charAt(0); let raw = node.raw.slice(1, -1); let replacement = raw.replace(htmlQEntityReg, (m, s, n) => { return s && s.length % 2 ? m : s + '\\' + n; }); if (raw != replacement) { let tip = replacement .replace(cmdPHReg, m => store[m]) .replace(cmdReg, m => refTmplCommands[m]) .replace(removeTempReg, ''); let tipRaw = raw .replace(cmdPHReg, m => store[m]) .replace(cmdReg, m => refTmplCommands[m]) .replace(removeTempReg, ''); slog.ever(chalk.magenta(`[MXC Tip(tmpl-attr-mxevent)]`), chalk.red('beware!'), 'You should use', chalk.magenta(tip), 'instead of', chalk.magenta(tipRaw), 'at', chalk.grey(e.shortHTMLFile), 'in', chalk.magenta(mxEvent.replace(removeTempReg, ''))); } let eq = jsGeneric.escapeQ(replacement, q); replacement = replacement.replace(cmdPHReg, m => store[m]); processQuot(replacement, refTmplCommands, mxEvent, e, toSrc); modifiers.push({ start: node.start, end: node.end, content: q + eq + q }); } }; acorn.walk(ast, { Property(node) { let key = node.key; if (key.type == 'Literal') { processString(key); } let value = node.value; if (value.type == 'Identifier') { let cmd = value.name.replace(cmdPHReg, m => store[m]); if (onlyCmdReg.test(cmd)) { cmd = tmplCmd.recover(cmd, refTmplCommands); let modify = false; cmd.replace(dOutCmdReg, (m, o) => { modify = o == '@'; }); if (modify) { modifiers.push({ start: value.start, end: value.end, content: '\'' + value.name + '\'' }); } } else { cmd.replace(cmdReg, cm => { let oCmd = refTmplCommands[cm]; if (oCmd) { oCmd.replace(unsupportOutCmdReg, m => { m = m.replace(removeTempReg, ''); slog.ever(chalk.red('[MXC Error(tmpl-attr-mxevent)] unsupport ' + m), 'at', chalk.grey(e.shortHTMLFile), 'in', chalk.magenta(mxEvent.replace(removeTempReg, ''))); }); } }); } } }, Literal: processString }); modifiers.sort((a, b) => { //根据start大小排序,这样修改后的fn才是正确的 return a.start - b.start; }); for (let i = modifiers.length - 1, m; i >= 0; i--) { m = modifiers[i]; params = params.substring(0, m.start) + m.content + params.substring(m.end); } params = params.replace(cmdPHReg, m => store[m]); return params.slice(1, -1); }; module.exports = (e, match, refTmplCommands, toSrc) => { if (!configs.disableMagixUpdater && !e.isOldTemplate) { //增加事件前缀 match = match.replace(configs.tmplMxEventReg, (m, name, double, single) => { //查找事件 tmplChecker.checkMxEventName(name, e); if (double || single) { let originalMatch = toSrc(m); tmplChecker.checkMxEvengSingQuote(single, originalMatch, e); // m = m.replace(eventPrefixReg, match => { // return match.replace(revisableReg, c => { // tmplChecker.checkMxEventStringRevisable(c, originalMatch, e); // if (configs.debug) { // return c; // } // return md5(c, 'revisableString', configs.revisableStringPrefix); // }); // }); let left = m.indexOf('('); let right = m.lastIndexOf(')'); if (left > -1 && right > -1 && right > left) { let params = m.substring(left + 1, right).trim(); left = m.substring(0, left + 1); right = m.substring(right); //console.log(cmdReg.test(left), left, right); if (cmdReg.test(left) || cmdReg.test(right)) { right = params + right; } else if (params) { tmplChecker.checkMxEventParams(name, params, originalMatch, e); right = encodeParams(params, refTmplCommands, originalMatch, e, toSrc) + right; } let start = left.indexOf('='); let c; do { c = left.charAt(start); start++; } while (c != '"' && c != '\''); let rest = left.substring(start) + right; return left.substring(0, start) + holder + magixHolder + rest; } else { return m; } } return m; }); } return match; };