@ezez/utils 1.0.0 → 1.2.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/CHANGELOG.md +24 -8
- package/README.md +41 -18
- package/dist/ensureDate.d.ts +3 -0
- package/dist/ensureDate.d.ts.map +1 -0
- package/dist/ensureDate.js +11 -0
- package/dist/ensureDate.js.map +1 -0
- package/dist/ensurePrefix.d.ts +3 -0
- package/dist/ensurePrefix.d.ts.map +1 -0
- package/dist/ensurePrefix.js +11 -0
- package/dist/ensurePrefix.js.map +1 -0
- package/dist/ensureSuffix.d.ts +3 -0
- package/dist/ensureSuffix.d.ts.map +1 -0
- package/dist/ensureSuffix.js +11 -0
- package/dist/ensureSuffix.js.map +1 -0
- package/dist/ensureTimestamp.d.ts +3 -0
- package/dist/ensureTimestamp.d.ts.map +1 -0
- package/dist/ensureTimestamp.js +11 -0
- package/dist/ensureTimestamp.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/isEmpty.js +1 -1
- package/dist/isEmpty.js.map +1 -1
- package/dist/isNumericString.d.ts +10 -0
- package/dist/isNumericString.d.ts.map +1 -0
- package/dist/isNumericString.js +61 -0
- package/dist/isNumericString.js.map +1 -0
- package/dist/occurrences.d.ts +7 -0
- package/dist/occurrences.d.ts.map +1 -0
- package/dist/occurrences.js +27 -0
- package/dist/occurrences.js.map +1 -0
- package/dist/stripPrefix.d.ts +3 -0
- package/dist/stripPrefix.d.ts.map +1 -0
- package/dist/stripPrefix.js +11 -0
- package/dist/stripPrefix.js.map +1 -0
- package/dist/stripSuffix.d.ts +3 -0
- package/dist/stripSuffix.d.ts.map +1 -0
- package/dist/stripSuffix.js +11 -0
- package/dist/stripSuffix.js.map +1 -0
- package/docs/assets/search.js +1 -1
- package/docs/functions/cap.html +15 -5
- package/docs/functions/capitalize.html +15 -5
- package/docs/functions/coalesce.html +15 -5
- package/docs/functions/ensureArray.html +15 -5
- package/docs/functions/ensureDate.html +126 -0
- package/docs/functions/ensureError.html +15 -5
- package/docs/functions/ensurePrefix.html +128 -0
- package/docs/functions/ensureSuffix.html +128 -0
- package/docs/functions/ensureTimestamp.html +126 -0
- package/docs/functions/get.html +15 -5
- package/docs/functions/getMultiple.html +15 -5
- package/docs/functions/insertSeparator.html +15 -5
- package/docs/functions/isEmpty.html +15 -5
- package/docs/functions/isNumericString.html +123 -0
- package/docs/functions/isPlainObject.html +15 -5
- package/docs/functions/last.html +15 -5
- package/docs/functions/mapAsync.html +15 -5
- package/docs/functions/mapValues.html +15 -5
- package/docs/functions/match.html +15 -5
- package/docs/functions/merge.html +23 -13
- package/docs/functions/mostFrequent.html +15 -5
- package/docs/functions/noop.html +15 -5
- package/docs/functions/occurrences.html +135 -0
- package/docs/functions/omit.html +15 -5
- package/docs/functions/pick.html +15 -5
- package/docs/functions/pull.html +15 -5
- package/docs/functions/remove.html +15 -5
- package/docs/functions/rethrow.html +15 -5
- package/docs/functions/scale.html +15 -5
- package/docs/functions/seq.html +15 -5
- package/docs/functions/seqEarlyBreak.html +15 -5
- package/docs/functions/set.html +15 -5
- package/docs/functions/setImmutable.html +15 -5
- package/docs/functions/sortBy.html +15 -5
- package/docs/functions/stripPrefix.html +122 -0
- package/docs/functions/stripSuffix.html +122 -0
- package/docs/functions/throttle.html +15 -5
- package/docs/functions/truthy.html +15 -5
- package/docs/functions/wait.html +15 -5
- package/docs/functions/waitFor.html +15 -5
- package/docs/functions/waitSync.html +15 -5
- package/docs/index.html +86 -22
- package/docs/interfaces/GetMultipleSource.html +15 -5
- package/docs/interfaces/GetSource.html +15 -5
- package/docs/interfaces/IsNumericStringOptions.html +90 -0
- package/docs/interfaces/OccurencesOptions.html +71 -0
- package/docs/interfaces/SetImmutableSource.html +15 -5
- package/docs/interfaces/SetSource.html +15 -5
- package/docs/interfaces/ThrottleOptions.html +7 -7
- package/docs/interfaces/ThrottledFunctionExtras.html +7 -7
- package/docs/modules.html +24 -4
- package/docs/pages/Introduction.html +14 -4
- package/docs/types/MapValuesFn.html +15 -5
- package/docs/types/MatchCallback.html +15 -5
- package/docs/types/SeqEarlyBreaker.html +15 -5
- package/docs/types/SeqFn.html +15 -5
- package/docs/types/SeqFunctions.html +15 -5
- package/docs/types/SetImmutablePath.html +15 -5
- package/docs/types/ThrottledFunction.html +15 -5
- package/docs/variables/mapValuesUNSET.html +15 -5
- package/docs/variables/mergeUNSET.html +15 -5
- package/esm/ensureDate.d.ts +3 -0
- package/esm/ensureDate.d.ts.map +1 -0
- package/esm/ensureDate.js +8 -0
- package/esm/ensureDate.js.map +1 -0
- package/esm/ensurePrefix.d.ts +3 -0
- package/esm/ensurePrefix.d.ts.map +1 -0
- package/esm/ensurePrefix.js +8 -0
- package/esm/ensurePrefix.js.map +1 -0
- package/esm/ensureSuffix.d.ts +3 -0
- package/esm/ensureSuffix.d.ts.map +1 -0
- package/esm/ensureSuffix.js +8 -0
- package/esm/ensureSuffix.js.map +1 -0
- package/esm/ensureTimestamp.d.ts +3 -0
- package/esm/ensureTimestamp.d.ts.map +1 -0
- package/esm/ensureTimestamp.js +8 -0
- package/esm/ensureTimestamp.js.map +1 -0
- package/esm/index.d.ts +8 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +8 -0
- package/esm/index.js.map +1 -1
- package/esm/isEmpty.js +1 -1
- package/esm/isEmpty.js.map +1 -1
- package/esm/isNumericString.d.ts +10 -0
- package/esm/isNumericString.d.ts.map +1 -0
- package/esm/isNumericString.js +58 -0
- package/esm/isNumericString.js.map +1 -0
- package/esm/occurrences.d.ts +7 -0
- package/esm/occurrences.d.ts.map +1 -0
- package/esm/occurrences.js +24 -0
- package/esm/occurrences.js.map +1 -0
- package/esm/stripPrefix.d.ts +3 -0
- package/esm/stripPrefix.d.ts.map +1 -0
- package/esm/stripPrefix.js +8 -0
- package/esm/stripPrefix.js.map +1 -0
- package/esm/stripSuffix.d.ts +3 -0
- package/esm/stripSuffix.d.ts.map +1 -0
- package/esm/stripSuffix.js +8 -0
- package/esm/stripSuffix.js.map +1 -0
- package/package.json +1 -1
- package/src/ensureDate.spec.ts +13 -0
- package/src/ensureDate.ts +18 -0
- package/src/ensurePrefix.spec.ts +11 -0
- package/src/ensurePrefix.ts +18 -0
- package/src/ensureSuffix.spec.ts +11 -0
- package/src/ensureSuffix.ts +18 -0
- package/src/ensureTimestamp.spec.ts +11 -0
- package/src/ensureTimestamp.ts +18 -0
- package/src/index.ts +8 -0
- package/src/isEmpty.ts +1 -1
- package/src/isNumericString.spec.ts +100 -0
- package/src/isNumericString.ts +94 -0
- package/src/occurrences.spec.ts +20 -0
- package/src/occurrences.ts +53 -0
- package/src/stripPrefix.spec.ts +13 -0
- package/src/stripPrefix.ts +15 -0
- package/src/stripSuffix.spec.ts +13 -0
- package/src/stripSuffix.ts +16 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const NOT_FOUND = -1;
|
|
2
|
+
const isNumericString = (string, options = {}) => {
|
|
3
|
+
if (typeof string !== "string") {
|
|
4
|
+
throw new TypeError("Expected a string");
|
|
5
|
+
}
|
|
6
|
+
if (options.allowNaN && string === "NaN") {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (options.allowInfinity && (string === "Infinity" || string === "-Infinity")) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
let normalized = string.toLowerCase();
|
|
13
|
+
if (normalized.startsWith("-")) {
|
|
14
|
+
normalized = normalized.slice(1);
|
|
15
|
+
}
|
|
16
|
+
const parts = normalized.split(".");
|
|
17
|
+
if (parts.length > (options.allowFloats ? 2 : 1)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const expParts = parts[parts.length - 1].split("e");
|
|
21
|
+
if (!options.allowExponents) {
|
|
22
|
+
if (expParts.length > 1) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
if (expParts.length > 2) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const hasPlusAt = normalized.indexOf("+");
|
|
32
|
+
if (hasPlusAt > NOT_FOUND) {
|
|
33
|
+
if (!options.allowExponents) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (hasPlusAt !== normalized.lastIndexOf("+")) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (hasPlusAt !== normalized.indexOf("e") + 1) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const hasMinusAt = normalized.indexOf("-");
|
|
44
|
+
if (hasMinusAt > NOT_FOUND) {
|
|
45
|
+
if (!options.allowExponents) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (hasMinusAt !== normalized.lastIndexOf("-")) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (hasMinusAt !== normalized.indexOf("e") + 1) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return Boolean(/^[\de.+-]+$/.exec(normalized));
|
|
56
|
+
};
|
|
57
|
+
export { isNumericString, };
|
|
58
|
+
//# sourceMappingURL=isNumericString.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isNumericString.js","sourceRoot":"","sources":["../src/isNumericString.ts"],"names":[],"mappings":"AAOA,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC;AAYrB,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,UAAmB,EAAE,EAAE,EAAE;IAC9D,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC5B,MAAM,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAAC;KAC5C;IAED,IAAI,OAAO,CAAC,QAAQ,IAAI,MAAM,KAAK,KAAK,EAAE;QACtC,OAAO,IAAI,CAAC;KACf;IAED,IAAI,OAAO,CAAC,aAAa,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,WAAW,CAAC,EAAE;QAC5E,OAAO,IAAI,CAAC;KACf;IAED,IAAI,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACtC,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAC5B,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACpC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAGpC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QAC9C,OAAO,KAAK,CAAC;KAChB;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;QACzB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YACrB,OAAO,KAAK,CAAC;SAChB;KACJ;SACI;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YACrB,OAAO,KAAK,CAAC;SAChB;KACJ;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,SAAS,GAAG,SAAS,EAAE;QACvB,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;YACzB,OAAO,KAAK,CAAC;SAChB;QACD,IAAI,SAAS,KAAK,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE;YAC3C,OAAO,KAAK,CAAC;SAChB;QACD,IAAI,SAAS,KAAK,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC3C,OAAO,KAAK,CAAC;SAChB;KACJ;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,UAAU,GAAG,SAAS,EAAE;QACxB,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;YACzB,OAAO,KAAK,CAAC;SAChB;QACD,IAAI,UAAU,KAAK,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE;YAC5C,OAAO,KAAK,CAAC;SAChB;QACD,IAAI,UAAU,KAAK,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC5C,OAAO,KAAK,CAAC;SAChB;KACJ;IAED,OAAO,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC;AAEF,OAAO,EACH,eAAe,GAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"occurrences.d.ts","sourceRoot":"","sources":["../src/occurrences.ts"],"names":[],"mappings":"AAAA,UAAU,OAAO;IAIb,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAeD,QAAA,MAAM,WAAW,WAAY,MAAM,UAAU,MAAM,gBAAe,OAAO,WAwBxE,CAAC;AAEF,OAAO,EACH,WAAW,GACd,CAAC;AAEF,YAAY,EACR,OAAO,IAAI,iBAAiB,GAC/B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const NOT_FOUND = -1;
|
|
2
|
+
const occurrences = (string, search, { overlap } = {}) => {
|
|
3
|
+
if (typeof string !== "string") {
|
|
4
|
+
throw new TypeError("Expected a string");
|
|
5
|
+
}
|
|
6
|
+
if (typeof search !== "string") {
|
|
7
|
+
throw new TypeError("Expected a string");
|
|
8
|
+
}
|
|
9
|
+
if (search.length === 0) {
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
let n = 0, i = 0;
|
|
13
|
+
while (true) {
|
|
14
|
+
i = string.indexOf(search, i);
|
|
15
|
+
if (i === NOT_FOUND) {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
n++;
|
|
19
|
+
i += overlap ? 1 : search.length;
|
|
20
|
+
}
|
|
21
|
+
return n;
|
|
22
|
+
};
|
|
23
|
+
export { occurrences, };
|
|
24
|
+
//# sourceMappingURL=occurrences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"occurrences.js","sourceRoot":"","sources":["../src/occurrences.ts"],"names":[],"mappings":"AAOA,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC;AAarB,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,MAAc,EAAE,EAAE,OAAO,KAAc,EAAE,EAAE,EAAE;IAC9E,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC5B,MAAM,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAAC;KAC5C;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC5B,MAAM,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAAC;KAC5C;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QACrB,OAAO,CAAC,CAAC;KACZ;IACD,IAAI,CAAC,GAAG,CAAC,EACL,CAAC,GAAG,CAAC,CAAC;IAGV,OAAO,IAAI,EAAE;QACT,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE9B,IAAI,CAAC,KAAK,SAAS,EAAE;YACjB,MAAM;SACT;QACD,CAAC,EAAE,CAAC;QACJ,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;KACpC;IACD,OAAO,CAAC,CAAC;AACb,CAAC,CAAC;AAEF,OAAO,EACH,WAAW,GACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripPrefix.d.ts","sourceRoot":"","sources":["../src/stripPrefix.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,WAAW,SAAU,MAAM,UAAU,MAAM,KAAG,MAKnD,CAAC;AAEF,OAAO,EACH,WAAW,GACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripPrefix.js","sourceRoot":"","sources":["../src/stripPrefix.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,MAAc,EAAU,EAAE;IACzD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACpC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF,OAAO,EACH,WAAW,GACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripSuffix.d.ts","sourceRoot":"","sources":["../src/stripSuffix.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,WAAW,SAAU,MAAM,UAAU,MAAM,KAAG,MAKnD,CAAC;AAEF,OAAO,EACH,WAAW,GACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripSuffix.js","sourceRoot":"","sources":["../src/stripSuffix.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,MAAc,EAAU,EAAE;IACzD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACxC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF,OAAO,EACH,WAAW,GACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ensureDate } from "./ensureDate.js";
|
|
2
|
+
|
|
3
|
+
describe("ensureDate", function() {
|
|
4
|
+
it("should convert timestamps to date instances", function() {
|
|
5
|
+
ensureDate(123456789).must.be.instanceOf(Date);
|
|
6
|
+
ensureDate(123456789).getTime().must.equal(123456789);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("should return the same date instance", function() {
|
|
10
|
+
const date = new Date(123456789);
|
|
11
|
+
ensureDate(date).must.equal(date);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure that the date value is a Date instance
|
|
3
|
+
*
|
|
4
|
+
* @example ensureDate(123456789); // Date(123456789)
|
|
5
|
+
* @example ensureDate(new Date(123456789)); // Date(123456789) -- same instance as given
|
|
6
|
+
* @see {@link ensureTimestamp}
|
|
7
|
+
* @param {Date | number} date - date value
|
|
8
|
+
*/
|
|
9
|
+
const ensureDate = (date: Date | number): Date => {
|
|
10
|
+
if (typeof date === "number") {
|
|
11
|
+
return new Date(date);
|
|
12
|
+
}
|
|
13
|
+
return date;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
ensureDate,
|
|
18
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ensurePrefix } from "./ensurePrefix.js";
|
|
2
|
+
|
|
3
|
+
describe("ensure prefix", function() {
|
|
4
|
+
it("adds prefix", function() {
|
|
5
|
+
ensurePrefix("1234bbcc", "0x").must.equal("0x1234bbcc");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it("doesn't add prefix if already present", function() {
|
|
9
|
+
ensurePrefix("0x1234bbcc", "0x").must.equal("0x1234bbcc");
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add prefix to string if it doesn't already have it
|
|
3
|
+
*
|
|
4
|
+
* @example ensurePrefix("1234bbcc", "0x") -> "0x1234bbcc"
|
|
5
|
+
* @example ensurePrefix("0x1234bbcc", "0x") -> "0x1234bbcc"
|
|
6
|
+
* @param {string} string - string to add prefix to
|
|
7
|
+
* @param {string} prefix - prefix to add
|
|
8
|
+
*/
|
|
9
|
+
const ensurePrefix = (string: string, prefix: string) => {
|
|
10
|
+
if (string.startsWith(prefix)) {
|
|
11
|
+
return string;
|
|
12
|
+
}
|
|
13
|
+
return prefix + string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
ensurePrefix,
|
|
18
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ensureSuffix } from "./ensureSuffix.js";
|
|
2
|
+
|
|
3
|
+
describe("ensure suffix", function() {
|
|
4
|
+
it("adds suffix to a string", function() {
|
|
5
|
+
ensureSuffix("hello world", ".").must.equal("hello world.");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it("doesn't add suffix if already present", function() {
|
|
9
|
+
ensureSuffix("hello world.", ".").must.equal("hello world.");
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add suffix to string if it does not already end with it
|
|
3
|
+
*
|
|
4
|
+
* @example ensureSuffix("hello world", ".") -> "hello world."
|
|
5
|
+
* @example ensureSuffix("hello world.", ".") -> "hello world."
|
|
6
|
+
* @param {string} string - string to add suffix to
|
|
7
|
+
* @param {string} suffix - suffix to add
|
|
8
|
+
*/
|
|
9
|
+
const ensureSuffix = (string: string, suffix: string) => {
|
|
10
|
+
if (string.endsWith(suffix)) {
|
|
11
|
+
return string;
|
|
12
|
+
}
|
|
13
|
+
return string + suffix;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
ensureSuffix,
|
|
18
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ensureTimestamp } from "./ensureTimestamp.js";
|
|
2
|
+
|
|
3
|
+
describe("ensure timestamp", function() {
|
|
4
|
+
it("returns number if number given", function() {
|
|
5
|
+
ensureTimestamp(123456789).must.equal(123456789);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it("returns number if date given", function() {
|
|
9
|
+
ensureTimestamp(new Date(123456789)).must.equal(123456789);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures that the given date value is a numeric timestamp.
|
|
3
|
+
*
|
|
4
|
+
* @example ensureTimestamp(123456789); // 123456789
|
|
5
|
+
* @example ensureTimestamp(new Date(123456789)); // 123456789
|
|
6
|
+
* @see {@link ensureDate}
|
|
7
|
+
* @param {Date | number} date - date value
|
|
8
|
+
*/
|
|
9
|
+
const ensureTimestamp = (date: Date | number): number => {
|
|
10
|
+
if (typeof date === "number") {
|
|
11
|
+
return date;
|
|
12
|
+
}
|
|
13
|
+
return date.getTime();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
ensureTimestamp,
|
|
18
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/* eslint-disable import/max-dependencies */
|
|
2
|
+
export * from "./ensurePrefix.js";
|
|
3
|
+
export * from "./ensureSuffix.js";
|
|
2
4
|
export * from "./cap.js";
|
|
3
5
|
export * from "./capitalize.js";
|
|
4
6
|
export * from "./coalesce.js";
|
|
5
7
|
export * from "./ensureArray.js";
|
|
8
|
+
export * from "./ensureDate.js";
|
|
6
9
|
export * from "./ensureError.js";
|
|
10
|
+
export * from "./ensureTimestamp.js";
|
|
7
11
|
export * from "./get.js";
|
|
8
12
|
export * from "./getMultiple.js";
|
|
9
13
|
export * from "./insertSeparator.js";
|
|
10
14
|
export * from "./isEmpty.js";
|
|
15
|
+
export * from "./isNumericString.js";
|
|
11
16
|
export * from "./isPlainObject.js";
|
|
12
17
|
export * from "./last.js";
|
|
13
18
|
export * from "./mapAsync.js";
|
|
@@ -16,6 +21,7 @@ export * from "./match.js";
|
|
|
16
21
|
export * from "./merge.js";
|
|
17
22
|
export * from "./mostFrequent.js";
|
|
18
23
|
export * from "./noop.js";
|
|
24
|
+
export * from "./occurrences.js";
|
|
19
25
|
export * from "./omit.js";
|
|
20
26
|
export * from "./pick.js";
|
|
21
27
|
export * from "./pull.js";
|
|
@@ -26,6 +32,8 @@ export * from "./seq.js";
|
|
|
26
32
|
export * from "./set.js";
|
|
27
33
|
export * from "./setImmutable.js";
|
|
28
34
|
export * from "./sortBy.js";
|
|
35
|
+
export * from "./stripPrefix.js";
|
|
36
|
+
export * from "./stripSuffix.js";
|
|
29
37
|
export * from "./throttle.js";
|
|
30
38
|
export * from "./truthy.js";
|
|
31
39
|
export * from "./wait.js";
|
package/src/isEmpty.ts
CHANGED
|
@@ -33,7 +33,7 @@ const isEmpty = (obj: unknown) => {
|
|
|
33
33
|
return true;
|
|
34
34
|
}
|
|
35
35
|
if (typeof obj !== "object") {
|
|
36
|
-
throw new
|
|
36
|
+
throw new TypeError("isEmpty cannot be used on primitives");
|
|
37
37
|
}
|
|
38
38
|
if (Array.isArray(obj)) {
|
|
39
39
|
return !Object.keys(obj).length;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { isNumericString } from "./isNumericString.js";
|
|
2
|
+
|
|
3
|
+
describe("isNumericString", function() {
|
|
4
|
+
it("crashes on non-strings", function() {
|
|
5
|
+
(() => isNumericString(1)).must.throw(TypeError);
|
|
6
|
+
(() => isNumericString({})).must.throw(TypeError);
|
|
7
|
+
(() => isNumericString([])).must.throw(TypeError);
|
|
8
|
+
(() => isNumericString(true)).must.throw(TypeError);
|
|
9
|
+
(() => isNumericString(() => null)).must.throw(TypeError);
|
|
10
|
+
(() => isNumericString(null)).must.throw(TypeError);
|
|
11
|
+
(() => isNumericString([1])).must.throw(TypeError);
|
|
12
|
+
(() => isNumericString(NaN)).must.throw(TypeError);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("returns true for basic numeric strings", function() {
|
|
16
|
+
isNumericString("1").must.be.true();
|
|
17
|
+
isNumericString("0").must.be.true();
|
|
18
|
+
isNumericString("-1").must.be.true();
|
|
19
|
+
isNumericString("123").must.be.true();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("only allows floats when requested", function() {
|
|
23
|
+
isNumericString("1.2", { allowFloats: true }).must.be.true();
|
|
24
|
+
isNumericString("1.2", { allowFloats: false }).must.be.false();
|
|
25
|
+
isNumericString("1.2").must.be.false();
|
|
26
|
+
|
|
27
|
+
isNumericString(".2", { allowFloats: true }).must.be.true();
|
|
28
|
+
isNumericString("2.", { allowFloats: true }).must.be.true();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("only allow exponents when requested", function() {
|
|
32
|
+
isNumericString("1e2", { allowExponents: true }).must.be.true();
|
|
33
|
+
isNumericString("1e2", { allowExponents: false }).must.be.false();
|
|
34
|
+
isNumericString("1e2").must.be.false();
|
|
35
|
+
|
|
36
|
+
isNumericString("1e+2", { allowExponents: true }).must.be.true();
|
|
37
|
+
isNumericString("1e-2", { allowExponents: true }).must.be.true();
|
|
38
|
+
isNumericString("1e2", { allowExponents: true }).must.be.true();
|
|
39
|
+
isNumericString("1E-2", { allowExponents: true }).must.be.true();
|
|
40
|
+
isNumericString("1E+2", { allowExponents: true }).must.be.true();
|
|
41
|
+
isNumericString("1E2", { allowExponents: true }).must.be.true();
|
|
42
|
+
|
|
43
|
+
isNumericString("1e+2").must.be.false();
|
|
44
|
+
isNumericString("1e-2").must.be.false();
|
|
45
|
+
isNumericString("1e2").must.be.false();
|
|
46
|
+
isNumericString("1E-2").must.be.false();
|
|
47
|
+
isNumericString("1E+2").must.be.false();
|
|
48
|
+
isNumericString("1E2").must.be.false();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("only allows expotents with floats when requested", function() {
|
|
52
|
+
isNumericString("1.3e2", { allowExponents: true, allowFloats: true }).must.be.true();
|
|
53
|
+
isNumericString("1.3e2", { allowExponents: false, allowFloats: true }).must.be.false();
|
|
54
|
+
isNumericString("1.3e2", { allowExponents: true, allowFloats: false }).must.be.false();
|
|
55
|
+
|
|
56
|
+
isNumericString(".3e2", { allowExponents: true, allowFloats: true }).must.be.true();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("returns false for non-numeric strings", function() {
|
|
60
|
+
isNumericString("+5").must.be.false();
|
|
61
|
+
isNumericString("a").must.be.false();
|
|
62
|
+
isNumericString("1a").must.be.false();
|
|
63
|
+
isNumericString("a1").must.be.false();
|
|
64
|
+
isNumericString("1e").must.be.false();
|
|
65
|
+
isNumericString("1e-+1").must.be.false();
|
|
66
|
+
isNumericString("1e+-1").must.be.false();
|
|
67
|
+
isNumericString("1e--1").must.be.false();
|
|
68
|
+
isNumericString("1e++1").must.be.false();
|
|
69
|
+
isNumericString("1e10e2").must.be.false();
|
|
70
|
+
isNumericString("1.2.3").must.be.false();
|
|
71
|
+
isNumericString("1.2e3.4").must.be.false();
|
|
72
|
+
isNumericString("1.2e-3.4").must.be.false();
|
|
73
|
+
isNumericString("1.2e+3.4").must.be.false();
|
|
74
|
+
isNumericString("NaN").must.be.false();
|
|
75
|
+
isNumericString("12e20-2").must.be.false();
|
|
76
|
+
isNumericString("12e20+2").must.be.false();
|
|
77
|
+
isNumericString("12+e202").must.be.false();
|
|
78
|
+
isNumericString("12-e202").must.be.false();
|
|
79
|
+
isNumericString("1+2e202").must.be.false();
|
|
80
|
+
isNumericString("1-2e202").must.be.false();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("allows NaN when requeted", function() {
|
|
84
|
+
isNumericString("NaN", { allowNaN: true }).must.be.true();
|
|
85
|
+
isNumericString("NaN", { allowNaN: false }).must.be.false();
|
|
86
|
+
|
|
87
|
+
isNumericString("-NaN", { allowNaN: false }).must.be.false();
|
|
88
|
+
isNumericString("+NaN", { allowNaN: false }).must.be.false();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("allows positive and negative Infinity when requested", function() {
|
|
92
|
+
isNumericString("Infinity", { allowInfinity: true }).must.be.true();
|
|
93
|
+
isNumericString("Infinity", { allowInfinity: false }).must.be.false();
|
|
94
|
+
isNumericString("-Infinity", { allowInfinity: true }).must.be.true();
|
|
95
|
+
isNumericString("-Infinity", { allowInfinity: false }).must.be.false();
|
|
96
|
+
|
|
97
|
+
// plus is still not allowed
|
|
98
|
+
isNumericString("+Infinity", { allowInfinity: true }).must.be.false();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
interface Options {
|
|
2
|
+
allowFloats?: boolean;
|
|
3
|
+
allowExponents?: boolean;
|
|
4
|
+
allowInfinity?: boolean;
|
|
5
|
+
allowNaN?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const NOT_FOUND = -1;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a string is a numeric string. By default, it allows only integers. Floats and exponents can be enabled with
|
|
12
|
+
* options. Optionally allow NaN and Infinity.
|
|
13
|
+
* @param {string} string - String to check
|
|
14
|
+
* @param {object} [options] - Options object
|
|
15
|
+
* @param {boolean} [options.allowFloats=false] - Allow floats
|
|
16
|
+
* @param {boolean} [options.allowExponents=false] - Allow exponents
|
|
17
|
+
* @param {boolean} [options.allowInfinity=false] - Allow Initity and -Infinity (casing matters)
|
|
18
|
+
* @param {boolean} [options.allowNaN=false] - Allow NaN (casing matters)
|
|
19
|
+
*/
|
|
20
|
+
const isNumericString = (string: string, options: Options = {}) => { // eslint-disable-line max-statements, max-lines-per-function, max-len
|
|
21
|
+
if (typeof string !== "string") {
|
|
22
|
+
throw new TypeError("Expected a string");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (options.allowNaN && string === "NaN") {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (options.allowInfinity && (string === "Infinity" || string === "-Infinity")) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let normalized = string.toLowerCase();
|
|
34
|
+
if (normalized.startsWith("-")) {
|
|
35
|
+
normalized = normalized.slice(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const parts = normalized.split(".");
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
41
|
+
if (parts.length > (options.allowFloats ? 2 : 1)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const expParts = parts[parts.length - 1].split("e");
|
|
46
|
+
|
|
47
|
+
if (!options.allowExponents) {
|
|
48
|
+
if (expParts.length > 1) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
54
|
+
if (expParts.length > 2) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const hasPlusAt = normalized.indexOf("+");
|
|
60
|
+
if (hasPlusAt > NOT_FOUND) {
|
|
61
|
+
if (!options.allowExponents) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (hasPlusAt !== normalized.lastIndexOf("+")) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (hasPlusAt !== normalized.indexOf("e") + 1) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const hasMinusAt = normalized.indexOf("-");
|
|
73
|
+
if (hasMinusAt > NOT_FOUND) {
|
|
74
|
+
if (!options.allowExponents) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (hasMinusAt !== normalized.lastIndexOf("-")) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (hasMinusAt !== normalized.indexOf("e") + 1) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return Boolean(/^[\de.+-]+$/.exec(normalized));
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
isNumericString,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export type {
|
|
93
|
+
Options as IsNumericStringOptions,
|
|
94
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { occurrences } from "./occurrences.js";
|
|
2
|
+
|
|
3
|
+
describe("occurrences", function() {
|
|
4
|
+
it("returns zero for empty search string", function() {
|
|
5
|
+
occurrences("test string", "").must.equal(0);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it("returns count of occurences for typical use cases", function() {
|
|
9
|
+
occurrences("hello beautiful world, hello bees and hello sun", "hello").must.equal(3);
|
|
10
|
+
occurrences("hello beautiful world, hello bees and hello sun", "o").must.equal(4);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("allows counting overlaps too", function() {
|
|
14
|
+
occurrences("aaaa", "aa", { overlap: true }).must.equal(3);
|
|
15
|
+
occurrences("aaaa", "aa", { overlap: false }).must.equal(2);
|
|
16
|
+
|
|
17
|
+
occurrences("aaaaaa", "aa", { overlap: true }).must.equal(5);
|
|
18
|
+
occurrences("aaaaaa", "aa", { overlap: false }).must.equal(3);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
interface Options {
|
|
2
|
+
/**
|
|
3
|
+
* Allow overlapping matches, ie. "aa" in "aaa" will return 2 instead of 1
|
|
4
|
+
*/
|
|
5
|
+
overlap?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const NOT_FOUND = -1;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Count the number of occurrences of a substring in a string
|
|
12
|
+
*
|
|
13
|
+
* @example occurrences("aaa", "a"); // 3
|
|
14
|
+
* @example occurrences("aaaa", "aa", { overlap: false }); // 2
|
|
15
|
+
* @example occurrences("aaaa", "aa", { overlap: true }); // 3
|
|
16
|
+
* @param {string} string - string to search in
|
|
17
|
+
* @param {string} search - string to search for
|
|
18
|
+
* @param {object} [options] - options
|
|
19
|
+
* @param {boolean} [options.overlap=false] - allow overlapping matches, ie "aa" in "aaa" will return 2 instead of 1
|
|
20
|
+
*/
|
|
21
|
+
const occurrences = (string: string, search: string, { overlap }: Options = {}) => {
|
|
22
|
+
if (typeof string !== "string") {
|
|
23
|
+
throw new TypeError("Expected a string");
|
|
24
|
+
}
|
|
25
|
+
if (typeof search !== "string") {
|
|
26
|
+
throw new TypeError("Expected a string");
|
|
27
|
+
}
|
|
28
|
+
if (search.length === 0) {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
let n = 0,
|
|
32
|
+
i = 0;
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line no-constant-condition,@typescript-eslint/no-unnecessary-condition
|
|
35
|
+
while (true) {
|
|
36
|
+
i = string.indexOf(search, i);
|
|
37
|
+
|
|
38
|
+
if (i === NOT_FOUND) {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
n++;
|
|
42
|
+
i += overlap ? 1 : search.length;
|
|
43
|
+
}
|
|
44
|
+
return n;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
occurrences,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type {
|
|
52
|
+
Options as OccurencesOptions,
|
|
53
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { stripPrefix } from "./stripPrefix.js";
|
|
2
|
+
|
|
3
|
+
describe("strip prefix", function() {
|
|
4
|
+
it("should strip prefix if string has it", function() {
|
|
5
|
+
stripPrefix("abc", "a").must.equal("bc");
|
|
6
|
+
stripPrefix("hello world", "hello").must.equal(" world");
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("should keep the string as it is when string don't have specified prefix", function() {
|
|
10
|
+
stripPrefix("abc", "b").must.equal("abc");
|
|
11
|
+
stripPrefix("hello world", "world").must.equal("hello world");
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip a prefix from a string.
|
|
3
|
+
* @param {string} from - string to strip prefix from
|
|
4
|
+
* @param {string} prefix - prefix to strip
|
|
5
|
+
*/
|
|
6
|
+
const stripPrefix = (from: string, prefix: string): string => {
|
|
7
|
+
if (from.startsWith(prefix)) {
|
|
8
|
+
return from.slice(prefix.length);
|
|
9
|
+
}
|
|
10
|
+
return from;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
stripPrefix,
|
|
15
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { stripSuffix } from "./stripSuffix.js";
|
|
2
|
+
|
|
3
|
+
describe("strip suffix", function() {
|
|
4
|
+
it("should strip suffix if string has it", function() {
|
|
5
|
+
stripSuffix("abc", "c").must.equal("ab");
|
|
6
|
+
stripSuffix("hello world", "world").must.equal("hello ");
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("should keep the string as it is when string don't have specified suffix", function() {
|
|
10
|
+
stripSuffix("abc", "b").must.equal("abc");
|
|
11
|
+
stripSuffix("hello world", "hello").must.equal("hello world");
|
|
12
|
+
});
|
|
13
|
+
});
|