magix-combine
Version:
合并Magix View的html,js,css成一个js文件,并检测html,js,css中可能存在的问题
234 lines (231 loc) • 7.44 kB
JavaScript
//let utils = require('./util');
let acorn = require('./js-acorn');
let stringReg = /^['"]/;
let qmap = {
'\'': ''',
'"': '"'
};
let qReg = /['"]/g;
let escapeQ = str => str.replace(qReg, m => qmap[m]);
module.exports = {
escapeQ,
trimParentheses(expr) {
expr = expr.trim();
let start = 0, c,
stack = [], end = 0, last = 0;
while (start < expr.length) {
c = expr[start];
if (c == '(') {
stack.push({
c,
i: start
});
} else if (c == ')') {
stack.push({
c,
i: start
});
end = start;
} else if (c != ' ') {
last = start;
if (!stack.length) {
break;
}
}
start++;
}
if (last > end) {
stack = [];
}
let matches = [], m, check = [];
for (start = 0; start < stack.length; start++) {
m = stack[start];
check.push(m);
if (m.c == '(') {
matches.push(m);
} else if (m.c == ')') {
c = matches.pop();
if (c) {
m.m = c.i;
c.m = m.i;
}
}
}
let trimCount = 0;
let compare = expr;
do {
let first = check.shift();
let last = check.pop();
if (last && first.i === last.m && last.i === first.m) {
let c = expr.substring(first.i, first.m + 1);
if (c != compare) {
break;
}
compare = c.substring(1, c.length - 1).trim();
trimCount++;
} else {
break;
}
} while (check.length);
return expr.substring(trimCount, expr.length - trimCount).trim();
},
splitExpr(expr) { //拆分表达式,如"list[i].name[object[key[value]]]" => ["list", "[i]", "name", "[object[key[value]]]"]
expr = this.trimParentheses(expr);
let stack = [];
let temp = '';
let max = expr.length;
let i = 0,
c, opened = 0;
while (i < max) {
c = expr.charAt(i);
if (c == '.') {
if (!opened) {
if (temp) {
stack.push(temp);
}
temp = '';
} else {
temp += c;
}
} else if (c == '[') {
if (!opened && temp) {
stack.push(temp);
temp = '';
}
opened++;
temp += c;
} else if (c == ']') {
opened--;
temp += c;
if (!opened && temp) {
stack.push(temp);
temp = '';
}
} else {
temp += c;
}
i++;
}
if (temp) {
stack.push(temp);
}
return stack;
},
splitSafeguardExpr(expr) {//拆分 a[b&&b[c]] && a[b&&b[c]].d => [ a[b&&b[c]] ,a[b&&b[c]].d ]
let stack = [];
let temp = '';
let max = expr.length;
let i = 0,
c, opened = 0;
while (i < max) {
c = expr.charAt(i);
if (c == '&' && expr.charAt(i + 1) == '&' && !opened && temp) {
stack.push(temp);
temp = '';
i++;
} else {
if (c == '[') {
opened++;
} else if (c == ']') {
opened--;
}
temp += c;
}
i++;
}
if (temp) {
stack.push(temp);
}
return stack;
},
parseObject(str, startChar, endChar) {
str = '(' + str.trim() + ')';
let ast = acorn.parse(str);
let modifiers = [];
let processString = node => {
if (stringReg.test(node.raw)) {
let q = node.raw.charAt(0);
let value = node.raw.slice(1, -1);
if (q == '"') {
q = '\'';
value = value.replace(/'/g, '\\\'');
}
value = escapeQ(value);
modifiers.push({
start: node.start,
end: node.end,
value: q + value + q
});
}
};
let pushExpressions = e => {
if (e.type == 'Identifier' ||
e.type == 'MemberExpression' ||
e.type == 'CallExpression' ||
e.type == 'FunctionExpression' ||
e.type == 'ConditionalExpression' ||
e.type == 'BinaryExpression' ||
e.type == 'ArrowFunctionExpression' ||
e.type == 'LogicalExpression' ||
e.type == 'UnaryExpression' ||
e.type == 'ThisExpression' ||
e.type == 'NewExpression' ||
e.type == 'UpdateExpression') {
let oValue = str.substring(e.start, e.end);
modifiers.push({
start: e.start,
end: e.end,
value: endChar + '",' + oValue + ',"' + startChar
});
}
};
acorn.walk(ast, {
Property(node) {
let key = node.key;
let value = node.value;
if (key.type == 'Literal') {
processString(key);
}
if (node.shorthand) {
modifiers.push({
start: node.end,
end: node.end,
value: ':' + endChar + '",' + str.substring(value.start, value.end) + ',"' + startChar
});
} else if (node.computed) {
modifiers.push({
start: key.start - 1,
end: key.end + 1,
value: endChar + '",' + str.substring(key.start, key.end) + ',"' + startChar
});
} else {
pushExpressions(value);
}
},
ArrayExpression(node) {
for (let e of node.elements) {
pushExpressions(e);
}
},
Literal: processString
});
modifiers.sort((a, b) => { //根据start大小排序,这样修改后的fn才是正确的
return a.start - b.start;
});
for (let i = modifiers.length, m, pm, offset; i-- > 0;) {
m = modifiers[i];
offset = m.value.length - m.end + m.start;
for (let j = i; j--;) {
pm = modifiers[j];
if (pm.end > m.end) {
pm.end += offset;
}
}
}
for (let i = modifiers.length, m; i--;) {
m = modifiers[i];
str = str.substring(0, m.start) + m.value + str.substring(m.end);
}
return '"' + startChar + str.slice(1, -1) + '"';
}
};