153 lines
5.1 KiB
JavaScript
153 lines
5.1 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
function _export(target, all) {
|
|
for(var name in all)Object.defineProperty(target, name, {
|
|
enumerable: true,
|
|
get: all[name]
|
|
});
|
|
}
|
|
_export(exports, {
|
|
hasMathFn: function() {
|
|
return hasMathFn;
|
|
},
|
|
addWhitespaceAroundMathOperators: function() {
|
|
return addWhitespaceAroundMathOperators;
|
|
}
|
|
});
|
|
const LOWER_A = 0x61;
|
|
const LOWER_Z = 0x7a;
|
|
const UPPER_A = 0x41;
|
|
const UPPER_Z = 0x5a;
|
|
const LOWER_E = 0x65;
|
|
const UPPER_E = 0x45;
|
|
const ZERO = 0x30;
|
|
const NINE = 0x39;
|
|
const ADD = 0x2b;
|
|
const SUB = 0x2d;
|
|
const MUL = 0x2a;
|
|
const DIV = 0x2f;
|
|
const OPEN_PAREN = 0x28;
|
|
const CLOSE_PAREN = 0x29;
|
|
const COMMA = 0x2c;
|
|
const SPACE = 0x20;
|
|
const PERCENT = 0x25;
|
|
const MATH_FUNCTIONS = [
|
|
"calc",
|
|
"min",
|
|
"max",
|
|
"clamp",
|
|
"mod",
|
|
"rem",
|
|
"sin",
|
|
"cos",
|
|
"tan",
|
|
"asin",
|
|
"acos",
|
|
"atan",
|
|
"atan2",
|
|
"pow",
|
|
"sqrt",
|
|
"hypot",
|
|
"log",
|
|
"exp",
|
|
"round"
|
|
];
|
|
function hasMathFn(input) {
|
|
return input.indexOf("(") !== -1 && MATH_FUNCTIONS.some((fn)=>input.includes(`${fn}(`));
|
|
}
|
|
function addWhitespaceAroundMathOperators(input) {
|
|
// Bail early if there are no math functions in the input
|
|
if (!MATH_FUNCTIONS.some((fn)=>input.includes(fn))) {
|
|
return input;
|
|
}
|
|
let result = "";
|
|
let formattable = [];
|
|
let valuePos = null;
|
|
let lastValuePos = null;
|
|
for(let i = 0; i < input.length; i++){
|
|
let char = input.charCodeAt(i);
|
|
// Track if we see a number followed by a unit, then we know for sure that
|
|
// this is not a function call.
|
|
if (char >= ZERO && char <= NINE) {
|
|
valuePos = i;
|
|
} else if (valuePos !== null && (char === PERCENT || char >= LOWER_A && char <= LOWER_Z || char >= UPPER_A && char <= UPPER_Z)) {
|
|
valuePos = i;
|
|
} else {
|
|
lastValuePos = valuePos;
|
|
valuePos = null;
|
|
}
|
|
// Determine if we're inside a math function
|
|
if (char === OPEN_PAREN) {
|
|
result += input[i];
|
|
// Scan backwards to determine the function name. This assumes math
|
|
// functions are named with lowercase alphanumeric characters.
|
|
let start = i;
|
|
for(let j = i - 1; j >= 0; j--){
|
|
let inner = input.charCodeAt(j);
|
|
if (inner >= ZERO && inner <= NINE) {
|
|
start = j // 0-9
|
|
;
|
|
} else if (inner >= LOWER_A && inner <= LOWER_Z) {
|
|
start = j // a-z
|
|
;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
let fn = input.slice(start, i);
|
|
// This is a known math function so start formatting
|
|
if (MATH_FUNCTIONS.includes(fn)) {
|
|
formattable.unshift(true);
|
|
continue;
|
|
} else if (formattable[0] && fn === "") {
|
|
formattable.unshift(true);
|
|
continue;
|
|
}
|
|
// This is not a known math function so don't format it
|
|
formattable.unshift(false);
|
|
continue;
|
|
} else if (char === CLOSE_PAREN) {
|
|
result += input[i];
|
|
formattable.shift();
|
|
} else if (char === COMMA && formattable[0]) {
|
|
result += `, `;
|
|
continue;
|
|
} else if (char === SPACE && formattable[0] && result.charCodeAt(result.length - 1) === SPACE) {
|
|
continue;
|
|
} else if ((char === ADD || char === MUL || char === DIV || char === SUB) && formattable[0]) {
|
|
let trimmed = result.trimEnd();
|
|
let prev = trimmed.charCodeAt(trimmed.length - 1);
|
|
let prevPrev = trimmed.charCodeAt(trimmed.length - 2);
|
|
let next = input.charCodeAt(i + 1);
|
|
// Do not add spaces for scientific notation, e.g.: `-3.4e-2`
|
|
if ((prev === LOWER_E || prev === UPPER_E) && prevPrev >= ZERO && prevPrev <= NINE) {
|
|
result += input[i];
|
|
continue;
|
|
} else if (prev === ADD || prev === MUL || prev === DIV || prev === SUB) {
|
|
result += input[i];
|
|
continue;
|
|
} else if (prev === OPEN_PAREN || prev === COMMA) {
|
|
result += input[i];
|
|
continue;
|
|
} else if (input.charCodeAt(i - 1) === SPACE) {
|
|
result += `${input[i]} `;
|
|
} else if (// Previous is a digit
|
|
prev >= ZERO && prev <= NINE || // Next is a digit
|
|
next >= ZERO && next <= NINE || // Previous is end of a function call (or parenthesized expression)
|
|
prev === CLOSE_PAREN || // Next is start of a parenthesized expression
|
|
next === OPEN_PAREN || // Next is an operator
|
|
next === ADD || next === MUL || next === DIV || next === SUB || // Previous position was a value (+ unit)
|
|
lastValuePos !== null && lastValuePos === i - 1) {
|
|
result += ` ${input[i]} `;
|
|
} else {
|
|
result += input[i];
|
|
}
|
|
} else {
|
|
result += input[i];
|
|
}
|
|
}
|
|
return result;
|
|
}
|