mirror of
https://github.com/S2-/minifyfromhtml.git
synced 2025-08-03 20:30:04 +02:00
96 lines
2.5 KiB
JavaScript
96 lines
2.5 KiB
JavaScript
"use strict";
|
|
|
|
const operators = new Set(["+", "-", "*", "%", "<<", ">>", ">>>", "&", "|", "^", "/", "**"]);
|
|
const updateOperators = new Set(["+", "-"]);
|
|
|
|
module.exports = t => {
|
|
function simplify(path) {
|
|
const rightExpr = path.get("right");
|
|
const leftExpr = path.get("left");
|
|
|
|
if (path.node.operator !== "=") {
|
|
return;
|
|
}
|
|
|
|
const canBeUpdateExpression = rightExpr.get("right").isNumericLiteral() && rightExpr.get("right").node.value === 1 && updateOperators.has(rightExpr.node.operator);
|
|
|
|
if (leftExpr.isMemberExpression()) {
|
|
const leftPropNames = getPropNames(leftExpr);
|
|
const rightPropNames = getPropNames(rightExpr.get("left"));
|
|
|
|
if (!leftPropNames || leftPropNames.indexOf(undefined) > -1 || !rightPropNames || rightPropNames.indexOf(undefined) > -1 || !operators.has(rightExpr.node.operator) || !areArraysEqual(leftPropNames, rightPropNames)) {
|
|
return;
|
|
}
|
|
} else {
|
|
if (!rightExpr.isBinaryExpression() || !operators.has(rightExpr.node.operator) || leftExpr.node.name !== rightExpr.node.left.name) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
let newExpression; // special case x=x+1 --> ++x
|
|
|
|
if (canBeUpdateExpression) {
|
|
newExpression = t.updateExpression(rightExpr.node.operator + rightExpr.node.operator, t.clone(leftExpr.node), true
|
|
/* prefix */
|
|
);
|
|
} else {
|
|
newExpression = t.assignmentExpression(rightExpr.node.operator + "=", t.clone(leftExpr.node), t.clone(rightExpr.node.right));
|
|
}
|
|
|
|
path.replaceWith(newExpression);
|
|
}
|
|
|
|
return {
|
|
simplify
|
|
};
|
|
};
|
|
|
|
function areArraysEqual(arr1, arr2) {
|
|
return arr1.every((value, index) => {
|
|
return String(value) === String(arr2[index]);
|
|
});
|
|
}
|
|
|
|
function getPropNames(path) {
|
|
if (!path.isMemberExpression()) {
|
|
return;
|
|
}
|
|
|
|
let obj = path.get("object");
|
|
const prop = path.get("property");
|
|
const propNames = [getName(prop.node)];
|
|
|
|
while (obj.type === "MemberExpression") {
|
|
const node = obj.get("property").node;
|
|
|
|
if (node) {
|
|
propNames.push(getName(node));
|
|
}
|
|
|
|
obj = obj.get("object");
|
|
}
|
|
|
|
propNames.push(getName(obj.node));
|
|
return propNames;
|
|
}
|
|
|
|
function getName(node) {
|
|
if (node.type === "ThisExpression") {
|
|
return "this";
|
|
}
|
|
|
|
if (node.type === "Super") {
|
|
return "super";
|
|
}
|
|
|
|
if (node.type === "NullLiteral") {
|
|
return "null";
|
|
} // augment identifiers so that they don't match
|
|
// string/number literals
|
|
// but still match against each other
|
|
|
|
|
|
return node.name ? node.name + "_" : node.value
|
|
/* Literal */
|
|
;
|
|
} |