wsp-toolkit
Version:
Personal toolbox
690 lines (651 loc) • 15.9 kB
JavaScript
// src/functions/and/and.ts
function and(...conditions) {
for (const expr of conditions) {
if (typeof expr === "function" && !expr()) return false;
if (expr === false) return false;
}
return true;
}
// src/functions/concatMap/index.ts
var concatMap = (f, ...xs) => {
const result = [];
for (let x of xs) {
if (Array.isArray(x)) {
for (let i of x) {
result.push(f(i));
}
} else {
result.push(f(x));
}
}
return result;
};
// src/functions/curry/curry.ts
var curry = (fn) => {
const curry2 = (...args) => {
if (args.length >= fn.length) {
return fn(...args);
}
return curry2.bind(null, ...args);
};
return curry2;
};
// src/functions/isNil/index.ts
function isNil(x) {
return x === null || x === void 0;
}
// src/functions/throttle/throttle.ts
function throttle(fn, wait, opts = {}) {
const { maxWait = wait, leading = false, trailing = true } = opts || {};
let timerId;
let lastInvokeTime = null;
function reset() {
timerId = null;
lastInvokeTime = null;
}
function throttled(...args) {
clearTimeout(timerId);
const now = Date.now();
if (isNil(lastInvokeTime)) {
if (leading) {
fn(...args);
}
lastInvokeTime = now;
}
if (now - lastInvokeTime >= maxWait && maxWait !== 0) {
lastInvokeTime = now;
fn(...args);
} else {
timerId = setTimeout(() => {
reset();
if (!trailing) return;
fn(...args);
}, wait);
}
}
return throttled;
}
// src/functions/debounce/debounce.ts
function debounce(func, wait, opts = {}) {
return throttle(func, wait, {
leading: opts.leading,
trailing: opts.trailing,
maxWait: 0
});
}
// src/functions/decimalLength/index.ts
var decimalLength = (x) => {
const str = typeof x === "string" ? x : x.toString();
const idx = str.indexOf(".");
if (idx === -1) return 0;
return str.length - idx - 1;
};
// src/functions/identity/identity.ts
function identity(x) {
return x;
}
// src/functions/isExist/isExist.ts
function isExist(x) {
return x != null;
}
// src/functions/typeOf/typeOf.ts
function typeOf(x) {
const type = Object.prototype.toString.call(x);
return type.replace(/\[\w+ (\w+)]/, "$1");
}
// src/functions/isEmpty/isEmpty.ts
function isEmpty(x) {
if (isNil(x)) return true;
if (typeof x === "string") {
return x.length === 0;
}
if (Array.isArray(x)) {
return x.length === 0;
}
if (typeOf(x) === "Object") {
return Object.keys(x).length === 0;
}
if (typeOf(x) === "FormData") {
const isDone = x.keys().next().done;
return isExist(isDone) ? isDone : true;
}
return false;
}
// src/functions/isIterable/index.ts
var isIterable = (x) => {
return isExist(x) && typeof x[Symbol.iterator] === "function";
};
// src/internal/isNumber/isNumber.ts
function isNumber(x) {
return typeof x === "number";
}
// src/functions/isSafeNum/isSafeNum.ts
function isSafeNum(x) {
if (x == null) return false;
return isNumber(x) && isFinite(x) && Number.MIN_SAFE_INTEGER <= x && x <= Number.MAX_SAFE_INTEGER;
}
// src/functions/iterative/index.ts
function iterative(fn) {
return function(subject, ...rest) {
if (isIterable(subject)) {
const ret = [];
for (let obj of subject) {
ret.push(fn(obj, ...rest));
}
return ret;
}
return fn(subject, ...rest);
};
}
// src/functions/at/at.ts
var at = curry((index, xs) => {
return xs[index < 0 ? xs.length + index : index];
});
// src/functions/last/index.ts
function last(xs) {
return at(-1, xs);
}
// src/functions/matrixTo/matrixTo.ts
function matrixTo(matrixStr) {
const arr = matrixStr.replace("matrix(", "").replace(")", "").split(",").map((x) => Number(x));
const cos = arr[0], sin = arr[1], tan = sin / cos, rotate = Math.atan(tan) * 180 / Math.PI, scale = cos / Math.cos(Math.PI / 180 * rotate);
return {
x: arr[4],
y: arr[5],
scale,
rotate
};
}
// src/functions/once/once.ts
function once(fn) {
let done = false;
let result;
return (a) => {
if (done) return result;
done = true;
result = fn(a);
return result;
};
}
// src/functions/or/or.ts
function or(...conditions) {
for (const expr of conditions) {
if (typeof expr === "function" && expr()) return true;
if (expr === true) return true;
}
return false;
}
// src/functions/pipe/pipe.ts
function pipe(...fns) {
return (...args) => {
let res = args;
for (let fn of fns) {
res = [fn(...res)];
}
return res[0];
};
}
// src/internal/propStrToList/propStrToList.ts
function propStrToList(props) {
const res = [];
const leftBrackets = [];
const quotations = [];
let text = "";
const isInt = (token) => /^\d+$/.test(token);
const isQuotation = (x) => [`'`, `"`].includes(x);
const last2 = (xs) => xs[xs.length - 1];
const initToken = (isBraceMatching) => {
if (!isEmpty(text) || isBraceMatching === true) {
if (isInt(text)) {
res.push(parseInt(text));
} else {
res.push(text);
}
}
text = "";
};
for (let alpha of props) {
if (isQuotation(alpha)) {
if (last2(quotations) === alpha) {
quotations.pop();
initToken(true);
continue;
}
initToken();
quotations.push(alpha);
continue;
}
if (alpha === "[" && isEmpty(quotations)) {
initToken();
leftBrackets.push(alpha);
continue;
}
if (alpha === "]" && isEmpty(quotations)) {
const leftBracket = leftBrackets.pop();
if (isNil(leftBracket)) {
throw new SyntaxError("Unexpected token ']'");
}
initToken();
continue;
}
if (alpha === ".") {
if (isEmpty(leftBrackets) && isEmpty(quotations)) {
initToken();
continue;
}
}
text += alpha;
}
initToken();
if (!isEmpty(leftBrackets)) {
throw new SyntaxError("\u62EC\u53F7\u6570\u91CF\u4E0D\u5339\u914D");
}
if (!isEmpty(quotations)) {
throw new SyntaxError("\u5F15\u53F7\u6570\u91CF\u4E0D\u5339\u914D");
}
return res;
}
// src/functions/prop/index.ts
var prop = curry(
(props, subject) => {
if (typeof props === "string") {
props = propStrToList(props);
}
if (!Array.isArray(props)) {
props = [props];
}
return props.reduce((res, key) => {
if (isNil(res)) return;
return res[key];
}, subject);
}
);
// src/functions/sleep/sleep.ts
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(() => resolve(ms), ms);
});
}
// src/functions/splitIntegerDecimal/splitIntegerDecimal.ts
function splitIntegerDecimal(amount) {
if (isSafeNum(amount)) {
amount = amount.toString();
}
const res = [amount, ""];
if (typeof amount !== "string") {
return res;
}
const match = amount.match(/\.(\d+)$/);
const pointIndex = match && isExist(match.index) ? match.index : -1;
const hasOnlyPoint = amount.indexOf(".") === pointIndex;
if (!hasOnlyPoint || match && typeof match[1] !== "string") return res;
const isDecimal = match ? isSafeNum(parseInt(match[1])) : false;
if (!isDecimal) return res;
res[0] = amount.substring(0, pointIndex);
res[1] = amount.substring(pointIndex + 1, amount.length);
return res;
}
// src/functions/toArray/toArray.ts
function toArray(x) {
if (Array.isArray(x)) return x;
if (isNil(x)) return [];
if (isNumber(x) || typeOf(x) === "Boolean") {
return [x];
}
if (isIterable(x)) {
return Array.from(x);
}
return [];
}
// src/functions/toggle/toggle.ts
function toggle(fns) {
const endIndex = fns.length - 1;
let crtIndex = 0;
return function(args) {
const fn = fns[crtIndex];
crtIndex += 1;
if (crtIndex > endIndex) {
crtIndex = 0;
}
return typeof fn === "function" ? fn(args) : fn;
};
}
// src/functions/toNumberStr/index.ts
var numberMap = {
"0": true,
"1": true,
"2": true,
"3": true,
"4": true,
"5": true,
"6": true,
"7": true,
"8": true,
"9": true
};
var legalCharMap = {
"-": true,
"+": true,
".": true
};
function toNumberStr(x) {
if (typeof x === "number") return String(x);
if (typeof x === "boolean") return x ? "1" : "0";
if (Array.isArray(x)) {
return toNumberStr(x.flat(Infinity).join(""));
}
if (typeof x !== "string") return isEmpty(x) ? "0" : "1";
let symbol = "";
let res = "";
let resType = 0 /* unknown */;
let pointIndex = -1;
let nonzeroEnd = 0;
const initResType = (char) => {
switch (char) {
case "-":
symbol = symbol ? "" : "-";
return;
case "+":
symbol = symbol ? symbol : "";
return;
case ".":
resType = 6 /* floatDot */;
res = "0.";
pointIndex = 1;
return;
case "0":
resType = 4 /* zero */;
res = char;
return;
}
if (numberMap[char]) {
resType = 1 /* int */;
res += char;
}
};
for (let l of x) {
if (!(legalCharMap[l] || numberMap[l])) continue;
if (resType === 0 /* unknown */) {
initResType(l);
continue;
}
switch (resType) {
// @ts-ignore "0" 这里能走进去,ts错误检查
case 4 /* zero */:
if (l === "0") continue;
if (l === ".") {
resType = 5 /* zeroDot */;
pointIndex = res.length;
res += l;
} else if (numberMap[l]) {
resType = 1 /* int */;
res = l;
}
continue;
// "0."
case 5 /* zeroDot */:
if (l === "0") {
resType = 3 /* floatZeroDecimal */;
res += l;
} else if (numberMap[l]) {
resType = 2 /* float */;
res += l;
nonzeroEnd = res.length;
}
continue;
// "[1-9]+\d*"
case 1 /* int */:
if (l === ".") {
resType = 6 /* floatDot */;
pointIndex = res.length;
res += l;
} else if (numberMap[l]) {
res += l;
}
continue;
// "\d+\."
case 6 /* floatDot */:
if (l === "0") {
resType = 3 /* floatZeroDecimal */;
res += l;
} else if (numberMap[l]) {
resType = 2 /* float */;
res += l;
nonzeroEnd = res.length;
}
continue;
// 小数部分全部为0
case 3 /* floatZeroDecimal */:
if (l === "0") {
res += l;
} else if (numberMap[l]) {
resType = 2 /* float */;
res += l;
nonzeroEnd = res.length;
}
continue;
case 2 /* float */:
if (numberMap[l]) {
res += l;
if (l !== "0") {
nonzeroEnd = res.length;
}
}
}
}
if (resType === 5 /* zeroDot */) return symbol ? "0" : "-0";
if (resType === 3 /* floatZeroDecimal */ || resType === 6 /* floatDot */)
return `${symbol}${res.slice(0, pointIndex)}`;
if (resType === 2 /* float */)
return `${symbol}${res.slice(0, nonzeroEnd)}`;
return isEmpty(res) || resType === 0 /* unknown */ ? `${symbol}0` : `${symbol}${res}`;
}
// src/functions/treeEach/index.ts
function treeEach(xs, fn, options) {
const {
childKey = "children",
filterNull = true,
filterEmpty = true,
startLeaf = false
} = options || {};
if (!Array.isArray(xs)) return [];
const each = (list, level, parent) => {
return list.reduce((result, value, index, array) => {
let children = isExist(value) ? value[childKey] : null;
if (startLeaf && Array.isArray(children)) {
children = each(children, level + 1, value);
}
const newItem = fn(value, index, array, level, parent);
if (!startLeaf && Array.isArray(children)) {
children = each(children, level + 1, value);
}
if (typeof newItem === "object" && isExist(newItem)) {
if (isNil(children) && filterNull) {
Reflect.deleteProperty(newItem, childKey);
} else if (isExist(children) && isEmpty(children) && filterEmpty) {
Reflect.deleteProperty(newItem, childKey);
} else {
newItem[childKey] = children;
}
} else if (filterNull && isNil(newItem)) {
return result;
}
result.push(newItem);
return result;
}, []);
};
return each(xs, 0, null);
}
// src/functions/unique/unique.ts
function unique(arr, property) {
if (!property) {
return [...new Set(arr)];
}
const record = /* @__PURE__ */ new Map();
const result = [];
for (let crt of arr) {
const val = typeof property === "function" ? property(crt) : typeof crt === "object" && isExist(crt) ? prop(property, crt) : crt;
if (record.get(val)) {
continue;
}
record.set(val, true);
result.push(crt);
}
return result;
}
// src/functions/zip/index.ts
var zip = (...xs) => {
const r = [];
let nple = [];
const length = Math.min.apply(
null,
xs.map((x) => x.length)
);
for (let i = 0; i < length; i++) {
xs.forEach((x) => nple.push(x[i]));
r.push(nple);
nple = [];
}
return r;
};
// src/functions/zipWith/index.ts
var zipWidth = (op, ...xs) => zip(...xs).map((x) => x.reduce(op));
// src/functions/ifElse/index.ts
var ifElse = (condition, onTrue, onFalse) => {
return (arg) => {
if (condition(arg)) {
return onTrue(arg);
} else {
return onFalse(arg);
}
};
};
// src/functions/toPromiseTuple/index.ts
function toPromiseTuple(promise, errorExt) {
return promise.then((data) => [null, data]).catch((err) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt);
return [parsedError, void 0];
}
return [err, void 0];
});
}
// src/functions/promiseTry/index.ts
async function promiseTry(func, ...args) {
return new Promise((resolve) => {
resolve(func(...args));
});
}
// src/functions/when/index.ts
var when = curry(
(pred, whenTrueFn, x) => {
return pred(x) ? whenTrueFn(x) : x;
}
);
// src/functions/clamp/clamp.ts
function clamp(min, max, val) {
return Math.max(min, Math.min(max, val));
}
// src/functions/emptyFn/index.ts
function emptyFn() {
}
// src/struct/Vector/Vector.ts
function pointSub(a, b) {
return {
x: a.x - b.x,
y: a.y - b.y
};
}
function getLength(v) {
const x = Math.abs(v.x);
const y = Math.abs(v.y);
return Math.sqrt(x * x + y * y);
}
function getDirection(v1, v2) {
const res = v1.x * v2.y - v2.x * v1.y;
if (res === 0) return 0;
return res > 0 ? 1 : -1;
}
function getAngle(v1, v2) {
const direction = getDirection(v1, v2);
const len1 = v1.getLength();
const len2 = v2.getLength();
const mr = len1 * len2;
if (mr === 0) return 0;
const dot = v1.x * v2.x + v1.y * v2.y;
let r = dot / mr;
if (r > 1) r = 1;
if (r < -1) r = -1;
const res = Math.acos(r) * direction * 180 / Math.PI;
return res === 0 ? 0 : res;
}
function getScale(v1, v2) {
return v2.getLength() / v1.getLength();
}
var Vector = class _Vector {
constructor(a, b) {
a = a || { x: 0, y: 0 };
b = b || { x: 0, y: 0 };
const { x, y } = pointSub(a, b);
this.x = x;
this.y = y;
}
static of(a, b) {
return new _Vector(a, b);
}
// 获取向量模
getLength() {
return getLength(this);
}
// 获取旋转角度
getAngle(vector) {
return getAngle(this, vector);
}
// 获取旋转方向
getDirection(vector) {
return getDirection(this, vector);
}
// 获取缩放比例
getScale(vector) {
return getScale(this, vector);
}
};
export {
Vector,
and,
at,
clamp,
concatMap,
curry,
debounce,
decimalLength,
emptyFn,
identity,
ifElse,
isEmpty,
isExist,
isIterable,
isNil,
isSafeNum,
iterative,
last,
matrixTo,
once,
or,
pipe,
promiseTry,
prop,
sleep,
splitIntegerDecimal,
throttle,
toArray,
toNumberStr,
toPromiseTuple,
toggle,
treeEach,
typeOf,
unique,
when,
zip,
zipWidth
};