qsu 1.18.0 → 1.19.0

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021-2026 CDGet <jooy2.contact@gmail.com> (https://cdget.com).
3
+ Copyright (c) 2021-2026 CDGet (https://cdget.com).
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -160,9 +160,9 @@ The categories in the top half are exported from `qsu` and are safe to bundle fo
160
160
 
161
161
  Installing and using the package and defining all the utility methods can be found on the documentation page below.
162
162
 
163
- - [Installation](https://qsu.cdget.com/installation/javascript)
163
+ - [Installation](https://qsu.cdget.com/installation)
164
164
  - [Reference](https://qsu.cdget.com/reference) — every function, with parameters, defaults and examples
165
- - [Changelog](https://qsu.cdget.com/changelog/javascript)
165
+ - [Changelog](https://qsu.cdget.com/changelog/)
166
166
 
167
167
  ## Development
168
168
 
@@ -6,15 +6,32 @@ export type AnyValueObject = {
6
6
  [key: string]: any;
7
7
  };
8
8
  export type DurationUnitName = 'Year' | 'Month' | 'Day' | 'Hour' | 'Minute' | 'Second' | 'Millisecond';
9
- export type DurationOptions = {
10
- useShortString?: boolean;
11
- useSpace?: boolean;
9
+ export type DurationPartsOptions = {
12
10
  withZeroValue?: boolean;
13
- separator?: string;
14
11
  withMilliSeconds?: boolean;
15
12
  maxUnitCount?: number;
16
13
  unit?: DurationUnitName;
17
14
  };
15
+ export type DurationOptions = DurationPartsOptions & {
16
+ useShortString?: boolean;
17
+ useSpace?: boolean;
18
+ separator?: string;
19
+ };
20
+ export type DurationPart = {
21
+ value: number;
22
+ unit: DurationUnitName;
23
+ };
24
+ export type FileSizeStandard = 'jedec' | 'iec' | 'si';
25
+ export type FileSizeUnitDisplay = 'short' | 'long';
26
+ export type FileSizeOptions = {
27
+ standard?: FileSizeStandard;
28
+ unitDisplay?: FileSizeUnitDisplay;
29
+ };
30
+ export type FileSizeParts = {
31
+ value: number;
32
+ unit: string;
33
+ exponent: number;
34
+ };
18
35
  export type RetryOptions = {
19
36
  times?: number;
20
37
  delay?: number;
@@ -0,0 +1,11 @@
1
+ type Run = [number, string, boolean];
2
+ export type NaturalKey = {
3
+ runs: Run[];
4
+ accents: string;
5
+ caseBits: string;
6
+ raw: string;
7
+ };
8
+ export declare function naturalKey(value: unknown): NaturalKey;
9
+ export declare function compareNaturalKey(a: NaturalKey, b: NaturalKey): number;
10
+ export declare function compareNatural(a: unknown, b: unknown): number;
11
+ export {};
@@ -0,0 +1 @@
1
+ const t=/([0-9]+)/,n=/^[0-9]+$/,e=/^0+(?=\d)/,r=/[̀-ͯ]/g,o=/[^̀-ͯ]/g,c=/\s/,s=/[\p{L}\p{M}\p{N}]/u;function a(t){return c.test(t)?0:s.test(t)?3:1}export function naturalKey(c){const s="string"==typeof c?c:String(c??""),u=[];let i="",l="";for(const c of s.split(t)){if(""===c)continue;if(n.test(c)){u.push([2,c.replace(e,""),!0]);continue}const t=c.normalize("NFD"),s=t.replace(r,"");i+=t.replace(o,"");for(const t of s){const n=t.toLowerCase(),e=a(t),r=u[u.length-1];l+=t===n?"0":"1",void 0===r||r[0]!==e||r[2]?u.push([e,n,!1]):r[1]+=n}}return{runs:u,accents:i,caseBits:l,raw:s}}function u(t,n){return t.length!==n.length?t.length<n.length?-1:1:t<n?-1:t>n?1:0}function i(t,n){return t<n?-1:t>n?1:0}export function compareNaturalKey(t,n){const e=Math.max(t.runs.length,n.runs.length);for(let r=0;r<e;r+=1){const e=t.runs[r],o=n.runs[r];if(void 0===e||void 0===o)return void 0===e?-1:1;if(e[0]!==o[0])return e[0]<o[0]?-1:1;const c=e[2]?u(e[1],o[1]):i(e[1],o[1]);if(0!==c)return c}return i(t.accents,n.accents)||i(t.caseBits,n.caseBits)||i(t.raw,n.raw)}export function compareNatural(t,n){return compareNaturalKey(naturalKey(t),naturalKey(n))}
@@ -1 +1 @@
1
- let r;export function sortByObjectKey(t,e,o=!1,n=!1){if(n){const n=r??=new Intl.Collator([],{numeric:!0});return[...t].sort((r,t)=>o?n.compare(t[e],r[e]):n.compare(r[e],t[e]))}return[...t].sort((r,t)=>o?r[e]>t[e]?-1:r[e]<t[e]?1:0:r[e]<t[e]?-1:r[e]>t[e]?1:0)}
1
+ import{compareNaturalKey as t,naturalKey as r}from"./_naturalCompare.js";export function sortByObjectKey(o,e,s=!1,n=!1){if(n){const n=o.map(t=>({item:t,sortKey:r(t[e])}));return n.sort((r,o)=>{const e=t(r.sortKey,o.sortKey);return s?-e:e}),n.map(t=>t.item)}return[...o].sort((t,r)=>s?t[e]>r[e]?-1:t[e]<r[e]?1:0:t[e]<r[e]?-1:t[e]>r[e]?1:0)}
@@ -1 +1 @@
1
- let r;export function sortNumeric(o,t=!1){const e=r??=new Intl.Collator([],{numeric:!0});return[...o].sort((r,o)=>t?e.compare(o,r):e.compare(r,o))}
1
+ import{compareNaturalKey as r,naturalKey as e}from"./_naturalCompare.js";export function sortNumeric(t,o=!1){const a=t.map(r=>({value:r,key:e(r)}));return a.sort((e,t)=>{const a=r(e.key,t.key);return o?-a:a}),a.map(r=>r.value)}
@@ -1 +1 @@
1
- const e=[{name:"Year",short:"Y",ms:31536e6},{name:"Month",short:"Mo",ms:2592e6},{name:"Day",short:"D",ms:864e5},{name:"Hour",short:"H",ms:36e5},{name:"Minute",short:"M",ms:6e4},{name:"Second",short:"S",ms:1e3},{name:"Millisecond",short:"ms",ms:1}];function t(e,t,n,o){return`${e}${o?" ":""}${n?t.short:`${t.name}${1===e?"":"s"}`}`}export function duration(n,o){const{useShortString:s=!1,useSpace:r=!0,withZeroValue:a=!1,separator:i=" ",withMilliSeconds:m=!1,maxUnitCount:u,unit:l}={...o};if(l){const o=l.toLowerCase().replace(/s$/,""),a=e.find(e=>e.name.toLowerCase()===o);if(a)return t((c=n/a.ms,Number(c.toFixed(6))),a,s,r)}var c;const h=m?e:e.filter(e=>"Millisecond"!==e.name),f=[];let d=n;for(const e of h){const t=Math.floor(d/e.ms);d-=t*e.ms,f.push({value:t,unit:e})}const M=f.findIndex(e=>0!==e.value);if(-1===M)return"";let p=f.slice(M).filter(e=>a||0!==e.value).map(e=>t(e.value,e.unit,s,r));return"number"==typeof u&&u>=0&&(p=p.slice(0,u)),p.join(i)}
1
+ import{durationParts as t,findUnit as r}from"./durationParts.js";export function duration(n,o){const{useShortString:u=!1,useSpace:s=!0,separator:a=" "}={...o};return t(n,o).map(t=>function(t,n,o,u){const s=r(n);return`${t}${u?" ":""}${o?s?.short??n:`${n}${1===t?"":"s"}`}`}(t.value,t.unit,u,s)).join(a)}
@@ -0,0 +1,10 @@
1
+ import type { DurationPart, DurationPartsOptions, DurationUnitName } from '../_types/global.js';
2
+ export type Unit = {
3
+ name: DurationUnitName;
4
+ short: string;
5
+ ms: number;
6
+ };
7
+ export declare const UNITS: Unit[];
8
+ export declare function cleanNumber(value: number): number;
9
+ export declare function findUnit(name: string): Unit | undefined;
10
+ export declare function durationParts(milliseconds: number, options?: DurationPartsOptions): DurationPart[];
@@ -0,0 +1 @@
1
+ export const UNITS=[{name:"Year",short:"Y",ms:31536e6},{name:"Month",short:"Mo",ms:2592e6},{name:"Day",short:"D",ms:864e5},{name:"Hour",short:"H",ms:36e5},{name:"Minute",short:"M",ms:6e4},{name:"Second",short:"S",ms:1e3},{name:"Millisecond",short:"ms",ms:1}];export function cleanNumber(e){return Number(e.toFixed(6))}export function findUnit(e){const n=e.toLowerCase().replace(/s$/,"");return UNITS.find(e=>e.name.toLowerCase()===n)}export function durationParts(e,n){const{withZeroValue:t=!1,withMilliSeconds:o=!1,maxUnitCount:r,unit:s}={...n};if(s){const n=findUnit(s);if(n)return[{value:cleanNumber(e/n.ms),unit:n.name}]}const i=o?UNITS:UNITS.filter(e=>"Millisecond"!==e.name),a=[];let m=e;for(const e of i){const n=Math.floor(m/e.ms);m-=n*e.ms,a.push({value:n,unit:e.name})}const u=a.findIndex(e=>0!==e.value);if(-1===u)return[];const c=a.slice(u).filter(e=>t||0!==e.value);return"number"==typeof r&&r>=0?c.slice(0,r):c}
@@ -1,2 +1,2 @@
1
- import type { PositiveNumber } from '../_types/global.js';
2
- export declare function fileSizeFormat<N extends number>(bytes: PositiveNumber<N>, decimals?: number, ceil?: boolean): string;
1
+ import type { FileSizeOptions, PositiveNumber } from '../_types/global.js';
2
+ export declare function fileSizeFormat<N extends number>(bytes: PositiveNumber<N>, decimals?: number, ceil?: boolean, options?: FileSizeOptions): string;
@@ -1 +1 @@
1
- export function fileSizeFormat(t,o=2,e=!1){const B=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];if(t<1)return`0 ${B[0]}`;const r=Math.floor(Math.log(t)/Math.log(1024)),a=t/1024**r;return`${e?Math.ceil(a):parseFloat(a.toFixed(o<0?0:o))} ${B[r]}`}
1
+ import{fileSizeParts as t,resolveUnitTable as e,unitLabel as i}from"./fileSizeParts.js";export function fileSizeFormat(a,o=2,r=!1,n){const{standard:l,unitDisplay:s}={...n},{value:p,exponent:f}=t(a,n),u=r?Math.ceil(p):parseFloat(p.toFixed(o<0?0:o));return`${u} ${i(e(l),f,s,u)}`}
@@ -0,0 +1,11 @@
1
+ import type { FileSizeOptions, FileSizeParts, FileSizeStandard, PositiveNumber } from '../_types/global.js';
2
+ type UnitTable = {
3
+ base: number;
4
+ short: string[];
5
+ long: string[];
6
+ };
7
+ export declare function resolveUnitTable(standard: FileSizeStandard | undefined): UnitTable;
8
+ export declare function unitLabel(table: UnitTable, exponent: number, unitDisplay: string | undefined, value: number): string;
9
+ export declare function sizeExponent(bytes: number, base: number, unitCount: number): number;
10
+ export declare function fileSizeParts<N extends number>(bytes: PositiveNumber<N>, options?: FileSizeOptions): FileSizeParts;
11
+ export {};
@@ -0,0 +1 @@
1
+ const e={jedec:{base:1024,short:["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],long:["Byte","Kilobyte","Megabyte","Gigabyte","Terabyte","Petabyte","Exabyte","Zettabyte","Yottabyte"]},iec:{base:1024,short:["Bytes","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],long:["Byte","Kibibyte","Mebibyte","Gibibyte","Tebibyte","Pebibyte","Exbibyte","Zebibyte","Yobibyte"]},si:{base:1e3,short:["Bytes","kB","MB","GB","TB","PB","EB","ZB","YB"],long:["Byte","Kilobyte","Megabyte","Gigabyte","Terabyte","Petabyte","Exabyte","Zettabyte","Yottabyte"]}};export function resolveUnitTable(t){return e[t]??e.jedec}export function unitLabel(e,t,i,b){return"long"!==i?e.short[t]:`${e.long[t]}${1===b?"":"s"}`}export function sizeExponent(e,t,i){return Math.min(Math.floor(Math.log(e)/Math.log(t)),i-1)}export function fileSizeParts(e,t){const{standard:i,unitDisplay:b}={...t},n=resolveUnitTable(i);if(e<1)return{value:0,unit:unitLabel(n,0,b,0),exponent:0};const o=sizeExponent(e,n.base,n.short.length),a=e/n.base**o;return{value:a,unit:unitLabel(n,o,b,a),exponent:o}}
@@ -1,5 +1,7 @@
1
1
  export { duration } from './duration.js';
2
+ export { durationParts } from './durationParts.js';
2
3
  export { fileSizeFormat } from './fileSizeFormat.js';
4
+ export { fileSizeParts } from './fileSizeParts.js';
3
5
  export { numberFormat } from './numberFormat.js';
4
6
  export { safeJSONParse } from './safeJSONParse.js';
5
7
  export { safeParseInt } from './safeParseInt.js';
@@ -1 +1 @@
1
- export{duration}from"./duration.js";export{fileSizeFormat}from"./fileSizeFormat.js";export{numberFormat}from"./numberFormat.js";export{safeJSONParse}from"./safeJSONParse.js";export{safeParseInt}from"./safeParseInt.js";
1
+ export{duration}from"./duration.js";export{durationParts}from"./durationParts.js";export{fileSizeFormat}from"./fileSizeFormat.js";export{fileSizeParts}from"./fileSizeParts.js";export{numberFormat}from"./numberFormat.js";export{safeJSONParse}from"./safeJSONParse.js";export{safeParseInt}from"./safeParseInt.js";
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "qsu",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Everyday helpers you would otherwise write yourself: slugs, text case, date math, number and file size formatting, deep clone and merge, email and URL validation, debounce, throttle and hashing. No dependencies.",
5
- "author": "CDGet <jooy2.contact@gmail.com>",
5
+ "author": "CDGet (https://cdget.com)",
6
6
  "license": "MIT",
7
7
  "homepage": "https://qsu.cdget.com",
8
8
  "repository": {