@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 CHANGED
@@ -1,6 +1,19 @@
1
1
  /**
2
2
  * Determine if either black or white provides more contrast to the provided color
3
- * @param {string} background Color to compare against
3
+ * @param {string} color Color to compare against
4
4
  * @return {"white" | "black"} Color with the most contrast
5
5
  */
6
- export declare function contrast(background: string): 'white' | 'black';
6
+ export declare function contrast(color: string): 'white' | 'black';
7
+ export declare function hex2Int(hex: string): {
8
+ r: number;
9
+ g: number;
10
+ b: number;
11
+ };
12
+ export declare function hue2rgb(p: number, q: number, t: number): number;
13
+ export declare function int2Hex(r: number, g: number, b: number): string;
14
+ /**
15
+ * Adjusts the darkness of a hex color.
16
+ * @param {string} hex - The hex color (e.g., '#ff0000').
17
+ * @param {number} amount - A value between -1 (black) and 1 (white)
18
+ */
19
+ export declare function shadeColor(hex: string, amount: number): string;
package/dist/index.cjs CHANGED
@@ -669,13 +669,101 @@ ${opts.message || this.desc}`;
669
669
  /** Get all cached items */
670
670
  values = this.all;
671
671
  }
672
- function contrast(background) {
673
- const exploded = background?.match(background.length >= 6 ? /[0-9a-fA-F]{2}/g : /[0-9a-fA-F]/g);
672
+ function dec2Frac(num, maxDen = 1e3) {
673
+ let sign = Math.sign(num);
674
+ num = Math.abs(num);
675
+ if (Number.isInteger(num)) return sign * num + "";
676
+ let closest = { n: 0, d: 1, diff: Math.abs(num) };
677
+ for (let d = 1; d <= maxDen; d++) {
678
+ let n = Math.round(num * d);
679
+ let diff = Math.abs(num - n / d);
680
+ if (diff < closest.diff) {
681
+ closest = { n, d, diff };
682
+ if (diff < 1e-8) break;
683
+ }
684
+ }
685
+ let integer = Math.floor(closest.n / closest.d);
686
+ let numerator = closest.n - integer * closest.d;
687
+ return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
688
+ }
689
+ function dec2Hex(num) {
690
+ const hex = Math.round(num * 255).toString(16);
691
+ return hex.length === 1 ? "0" + hex : hex;
692
+ }
693
+ function frac2Dec(frac) {
694
+ let split = frac.split(" ");
695
+ const whole = split.length == 2 ? Number(split[0]) : 0;
696
+ split = split.pop().split("/");
697
+ return whole + Number(split[0]) / Number(split[1]);
698
+ }
699
+ function numSuffix(n) {
700
+ const s = ["th", "st", "nd", "rd"], v = n % 100;
701
+ return `${n}${s[(v - 20) % 10] || s[v] || s[0]}`;
702
+ }
703
+ function contrast(color) {
704
+ const exploded = color?.match(color.length >= 6 ? /[0-9a-fA-F]{2}/g : /[0-9a-fA-F]/g);
674
705
  if (!exploded || exploded?.length < 3) return "black";
675
706
  const [r, g, b] = exploded.map((hex) => parseInt(hex.length == 1 ? `${hex}${hex}` : hex, 16));
676
707
  const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
677
708
  return luminance > 0.5 ? "black" : "white";
678
709
  }
710
+ function hex2Int(hex) {
711
+ let r = 0, g = 0, b = 0;
712
+ if (hex.length === 4) {
713
+ r = parseInt(hex[1] + hex[1], 16);
714
+ g = parseInt(hex[2] + hex[2], 16);
715
+ b = parseInt(hex[3] + hex[3], 16);
716
+ } else {
717
+ r = parseInt(hex.slice(1, 3), 16);
718
+ g = parseInt(hex.slice(3, 5), 16);
719
+ b = parseInt(hex.slice(5, 7), 16);
720
+ }
721
+ return { r, g, b };
722
+ }
723
+ function hue2rgb(p, q, t) {
724
+ if (t < 0) t += 1;
725
+ if (t > 1) t -= 1;
726
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
727
+ if (t < 1 / 2) return q;
728
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
729
+ return p;
730
+ }
731
+ function int2Hex(r, g, b) {
732
+ return "#" + dec2Hex(r) + dec2Hex(g) + dec2Hex(b);
733
+ }
734
+ function shadeColor(hex, amount) {
735
+ let { r, g, b } = hex2Int(hex);
736
+ r /= 255;
737
+ g /= 255;
738
+ b /= 255;
739
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
740
+ let h, s, l = (max + min) / 2;
741
+ if (max === min) {
742
+ h = s = 0;
743
+ } else {
744
+ const d = max - min;
745
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
746
+ switch (max) {
747
+ case r:
748
+ h = (g - b) / d + (g < b ? 6 : 0);
749
+ break;
750
+ case g:
751
+ h = (b - r) / d + 2;
752
+ break;
753
+ case b:
754
+ h = (r - g) / d + 4;
755
+ break;
756
+ default:
757
+ h = 0;
758
+ break;
759
+ }
760
+ h /= 6;
761
+ }
762
+ l = Math.max(0, Math.min(1, l + amount));
763
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
764
+ const p = 2 * l - q;
765
+ return int2Hex(hue2rgb(p, q, h + 1 / 3), hue2rgb(p, q, h), hue2rgb(p, q, h - 1 / 3));
766
+ }
679
767
  const LETTER_LIST = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
680
768
  const NUMBER_LIST = "0123456789";
681
769
  const SYMBOL_LIST = "~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/";
@@ -855,27 +943,42 @@ ${opts.message || this.desc}`;
855
943
  function fromCsv(csv, hasHeaders = true) {
856
944
  function parseLine(line) {
857
945
  const columns = [];
858
- let current = "", inQuotes2 = false;
946
+ let current = "", inQuotes2 = false, quoteChar2 = null;
859
947
  for (let i = 0; i < line.length; i++) {
860
948
  const char = line[i];
861
949
  const nextChar = line[i + 1];
862
- if (char === '"') {
863
- if (inQuotes2 && nextChar === '"') {
864
- current += '"';
950
+ if ((char === '"' || char === "'") && !inQuotes2) {
951
+ inQuotes2 = true;
952
+ quoteChar2 = char;
953
+ } else if (char === quoteChar2 && inQuotes2) {
954
+ if (nextChar === quoteChar2) {
955
+ current += quoteChar2;
865
956
  i++;
866
- } else inQuotes2 = !inQuotes2;
957
+ } else {
958
+ inQuotes2 = false;
959
+ quoteChar2 = null;
960
+ }
867
961
  } else if (char === "," && !inQuotes2) {
868
962
  columns.push(current.trim());
869
963
  current = "";
870
964
  } else current += char;
871
965
  }
872
966
  columns.push(current.trim());
873
- return columns.map((col) => col.replace(/^"|"$/g, "").replace(/""/g, '"'));
967
+ return columns.map((col) => {
968
+ col = col.replace(/^["']|["']$/g, "");
969
+ return col.replace(/""/g, '"').replace(/''/g, "'");
970
+ });
874
971
  }
875
972
  const rows = [];
876
- let currentRow = "", inQuotes = false;
973
+ let currentRow = "", inQuotes = false, quoteChar = null;
877
974
  for (const char of csv.replace(/\r\n/g, "\n")) {
878
- if (char === '"') inQuotes = !inQuotes;
975
+ if ((char === '"' || char === "'") && !inQuotes) {
976
+ inQuotes = true;
977
+ quoteChar = char;
978
+ } else if (char === quoteChar && inQuotes) {
979
+ inQuotes = false;
980
+ quoteChar = null;
981
+ }
879
982
  if (char === "\n" && !inQuotes) {
880
983
  rows.push(currentRow.trim());
881
984
  currentRow = "";
@@ -1802,33 +1905,6 @@ ${opts.message || this.desc}`;
1802
1905
  console.error(CliForeground.RED + str + CliEffects.CLEAR);
1803
1906
  }
1804
1907
  }
1805
- function dec2Frac(num, maxDen = 1e3) {
1806
- let sign = Math.sign(num);
1807
- num = Math.abs(num);
1808
- if (Number.isInteger(num)) return sign * num + "";
1809
- let closest = { n: 0, d: 1, diff: Math.abs(num) };
1810
- for (let d = 1; d <= maxDen; d++) {
1811
- let n = Math.round(num * d);
1812
- let diff = Math.abs(num - n / d);
1813
- if (diff < closest.diff) {
1814
- closest = { n, d, diff };
1815
- if (diff < 1e-8) break;
1816
- }
1817
- }
1818
- let integer = Math.floor(closest.n / closest.d);
1819
- let numerator = closest.n - integer * closest.d;
1820
- return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
1821
- }
1822
- function fracToDec(frac) {
1823
- let split = frac.split(" ");
1824
- const whole = split.length == 2 ? Number(split[0]) : 0;
1825
- split = split.pop().split("/");
1826
- return whole + Number(split[0]) / Number(split[1]);
1827
- }
1828
- function numSuffix(n) {
1829
- const s = ["th", "st", "nd", "rd"], v = n % 100;
1830
- return `${n}${s[(v - 20) % 10] || s[v] || s[0]}`;
1831
- }
1832
1908
  function compareVersions(target, vs) {
1833
1909
  const [tMajor, tMinor, tPatch] = target.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
1834
1910
  const [vMajor, vMinor, vPatch] = vs.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
@@ -2977,6 +3053,7 @@ ${err.message || err.toString()}`);
2977
3053
  exports2.dayOfWeek = dayOfWeek;
2978
3054
  exports2.dayOfYear = dayOfYear;
2979
3055
  exports2.dec2Frac = dec2Frac;
3056
+ exports2.dec2Hex = dec2Hex;
2980
3057
  exports2.decodeJwt = decodeJwt;
2981
3058
  exports2.deepCopy = deepCopy;
2982
3059
  exports2.deepMerge = deepMerge;
@@ -2998,12 +3075,15 @@ ${err.message || err.toString()}`);
2998
3075
  exports2.formatDate = formatDate;
2999
3076
  exports2.formatMs = formatMs;
3000
3077
  exports2.formatPhoneNumber = formatPhoneNumber;
3001
- exports2.fracToDec = fracToDec;
3078
+ exports2.frac2Dec = frac2Dec;
3002
3079
  exports2.fromCsv = fromCsv;
3003
3080
  exports2.gravatar = gravatar;
3081
+ exports2.hex2Int = hex2Int;
3082
+ exports2.hue2rgb = hue2rgb;
3004
3083
  exports2.includes = includes;
3005
3084
  exports2.insertAt = insertAt;
3006
3085
  exports2.instantInterval = instantInterval;
3086
+ exports2.int2Hex = int2Hex;
3007
3087
  exports2.ipV6ToV4 = ipV6ToV4;
3008
3088
  exports2.isEqual = isEqual;
3009
3089
  exports2.kebabCase = kebabCase;
@@ -3027,6 +3107,7 @@ ${err.message || err.toString()}`);
3027
3107
  exports2.renderTemplate = renderTemplate;
3028
3108
  exports2.reservedIp = reservedIp;
3029
3109
  exports2.search = search;
3110
+ exports2.shadeColor = shadeColor;
3030
3111
  exports2.sleep = sleep;
3031
3112
  exports2.sleepWhile = sleepWhile;
3032
3113
  exports2.snakeCase = snakeCase;