@ztimson/utils 0.28.13 → 0.28.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/color.d.ts +15 -2
- package/dist/index.cjs +119 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +119 -38
- package/dist/index.mjs.map +1 -1
- package/dist/math.d.ts +2 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -665,13 +665,101 @@ class Cache {
|
|
|
665
665
|
/** Get all cached items */
|
|
666
666
|
values = this.all;
|
|
667
667
|
}
|
|
668
|
-
function
|
|
669
|
-
|
|
668
|
+
function dec2Frac(num, maxDen = 1e3) {
|
|
669
|
+
let sign = Math.sign(num);
|
|
670
|
+
num = Math.abs(num);
|
|
671
|
+
if (Number.isInteger(num)) return sign * num + "";
|
|
672
|
+
let closest = { n: 0, d: 1, diff: Math.abs(num) };
|
|
673
|
+
for (let d = 1; d <= maxDen; d++) {
|
|
674
|
+
let n = Math.round(num * d);
|
|
675
|
+
let diff = Math.abs(num - n / d);
|
|
676
|
+
if (diff < closest.diff) {
|
|
677
|
+
closest = { n, d, diff };
|
|
678
|
+
if (diff < 1e-8) break;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
let integer = Math.floor(closest.n / closest.d);
|
|
682
|
+
let numerator = closest.n - integer * closest.d;
|
|
683
|
+
return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
|
|
684
|
+
}
|
|
685
|
+
function dec2Hex(num) {
|
|
686
|
+
const hex = Math.round(num * 255).toString(16);
|
|
687
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
688
|
+
}
|
|
689
|
+
function frac2Dec(frac) {
|
|
690
|
+
let split = frac.split(" ");
|
|
691
|
+
const whole = split.length == 2 ? Number(split[0]) : 0;
|
|
692
|
+
split = split.pop().split("/");
|
|
693
|
+
return whole + Number(split[0]) / Number(split[1]);
|
|
694
|
+
}
|
|
695
|
+
function numSuffix(n) {
|
|
696
|
+
const s = ["th", "st", "nd", "rd"], v = n % 100;
|
|
697
|
+
return `${n}${s[(v - 20) % 10] || s[v] || s[0]}`;
|
|
698
|
+
}
|
|
699
|
+
function contrast(color) {
|
|
700
|
+
const exploded = color?.match(color.length >= 6 ? /[0-9a-fA-F]{2}/g : /[0-9a-fA-F]/g);
|
|
670
701
|
if (!exploded || exploded?.length < 3) return "black";
|
|
671
702
|
const [r, g, b] = exploded.map((hex) => parseInt(hex.length == 1 ? `${hex}${hex}` : hex, 16));
|
|
672
703
|
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
673
704
|
return luminance > 0.5 ? "black" : "white";
|
|
674
705
|
}
|
|
706
|
+
function hex2Int(hex) {
|
|
707
|
+
let r = 0, g = 0, b = 0;
|
|
708
|
+
if (hex.length === 4) {
|
|
709
|
+
r = parseInt(hex[1] + hex[1], 16);
|
|
710
|
+
g = parseInt(hex[2] + hex[2], 16);
|
|
711
|
+
b = parseInt(hex[3] + hex[3], 16);
|
|
712
|
+
} else {
|
|
713
|
+
r = parseInt(hex.slice(1, 3), 16);
|
|
714
|
+
g = parseInt(hex.slice(3, 5), 16);
|
|
715
|
+
b = parseInt(hex.slice(5, 7), 16);
|
|
716
|
+
}
|
|
717
|
+
return { r, g, b };
|
|
718
|
+
}
|
|
719
|
+
function hue2rgb(p, q, t) {
|
|
720
|
+
if (t < 0) t += 1;
|
|
721
|
+
if (t > 1) t -= 1;
|
|
722
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
723
|
+
if (t < 1 / 2) return q;
|
|
724
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
725
|
+
return p;
|
|
726
|
+
}
|
|
727
|
+
function int2Hex(r, g, b) {
|
|
728
|
+
return "#" + dec2Hex(r) + dec2Hex(g) + dec2Hex(b);
|
|
729
|
+
}
|
|
730
|
+
function shadeColor(hex, amount) {
|
|
731
|
+
let { r, g, b } = hex2Int(hex);
|
|
732
|
+
r /= 255;
|
|
733
|
+
g /= 255;
|
|
734
|
+
b /= 255;
|
|
735
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
736
|
+
let h, s, l = (max + min) / 2;
|
|
737
|
+
if (max === min) {
|
|
738
|
+
h = s = 0;
|
|
739
|
+
} else {
|
|
740
|
+
const d = max - min;
|
|
741
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
742
|
+
switch (max) {
|
|
743
|
+
case r:
|
|
744
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
745
|
+
break;
|
|
746
|
+
case g:
|
|
747
|
+
h = (b - r) / d + 2;
|
|
748
|
+
break;
|
|
749
|
+
case b:
|
|
750
|
+
h = (r - g) / d + 4;
|
|
751
|
+
break;
|
|
752
|
+
default:
|
|
753
|
+
h = 0;
|
|
754
|
+
break;
|
|
755
|
+
}
|
|
756
|
+
h /= 6;
|
|
757
|
+
}
|
|
758
|
+
l = Math.max(0, Math.min(1, l + amount));
|
|
759
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
760
|
+
const p = 2 * l - q;
|
|
761
|
+
return int2Hex(hue2rgb(p, q, h + 1 / 3), hue2rgb(p, q, h), hue2rgb(p, q, h - 1 / 3));
|
|
762
|
+
}
|
|
675
763
|
const LETTER_LIST = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
676
764
|
const NUMBER_LIST = "0123456789";
|
|
677
765
|
const SYMBOL_LIST = "~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/";
|
|
@@ -851,27 +939,42 @@ function validateEmail(email) {
|
|
|
851
939
|
function fromCsv(csv, hasHeaders = true) {
|
|
852
940
|
function parseLine(line) {
|
|
853
941
|
const columns = [];
|
|
854
|
-
let current = "", inQuotes2 = false;
|
|
942
|
+
let current = "", inQuotes2 = false, quoteChar2 = null;
|
|
855
943
|
for (let i = 0; i < line.length; i++) {
|
|
856
944
|
const char = line[i];
|
|
857
945
|
const nextChar = line[i + 1];
|
|
858
|
-
if (char === '"') {
|
|
859
|
-
|
|
860
|
-
|
|
946
|
+
if ((char === '"' || char === "'") && !inQuotes2) {
|
|
947
|
+
inQuotes2 = true;
|
|
948
|
+
quoteChar2 = char;
|
|
949
|
+
} else if (char === quoteChar2 && inQuotes2) {
|
|
950
|
+
if (nextChar === quoteChar2) {
|
|
951
|
+
current += quoteChar2;
|
|
861
952
|
i++;
|
|
862
|
-
} else
|
|
953
|
+
} else {
|
|
954
|
+
inQuotes2 = false;
|
|
955
|
+
quoteChar2 = null;
|
|
956
|
+
}
|
|
863
957
|
} else if (char === "," && !inQuotes2) {
|
|
864
958
|
columns.push(current.trim());
|
|
865
959
|
current = "";
|
|
866
960
|
} else current += char;
|
|
867
961
|
}
|
|
868
962
|
columns.push(current.trim());
|
|
869
|
-
return columns.map((col) =>
|
|
963
|
+
return columns.map((col) => {
|
|
964
|
+
col = col.replace(/^["']|["']$/g, "");
|
|
965
|
+
return col.replace(/""/g, '"').replace(/''/g, "'");
|
|
966
|
+
});
|
|
870
967
|
}
|
|
871
968
|
const rows = [];
|
|
872
|
-
let currentRow = "", inQuotes = false;
|
|
969
|
+
let currentRow = "", inQuotes = false, quoteChar = null;
|
|
873
970
|
for (const char of csv.replace(/\r\n/g, "\n")) {
|
|
874
|
-
if (char === '"')
|
|
971
|
+
if ((char === '"' || char === "'") && !inQuotes) {
|
|
972
|
+
inQuotes = true;
|
|
973
|
+
quoteChar = char;
|
|
974
|
+
} else if (char === quoteChar && inQuotes) {
|
|
975
|
+
inQuotes = false;
|
|
976
|
+
quoteChar = null;
|
|
977
|
+
}
|
|
875
978
|
if (char === "\n" && !inQuotes) {
|
|
876
979
|
rows.push(currentRow.trim());
|
|
877
980
|
currentRow = "";
|
|
@@ -1798,33 +1901,6 @@ class Logger extends TypedEmitter {
|
|
|
1798
1901
|
console.error(CliForeground.RED + str + CliEffects.CLEAR);
|
|
1799
1902
|
}
|
|
1800
1903
|
}
|
|
1801
|
-
function dec2Frac(num, maxDen = 1e3) {
|
|
1802
|
-
let sign = Math.sign(num);
|
|
1803
|
-
num = Math.abs(num);
|
|
1804
|
-
if (Number.isInteger(num)) return sign * num + "";
|
|
1805
|
-
let closest = { n: 0, d: 1, diff: Math.abs(num) };
|
|
1806
|
-
for (let d = 1; d <= maxDen; d++) {
|
|
1807
|
-
let n = Math.round(num * d);
|
|
1808
|
-
let diff = Math.abs(num - n / d);
|
|
1809
|
-
if (diff < closest.diff) {
|
|
1810
|
-
closest = { n, d, diff };
|
|
1811
|
-
if (diff < 1e-8) break;
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
let integer = Math.floor(closest.n / closest.d);
|
|
1815
|
-
let numerator = closest.n - integer * closest.d;
|
|
1816
|
-
return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
|
|
1817
|
-
}
|
|
1818
|
-
function fracToDec(frac) {
|
|
1819
|
-
let split = frac.split(" ");
|
|
1820
|
-
const whole = split.length == 2 ? Number(split[0]) : 0;
|
|
1821
|
-
split = split.pop().split("/");
|
|
1822
|
-
return whole + Number(split[0]) / Number(split[1]);
|
|
1823
|
-
}
|
|
1824
|
-
function numSuffix(n) {
|
|
1825
|
-
const s = ["th", "st", "nd", "rd"], v = n % 100;
|
|
1826
|
-
return `${n}${s[(v - 20) % 10] || s[v] || s[0]}`;
|
|
1827
|
-
}
|
|
1828
1904
|
function compareVersions(target, vs) {
|
|
1829
1905
|
const [tMajor, tMinor, tPatch] = target.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
|
|
1830
1906
|
const [vMajor, vMinor, vPatch] = vs.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
|
|
@@ -2974,6 +3050,7 @@ export {
|
|
|
2974
3050
|
dayOfWeek,
|
|
2975
3051
|
dayOfYear,
|
|
2976
3052
|
dec2Frac,
|
|
3053
|
+
dec2Hex,
|
|
2977
3054
|
decodeJwt,
|
|
2978
3055
|
deepCopy,
|
|
2979
3056
|
deepMerge,
|
|
@@ -2995,12 +3072,15 @@ export {
|
|
|
2995
3072
|
formatDate,
|
|
2996
3073
|
formatMs,
|
|
2997
3074
|
formatPhoneNumber,
|
|
2998
|
-
|
|
3075
|
+
frac2Dec,
|
|
2999
3076
|
fromCsv,
|
|
3000
3077
|
gravatar,
|
|
3078
|
+
hex2Int,
|
|
3079
|
+
hue2rgb,
|
|
3001
3080
|
includes,
|
|
3002
3081
|
insertAt,
|
|
3003
3082
|
instantInterval,
|
|
3083
|
+
int2Hex,
|
|
3004
3084
|
ipV6ToV4,
|
|
3005
3085
|
isEqual,
|
|
3006
3086
|
kebabCase,
|
|
@@ -3024,6 +3104,7 @@ export {
|
|
|
3024
3104
|
renderTemplate,
|
|
3025
3105
|
reservedIp,
|
|
3026
3106
|
search,
|
|
3107
|
+
shadeColor,
|
|
3027
3108
|
sleep,
|
|
3028
3109
|
sleepWhile,
|
|
3029
3110
|
snakeCase,
|