@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/index.mjs CHANGED
@@ -665,13 +665,101 @@ class Cache {
665
665
  /** Get all cached items */
666
666
  values = this.all;
667
667
  }
668
- function contrast(background) {
669
- const exploded = background?.match(background.length >= 6 ? /[0-9a-fA-F]{2}/g : /[0-9a-fA-F]/g);
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
- if (inQuotes2 && nextChar === '"') {
860
- current += '"';
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 inQuotes2 = !inQuotes2;
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) => col.replace(/^"|"$/g, "").replace(/""/g, '"'));
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 === '"') inQuotes = !inQuotes;
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
- fracToDec,
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,