reducer.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _convertUnit = _interopRequireDefault(require("./convertUnit"));
  7. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8. function isEqual(left, right) {
  9. return left.type === right.type && left.value === right.value;
  10. }
  11. function isValueType(type) {
  12. switch (type) {
  13. case 'LengthValue':
  14. case 'AngleValue':
  15. case 'TimeValue':
  16. case 'FrequencyValue':
  17. case 'ResolutionValue':
  18. case 'EmValue':
  19. case 'ExValue':
  20. case 'ChValue':
  21. case 'RemValue':
  22. case 'VhValue':
  23. case 'VwValue':
  24. case 'VminValue':
  25. case 'VmaxValue':
  26. case 'PercentageValue':
  27. case 'Number':
  28. return true;
  29. }
  30. return false;
  31. }
  32. function flip(operator) {
  33. return operator === '+' ? '-' : '+';
  34. }
  35. function flipValue(node) {
  36. if (isValueType(node.type)) {
  37. node.value = -node.value;
  38. } else if (node.type === 'MathExpression') {
  39. if (node.operator === '*' || node.operator === '/') {
  40. node.left = flipValue(node.left);
  41. } else {
  42. node.left = flipValue(node.left);
  43. node.right = flipValue(node.right);
  44. }
  45. }
  46. return node;
  47. }
  48. function reduceAddSubExpression(node, precision) {
  49. // something + 0 => something
  50. // something - 0 => something
  51. if (isValueType(node.right.type) && node.right.value === 0) {
  52. return node.left;
  53. } // 0 + something => something
  54. if (isValueType(node.left.type) && node.left.value === 0 && node.operator === "+") {
  55. return node.right;
  56. } // 0 - something => -something
  57. if (isValueType(node.left.type) && node.left.value === 0 && node.operator === "-" && node.right.type !== "Function") {
  58. return flipValue(node.right);
  59. } // value + value
  60. // value - value
  61. if (isValueType(node.left.type) && node.left.type === node.right.type) {
  62. var operator = node.operator;
  63. var _covertNodesUnits = covertNodesUnits(node.left, node.right, precision),
  64. left = _covertNodesUnits.left,
  65. right = _covertNodesUnits.right;
  66. if (operator === "+") {
  67. left.value += right.value;
  68. } else {
  69. left.value -= right.value;
  70. }
  71. return left;
  72. } // value <op> (expr)
  73. if (node.right.type === 'MathExpression' && (node.right.operator === '+' || node.right.operator === '-')) {
  74. // something - (something + something) => something - something - something
  75. // something - (something - something) => something - something + something
  76. if ((node.right.operator === '+' || node.right.operator === '-') && node.operator === '-') {
  77. node.right.operator = flip(node.right.operator);
  78. }
  79. if (isValueType(node.left.type)) {
  80. // value + (value + something) => value + something
  81. // value + (value - something) => value - something
  82. // value - (value + something) => value - something
  83. // value - (value - something) => value + something
  84. if (node.left.type === node.right.left.type) {
  85. var _left = node.left,
  86. _operator = node.operator,
  87. _right = node.right;
  88. node.left = reduce({
  89. type: 'MathExpression',
  90. operator: _operator,
  91. left: _left,
  92. right: _right.left
  93. });
  94. node.operator = _right.operator;
  95. node.right = _right.right;
  96. return reduce(node, precision);
  97. } // something + (something + value) => dimension + something
  98. // something + (something - value) => dimension + something
  99. // something - (something + value) => dimension - something
  100. // something - (something - value) => dimension - something
  101. if (node.left.type === node.right.right.type) {
  102. var _left2 = node.left,
  103. _right2 = node.right;
  104. node.left = reduce({
  105. type: 'MathExpression',
  106. operator: _right2.operator,
  107. left: _left2,
  108. right: _right2.right
  109. });
  110. node.right = _right2.left;
  111. return reduce(node, precision);
  112. }
  113. }
  114. } // (expr) <op> value
  115. if (node.left.type === 'MathExpression' && (node.left.operator === '+' || node.left.operator === '-') && isValueType(node.right.type)) {
  116. // (value + something) + value => value + something
  117. // (value - something) + value => value - something
  118. // (value + something) - value => value + something
  119. // (value - something) - value => value - something
  120. if (node.right.type === node.left.left.type) {
  121. var _left3 = node.left,
  122. _operator2 = node.operator,
  123. _right3 = node.right;
  124. _left3.left = reduce({
  125. type: 'MathExpression',
  126. operator: _operator2,
  127. left: _left3.left,
  128. right: _right3
  129. }, precision);
  130. return reduce(_left3, precision);
  131. } // (something + dimension) + dimension => something + dimension
  132. // (something - dimension) + dimension => something - dimension
  133. // (something + dimension) - dimension => something + dimension
  134. // (something - dimension) - dimension => something - dimension
  135. if (node.right.type === node.left.right.type) {
  136. var _left4 = node.left,
  137. _operator3 = node.operator,
  138. _right4 = node.right;
  139. if (_left4.operator === '-') {
  140. _left4.operator = _operator3 === '-' ? '-' : '+';
  141. _left4.right = reduce({
  142. type: 'MathExpression',
  143. operator: _operator3 === '-' ? '+' : '-',
  144. left: _right4,
  145. right: _left4.right
  146. }, precision);
  147. } else {
  148. _left4.right = reduce({
  149. type: 'MathExpression',
  150. operator: _operator3,
  151. left: _left4.right,
  152. right: _right4
  153. }, precision);
  154. }
  155. if (_left4.right.value < 0) {
  156. _left4.right.value *= -1;
  157. _left4.operator = _left4.operator === '-' ? '+' : '-';
  158. }
  159. _left4.parenthesized = node.parenthesized;
  160. return reduce(_left4, precision);
  161. }
  162. } // (expr) + (expr) => number
  163. // (expr) - (expr) => number
  164. if (node.right.type === 'MathExpression' && node.left.type === 'MathExpression') {
  165. if (isEqual(node.left.right, node.right.right)) {
  166. var newNodes = covertNodesUnits(node.left.left, node.right.left, precision);
  167. node.left = newNodes.left;
  168. node.right = newNodes.right;
  169. return reduce(node);
  170. }
  171. if (isEqual(node.left.right, node.right.left)) {
  172. var _newNodes = covertNodesUnits(node.left.left, node.right.right, precision);
  173. node.left = _newNodes.left;
  174. node.right = _newNodes.right;
  175. return reduce(node);
  176. }
  177. }
  178. return node;
  179. }
  180. function reduceDivisionExpression(node) {
  181. if (!isValueType(node.right.type)) {
  182. return node;
  183. }
  184. if (node.right.type !== 'Number') {
  185. throw new Error(`Cannot divide by "${node.right.unit}", number expected`);
  186. }
  187. if (node.right.value === 0) {
  188. throw new Error('Cannot divide by zero');
  189. } // something / value
  190. if (isValueType(node.left.type)) {
  191. node.left.value /= node.right.value;
  192. return node.left;
  193. }
  194. return node;
  195. }
  196. function reduceMultiplicationExpression(node) {
  197. // (expr) * number
  198. if (node.left.type === 'MathExpression' && node.right.type === 'Number') {
  199. if (isValueType(node.left.left.type) && isValueType(node.left.right.type)) {
  200. node.left.left.value *= node.right.value;
  201. node.left.right.value *= node.right.value;
  202. return node.left;
  203. }
  204. } // something * number
  205. if (isValueType(node.left.type) && node.right.type === 'Number') {
  206. node.left.value *= node.right.value;
  207. return node.left;
  208. } // number * (expr)
  209. if (node.left.type === 'Number' && node.right.type === 'MathExpression') {
  210. if (isValueType(node.right.left.type) && isValueType(node.right.right.type)) {
  211. node.right.left.value *= node.left.value;
  212. node.right.right.value *= node.left.value;
  213. return node.right;
  214. }
  215. } // number * something
  216. if (node.left.type === 'Number' && isValueType(node.right.type)) {
  217. node.right.value *= node.left.value;
  218. return node.right;
  219. }
  220. return node;
  221. }
  222. function covertNodesUnits(left, right, precision) {
  223. switch (left.type) {
  224. case 'LengthValue':
  225. case 'AngleValue':
  226. case 'TimeValue':
  227. case 'FrequencyValue':
  228. case 'ResolutionValue':
  229. if (right.type === left.type && right.unit && left.unit) {
  230. var converted = (0, _convertUnit.default)(right.value, right.unit, left.unit, precision);
  231. right = {
  232. type: left.type,
  233. value: converted,
  234. unit: left.unit
  235. };
  236. }
  237. return {
  238. left,
  239. right
  240. };
  241. default:
  242. return {
  243. left,
  244. right
  245. };
  246. }
  247. }
  248. function reduce(node, precision) {
  249. if (node.type === "MathExpression") {
  250. node.left = reduce(node.left, precision);
  251. node.right = reduce(node.right, precision);
  252. switch (node.operator) {
  253. case "+":
  254. case "-":
  255. return reduceAddSubExpression(node, precision);
  256. case "/":
  257. return reduceDivisionExpression(node, precision);
  258. case "*":
  259. return reduceMultiplicationExpression(node, precision);
  260. }
  261. return node;
  262. }
  263. return node;
  264. }
  265. var _default = reduce;
  266. exports.default = _default;
  267. module.exports = exports.default;