shelving 1.115.0 → 1.116.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/package.json +1 -1
- package/schema/DateSchema.d.ts +6 -5
- package/schema/LinkSchema.d.ts +5 -4
- package/schema/NumberSchema.d.ts +2 -2
- package/schema/NumberSchema.js +1 -1
- package/schema/TimeSchema.d.ts +8 -7
- package/store/PathStore.d.ts +3 -3
- package/store/PathStore.js +4 -4
- package/util/color.d.ts +4 -5
- package/util/color.js +13 -13
- package/util/date.d.ts +7 -9
- package/util/date.js +20 -21
- package/util/number.d.ts +6 -6
- package/util/number.js +7 -8
- package/util/path.d.ts +3 -1
- package/util/path.js +3 -2
- package/util/string.d.ts +5 -5
- package/util/string.js +8 -8
- package/util/time.d.ts +4 -8
- package/util/time.js +20 -18
- package/util/url.d.ts +4 -4
- package/util/url.js +12 -10
package/package.json
CHANGED
package/schema/DateSchema.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import type { SchemaOptions } from "./Schema.js";
|
|
2
|
-
import type { PossibleDate
|
|
2
|
+
import type { PossibleDate } from "../util/date.js";
|
|
3
|
+
import type { Optional } from "../util/optional.js";
|
|
3
4
|
import { Schema } from "./Schema.js";
|
|
4
5
|
/** Allowed options for `DateSchema` */
|
|
5
6
|
export type DateSchemaOptions = SchemaOptions & {
|
|
6
7
|
readonly value?: PossibleDate | undefined;
|
|
7
|
-
readonly min?:
|
|
8
|
-
readonly max?:
|
|
8
|
+
readonly min?: Optional<PossibleDate> | undefined;
|
|
9
|
+
readonly max?: Optional<PossibleDate> | undefined;
|
|
9
10
|
};
|
|
10
11
|
/** Define a valid date in YMD format, e.g. `2005-09-12` */
|
|
11
12
|
export declare class DateSchema extends Schema<string> {
|
|
12
13
|
readonly value: PossibleDate;
|
|
13
|
-
readonly min: Date |
|
|
14
|
-
readonly max: Date |
|
|
14
|
+
readonly min: Date | undefined;
|
|
15
|
+
readonly max: Date | undefined;
|
|
15
16
|
constructor(options: DateSchemaOptions);
|
|
16
17
|
validate(unsafeValue?: unknown): string;
|
|
17
18
|
}
|
package/schema/LinkSchema.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { StringSchemaOptions } from "./StringSchema.js";
|
|
2
|
+
import type { ImmutableArray } from "../util/array.js";
|
|
2
3
|
import { StringSchema } from "./StringSchema.js";
|
|
3
4
|
/** Allowed options for `LinkSchema` */
|
|
4
5
|
export type LinkSchemaOptions = Omit<StringSchemaOptions, "type" | "min" | "max" | "multiline"> & {
|
|
5
|
-
readonly schemes?: string
|
|
6
|
-
readonly hosts?: string
|
|
6
|
+
readonly schemes?: ImmutableArray<string> | undefined;
|
|
7
|
+
readonly hosts?: ImmutableArray<string> | undefined;
|
|
7
8
|
};
|
|
8
9
|
/**
|
|
9
10
|
* Type of `StringSchema` that defines a valid URL.
|
|
@@ -12,8 +13,8 @@ export type LinkSchemaOptions = Omit<StringSchemaOptions, "type" | "min" | "max"
|
|
|
12
13
|
* - Falsy values are converted to `""` empty string.
|
|
13
14
|
*/
|
|
14
15
|
export declare class LinkSchema extends StringSchema {
|
|
15
|
-
readonly schemes: string
|
|
16
|
-
readonly hosts: string
|
|
16
|
+
readonly schemes: ImmutableArray<string>;
|
|
17
|
+
readonly hosts: ImmutableArray<string> | undefined;
|
|
17
18
|
constructor(options: LinkSchemaOptions);
|
|
18
19
|
validate(unsafeValue: unknown): string;
|
|
19
20
|
}
|
package/schema/NumberSchema.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ export type NumberSchemaOptions = SchemaOptions & {
|
|
|
5
5
|
readonly value?: number | undefined;
|
|
6
6
|
readonly min?: number | undefined;
|
|
7
7
|
readonly max?: number | undefined;
|
|
8
|
-
readonly step?: number |
|
|
8
|
+
readonly step?: number | undefined;
|
|
9
9
|
};
|
|
10
10
|
/** Schema that defines a valid number. */
|
|
11
11
|
export declare class NumberSchema extends Schema<number> {
|
|
12
12
|
readonly value: number;
|
|
13
13
|
readonly min: number;
|
|
14
14
|
readonly max: number;
|
|
15
|
-
readonly step: number |
|
|
15
|
+
readonly step: number | undefined;
|
|
16
16
|
constructor(options: NumberSchemaOptions);
|
|
17
17
|
validate(unsafeValue?: unknown): number;
|
|
18
18
|
}
|
package/schema/NumberSchema.js
CHANGED
|
@@ -9,7 +9,7 @@ export class NumberSchema extends Schema {
|
|
|
9
9
|
step;
|
|
10
10
|
constructor(options) {
|
|
11
11
|
super({ title: "Number", value: 0, ...options });
|
|
12
|
-
const { min = -Infinity, max = Infinity, step
|
|
12
|
+
const { min = -Infinity, max = Infinity, step } = options;
|
|
13
13
|
this.min = min;
|
|
14
14
|
this.max = max;
|
|
15
15
|
this.step = step;
|
package/schema/TimeSchema.d.ts
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import type { SchemaOptions } from "./Schema.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Optional } from "../util/optional.js";
|
|
3
|
+
import type { PossibleTime } from "../util/time.js";
|
|
3
4
|
import { Time } from "../util/time.js";
|
|
4
5
|
import { Schema } from "./Schema.js";
|
|
5
6
|
/** Allowed options for `TimeSchama` */
|
|
6
7
|
export type TimeSchemaOptions = SchemaOptions & {
|
|
7
8
|
readonly value?: PossibleTime | undefined;
|
|
8
|
-
readonly min?:
|
|
9
|
-
readonly max?:
|
|
10
|
-
readonly step?: number |
|
|
9
|
+
readonly min?: Optional<PossibleTime> | undefined;
|
|
10
|
+
readonly max?: Optional<PossibleTime> | undefined;
|
|
11
|
+
readonly step?: number | undefined;
|
|
11
12
|
};
|
|
12
13
|
/** Define a valid time in 24h hh:mm:ss.fff format, e.g. `23:59` or `24:00 */
|
|
13
14
|
export declare class TimeSchema extends Schema<string> {
|
|
14
15
|
readonly value: PossibleTime;
|
|
15
|
-
readonly min: Time |
|
|
16
|
-
readonly max: Time |
|
|
16
|
+
readonly min: Time | undefined;
|
|
17
|
+
readonly max: Time | undefined;
|
|
17
18
|
/**
|
|
18
19
|
* Rounding step (in milliseconds, because that's the base unit for time), e.g. `60000` will round to the nearest second.
|
|
19
20
|
* - Note: `<input type="time">` elements expect `step=""` to be in _seconds_ so you need to multiply this by `1000`
|
|
20
21
|
*/
|
|
21
|
-
readonly step: number |
|
|
22
|
+
readonly step: number | undefined;
|
|
22
23
|
constructor(options: TimeSchemaOptions);
|
|
23
24
|
validate(unsafeValue?: unknown): string;
|
|
24
25
|
}
|
package/store/PathStore.d.ts
CHANGED
|
@@ -3,12 +3,12 @@ import type { PossibleStarter } from "../util/start.js";
|
|
|
3
3
|
import { Store } from "./Store.js";
|
|
4
4
|
/** Store an absolute path, e.g. `/a/b/c` */
|
|
5
5
|
export declare class PathStore extends Store<AbsolutePath> {
|
|
6
|
-
constructor(path?:
|
|
6
|
+
constructor(path?: string, time?: number, start?: PossibleStarter<[Store<AbsolutePath>]>);
|
|
7
7
|
/** Based on the current store path, is a path active? */
|
|
8
8
|
isActive(path: AbsolutePath): boolean;
|
|
9
9
|
/** Based on the current store path, is a path proud (i.e. a child of the current store path)? */
|
|
10
10
|
isProud(path: AbsolutePath): boolean;
|
|
11
|
-
/** Get an absolute path from a path relative to the current
|
|
12
|
-
|
|
11
|
+
/** Get an absolute path from a path relative to the current store path. */
|
|
12
|
+
getPath(path: string): AbsolutePath;
|
|
13
13
|
set(path: string): void;
|
|
14
14
|
}
|
package/store/PathStore.js
CHANGED
|
@@ -2,8 +2,8 @@ import { getPath, isPathActive, isPathProud } from "../util/path.js";
|
|
|
2
2
|
import { Store } from "./Store.js";
|
|
3
3
|
/** Store an absolute path, e.g. `/a/b/c` */
|
|
4
4
|
export class PathStore extends Store {
|
|
5
|
-
constructor(path =
|
|
6
|
-
super(path, time, start);
|
|
5
|
+
constructor(path = ".", time, start) {
|
|
6
|
+
super(getPath(path), time, start);
|
|
7
7
|
}
|
|
8
8
|
/** Based on the current store path, is a path active? */
|
|
9
9
|
isActive(path) {
|
|
@@ -13,8 +13,8 @@ export class PathStore extends Store {
|
|
|
13
13
|
isProud(path) {
|
|
14
14
|
return isPathProud(path, this.value);
|
|
15
15
|
}
|
|
16
|
-
/** Get an absolute path from a path relative to the current
|
|
17
|
-
|
|
16
|
+
/** Get an absolute path from a path relative to the current store path. */
|
|
17
|
+
getPath(path) {
|
|
18
18
|
return getPath(path, this.value);
|
|
19
19
|
}
|
|
20
20
|
// Override to clean the path.
|
package/util/color.d.ts
CHANGED
|
@@ -2,11 +2,10 @@ export declare const HEX3_REGEXP: RegExp;
|
|
|
2
2
|
export declare const HEX6_REGEXP: RegExp;
|
|
3
3
|
/** Things that can be converted to a `Color` instance. */
|
|
4
4
|
export type PossibleColor = Color | string;
|
|
5
|
-
export type PossibleOptionalColor = PossibleColor | null;
|
|
6
5
|
/** Represent a color. */
|
|
7
6
|
export declare class Color {
|
|
8
|
-
/** Make a `Color` from
|
|
9
|
-
static
|
|
7
|
+
/** Make a `Color` from an unknown value. */
|
|
8
|
+
static from(possible: unknown): Color | undefined;
|
|
10
9
|
readonly r: number;
|
|
11
10
|
readonly g: number;
|
|
12
11
|
readonly b: number;
|
|
@@ -30,7 +29,7 @@ export declare class Color {
|
|
|
30
29
|
export declare const isColor: (value: unknown) => value is Color;
|
|
31
30
|
/** Assert that an unknown value is a `Color` instance. */
|
|
32
31
|
export declare function assertColor(value: unknown): asserts value is Color;
|
|
33
|
-
/** Convert a possible color to a `Color` instance or `
|
|
34
|
-
export declare function getOptionalColor(possible: unknown): Color |
|
|
32
|
+
/** Convert a possible color to a `Color` instance or `undefined` */
|
|
33
|
+
export declare function getOptionalColor(possible: unknown): Color | undefined;
|
|
35
34
|
/** Convert a possible color to a `Color` instance */
|
|
36
35
|
export declare function getColor(possible: PossibleColor): Color;
|
package/util/color.js
CHANGED
|
@@ -7,13 +7,17 @@ export const HEX3_REGEXP = /^#?([0-F])([0-F])([0-F])$/i;
|
|
|
7
7
|
export const HEX6_REGEXP = /^#?([0-F]{2})([0-F]{2})([0-F]{2})([0-F]{2})?$/i;
|
|
8
8
|
/** Represent a color. */
|
|
9
9
|
export class Color {
|
|
10
|
-
/** Make a `Color` from
|
|
11
|
-
static
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
/** Make a `Color` from an unknown value. */
|
|
11
|
+
static from(possible) {
|
|
12
|
+
if (isColor(possible))
|
|
13
|
+
return possible;
|
|
14
|
+
if (typeof possible === "string") {
|
|
15
|
+
const matches = (possible.match(HEX3_REGEXP) || possible.match(HEX6_REGEXP));
|
|
16
|
+
if (matches) {
|
|
17
|
+
const [, r, g, b, a] = matches;
|
|
18
|
+
return new Color(_parse(r), _parse(g), _parse(b), typeof a === "string" ? _parse(a) : undefined);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
r;
|
|
19
23
|
g;
|
|
@@ -63,13 +67,9 @@ export function assertColor(value) {
|
|
|
63
67
|
if (!isColor(value))
|
|
64
68
|
throw new AssertionError("Invalid color", value);
|
|
65
69
|
}
|
|
66
|
-
/** Convert a possible color to a `Color` instance or `
|
|
70
|
+
/** Convert a possible color to a `Color` instance or `undefined` */
|
|
67
71
|
export function getOptionalColor(possible) {
|
|
68
|
-
|
|
69
|
-
return possible;
|
|
70
|
-
if (typeof possible === "string")
|
|
71
|
-
return Color.fromHex(possible);
|
|
72
|
-
return null;
|
|
72
|
+
return Color.from(possible);
|
|
73
73
|
}
|
|
74
74
|
/** Convert a possible color to a `Color` instance */
|
|
75
75
|
export function getColor(possible) {
|
package/util/date.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/** Things that converted to dates. */
|
|
2
2
|
export type PossibleDate = Date | number | string;
|
|
3
|
-
/** Things that converted to dates or `null` */
|
|
4
|
-
export type PossibleOptionalDate = Date | number | string | null;
|
|
5
3
|
/** Is a value a date? */
|
|
6
4
|
export declare function isDate(value: unknown): value is Date;
|
|
7
5
|
/** Assert that a value is a `Date` instance. */
|
|
@@ -12,7 +10,7 @@ export declare function assertDate(value: unknown): asserts value is Date;
|
|
|
12
10
|
*
|
|
13
11
|
* Conversion rules:
|
|
14
12
|
* - `Date` instance returns unchanged (BUT if the date isn't valid, `null` is returned).
|
|
15
|
-
* - `null` returns `
|
|
13
|
+
* - `null` or `""` empty string or the string `"none"` returns `undefined`
|
|
16
14
|
* - `undefined` returns the current date (e.g. `new Date()`).
|
|
17
15
|
* - The string `"now"` returns the current date (e.g. `new Date()`).
|
|
18
16
|
* - The string `"today"` returns the current date at midnight (e.g. `getMidnight()`).
|
|
@@ -25,15 +23,15 @@ export declare function assertDate(value: unknown): asserts value is Date;
|
|
|
25
23
|
* @param possible Any value that we want to parse as a valid date.
|
|
26
24
|
* @returns `Date` instance if the value could be converted to a valid date, and `null` if not.
|
|
27
25
|
*/
|
|
28
|
-
export declare function getOptionalDate(possible
|
|
26
|
+
export declare function getOptionalDate(possible?: unknown): Date | undefined;
|
|
29
27
|
/** Convert a possible date to a `Date` instance, or throw `AssertionError` if it couldn't be converted. */
|
|
30
28
|
export declare function getDate(possible?: PossibleDate): Date;
|
|
31
|
-
/** Convert an unknown value to a timestamp (milliseconds past Unix epoch), or `
|
|
32
|
-
export declare function getOptionalTimestamp(possible: unknown): number |
|
|
29
|
+
/** Convert an unknown value to a timestamp (milliseconds past Unix epoch), or `undefined` if it couldn't be converted. */
|
|
30
|
+
export declare function getOptionalTimestamp(possible: unknown): number | undefined;
|
|
33
31
|
/** Convert a possible date to a timestamp (milliseconds past Unix epoch), or throw `AssertionError` if it couldn't be converted. */
|
|
34
32
|
export declare function getTimestamp(possible?: PossibleDate): number;
|
|
35
|
-
/** Convert an unknown value to a YMD date string like "2015-09-12", or `
|
|
36
|
-
export declare function getOptionalYMD(possible: unknown): string |
|
|
33
|
+
/** Convert an unknown value to a YMD date string like "2015-09-12", or `undefined` if it couldn't be converted. */
|
|
34
|
+
export declare function getOptionalYMD(possible: unknown): string | undefined;
|
|
37
35
|
/** Convert a `Date` instance to a YMD string like "2015-09-12", or throw `AssertionError` if it couldn't be converted. */
|
|
38
36
|
export declare function getYMD(possible?: PossibleDate): string;
|
|
39
37
|
/** List of day-of-week strings. */
|
|
@@ -78,4 +76,4 @@ export declare function isToday(target: PossibleDate, current?: PossibleDate): b
|
|
|
78
76
|
/** Format a date in the browser locale. */
|
|
79
77
|
export declare function formatDate(date: PossibleDate): string;
|
|
80
78
|
/** Format an optional time as a string. */
|
|
81
|
-
export declare function formatOptionalDate(date?: unknown): string |
|
|
79
|
+
export declare function formatOptionalDate(date?: unknown): string | undefined;
|
package/util/date.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AssertionError } from "../error/AssertionError.js";
|
|
2
2
|
/** Is a value a date? */
|
|
3
3
|
export function isDate(value) {
|
|
4
|
-
return value instanceof Date;
|
|
4
|
+
return value instanceof Date && Number.isFinite(value.getTime());
|
|
5
5
|
}
|
|
6
6
|
/** Assert that a value is a `Date` instance. */
|
|
7
7
|
export function assertDate(value) {
|
|
@@ -14,7 +14,7 @@ export function assertDate(value) {
|
|
|
14
14
|
*
|
|
15
15
|
* Conversion rules:
|
|
16
16
|
* - `Date` instance returns unchanged (BUT if the date isn't valid, `null` is returned).
|
|
17
|
-
* - `null` returns `
|
|
17
|
+
* - `null` or `""` empty string or the string `"none"` returns `undefined`
|
|
18
18
|
* - `undefined` returns the current date (e.g. `new Date()`).
|
|
19
19
|
* - The string `"now"` returns the current date (e.g. `new Date()`).
|
|
20
20
|
* - The string `"today"` returns the current date at midnight (e.g. `getMidnight()`).
|
|
@@ -27,46 +27,45 @@ export function assertDate(value) {
|
|
|
27
27
|
* @param possible Any value that we want to parse as a valid date.
|
|
28
28
|
* @returns `Date` instance if the value could be converted to a valid date, and `null` if not.
|
|
29
29
|
*/
|
|
30
|
-
export function getOptionalDate(possible) {
|
|
31
|
-
if (possible ===
|
|
30
|
+
export function getOptionalDate(possible = "now") {
|
|
31
|
+
if (possible === null)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (possible === "now")
|
|
32
34
|
return new Date();
|
|
33
|
-
if (isDate(possible))
|
|
34
|
-
return _getValidDate(possible);
|
|
35
35
|
if (possible === "today")
|
|
36
36
|
return getMidnight();
|
|
37
37
|
if (possible === "tomorrow")
|
|
38
38
|
return addDays(1, getMidnight());
|
|
39
39
|
if (possible === "yesterday")
|
|
40
40
|
return addDays(-1, getMidnight());
|
|
41
|
-
if (possible
|
|
42
|
-
return
|
|
43
|
-
if (typeof possible === "string" || typeof possible === "number")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return Number.isFinite(date.getTime()) ? date : null;
|
|
41
|
+
if (isDate(possible))
|
|
42
|
+
return possible;
|
|
43
|
+
if (typeof possible === "string" || typeof possible === "number") {
|
|
44
|
+
const date = new Date(possible);
|
|
45
|
+
if (Number.isFinite(date.getTime()))
|
|
46
|
+
return date;
|
|
47
|
+
}
|
|
49
48
|
}
|
|
50
49
|
/** Convert a possible date to a `Date` instance, or throw `AssertionError` if it couldn't be converted. */
|
|
51
|
-
export function getDate(possible
|
|
50
|
+
export function getDate(possible) {
|
|
52
51
|
const date = getOptionalDate(possible);
|
|
53
52
|
if (!date)
|
|
54
53
|
throw new AssertionError(`Must be date`, possible);
|
|
55
54
|
return date;
|
|
56
55
|
}
|
|
57
|
-
/** Convert an unknown value to a timestamp (milliseconds past Unix epoch), or `
|
|
56
|
+
/** Convert an unknown value to a timestamp (milliseconds past Unix epoch), or `undefined` if it couldn't be converted. */
|
|
58
57
|
export function getOptionalTimestamp(possible) {
|
|
59
|
-
|
|
60
|
-
return date ? date.getTime() : null;
|
|
58
|
+
return getOptionalDate(possible)?.getTime();
|
|
61
59
|
}
|
|
62
60
|
/** Convert a possible date to a timestamp (milliseconds past Unix epoch), or throw `AssertionError` if it couldn't be converted. */
|
|
63
61
|
export function getTimestamp(possible) {
|
|
64
62
|
return getDate(possible).getTime();
|
|
65
63
|
}
|
|
66
|
-
/** Convert an unknown value to a YMD date string like "2015-09-12", or `
|
|
64
|
+
/** Convert an unknown value to a YMD date string like "2015-09-12", or `undefined` if it couldn't be converted. */
|
|
67
65
|
export function getOptionalYMD(possible) {
|
|
68
66
|
const date = getOptionalDate(possible);
|
|
69
|
-
|
|
67
|
+
if (date)
|
|
68
|
+
return _ymd(date);
|
|
70
69
|
}
|
|
71
70
|
/** Convert a `Date` instance to a YMD string like "2015-09-12", or throw `AssertionError` if it couldn't be converted. */
|
|
72
71
|
export function getYMD(possible) {
|
|
@@ -166,5 +165,5 @@ export function formatDate(date) {
|
|
|
166
165
|
}
|
|
167
166
|
/** Format an optional time as a string. */
|
|
168
167
|
export function formatOptionalDate(date) {
|
|
169
|
-
return getOptionalDate(date)?.toLocaleDateString()
|
|
168
|
+
return getOptionalDate(date)?.toLocaleDateString();
|
|
170
169
|
}
|
package/util/number.d.ts
CHANGED
|
@@ -19,16 +19,16 @@ export declare function assertMax(value: unknown, max: number): asserts value is
|
|
|
19
19
|
/** Assert that a value is a number less than. */
|
|
20
20
|
export declare function assertMin(value: unknown, min: number): asserts value is number;
|
|
21
21
|
/**
|
|
22
|
-
* Convert an unknown value to a finite number or `
|
|
23
|
-
* - Note: numbers can be non-finite numbers like `NaN` or `Infinity`. These are detected and will always return `
|
|
22
|
+
* Convert an unknown value to a finite number or `undefined`
|
|
23
|
+
* - Note: numbers can be non-finite numbers like `NaN` or `Infinity`. These are detected and will always return `undefined`
|
|
24
24
|
*
|
|
25
25
|
* Conversion rules:
|
|
26
|
-
* -
|
|
26
|
+
* - Finite numbers return numbers.
|
|
27
27
|
* - Strings are parsed as numbers.
|
|
28
|
-
* - Dates return their milliseconds (e.g. `date.getTime()`)
|
|
29
|
-
* - Everything else returns `
|
|
28
|
+
* - Dates return their milliseconds (e.g. `date.getTime()`).
|
|
29
|
+
* - Everything else returns `undefined`
|
|
30
30
|
*/
|
|
31
|
-
export declare function getOptionalNumber(value: unknown): number |
|
|
31
|
+
export declare function getOptionalNumber(value: unknown): number | undefined;
|
|
32
32
|
/**
|
|
33
33
|
* Assertively convert an unknown value to a finite number.
|
|
34
34
|
* @throws `AssertionError` if the value cannot be converted.
|
package/util/number.js
CHANGED
|
@@ -36,23 +36,22 @@ export function assertMin(value, min) {
|
|
|
36
36
|
throw new AssertionError(`Must be number with minimum ${min}`, value);
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* Convert an unknown value to a finite number or `
|
|
40
|
-
* - Note: numbers can be non-finite numbers like `NaN` or `Infinity`. These are detected and will always return `
|
|
39
|
+
* Convert an unknown value to a finite number or `undefined`
|
|
40
|
+
* - Note: numbers can be non-finite numbers like `NaN` or `Infinity`. These are detected and will always return `undefined`
|
|
41
41
|
*
|
|
42
42
|
* Conversion rules:
|
|
43
|
-
* -
|
|
43
|
+
* - Finite numbers return numbers.
|
|
44
44
|
* - Strings are parsed as numbers.
|
|
45
|
-
* - Dates return their milliseconds (e.g. `date.getTime()`)
|
|
46
|
-
* - Everything else returns `
|
|
45
|
+
* - Dates return their milliseconds (e.g. `date.getTime()`).
|
|
46
|
+
* - Everything else returns `undefined`
|
|
47
47
|
*/
|
|
48
48
|
export function getOptionalNumber(value) {
|
|
49
|
-
if (typeof value === "number")
|
|
50
|
-
return
|
|
49
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
50
|
+
return value === 0 ? 0 : value; // Convert `-0` to `0`
|
|
51
51
|
else if (typeof value === "string")
|
|
52
52
|
return getOptionalNumber(parseFloat(value.replace(NOT_NUMERIC_REGEXP, "")));
|
|
53
53
|
else if (value instanceof Date)
|
|
54
54
|
return getOptionalNumber(value.getTime());
|
|
55
|
-
return null;
|
|
56
55
|
}
|
|
57
56
|
const NOT_NUMERIC_REGEXP = /[^0-9-.]/g;
|
|
58
57
|
/**
|
package/util/path.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export type AbsolutePath = `/` | `/${string}`;
|
|
3
3
|
/** Relative path starts with `./` or `../` */
|
|
4
4
|
export type RelativePath = `.` | `./${string}` | `..` | `../${string}`;
|
|
5
|
+
/** Absolute path or relative path. */
|
|
6
|
+
export type Path = AbsolutePath | RelativePath;
|
|
5
7
|
/** Is a string path an absolute path? */
|
|
6
8
|
export declare const isAbsolutePath: (path: string) => path is `/${string}`;
|
|
7
9
|
/** Is a string path an absolute path? */
|
|
@@ -23,7 +25,7 @@ export declare function cleanPath(path: string): string;
|
|
|
23
25
|
* @param base Absolute path or `URL` instance used for resolving relative paths in `path`
|
|
24
26
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
25
27
|
*/
|
|
26
|
-
export declare function getPath(path: string | URL, base?: AbsolutePath | URL): AbsolutePath;
|
|
28
|
+
export declare function getPath(path: string | URL, base?: AbsolutePath | URL | Location): AbsolutePath;
|
|
27
29
|
/** Is a target path active? */
|
|
28
30
|
export declare function isPathActive(target: AbsolutePath, current: AbsolutePath): boolean;
|
|
29
31
|
/** Is a target path proud (i.e. is the current path, or is a child of the current path)? */
|
package/util/path.js
CHANGED
|
@@ -17,14 +17,15 @@ export function cleanPath(path) {
|
|
|
17
17
|
* @param base Absolute path or `URL` instance used for resolving relative paths in `path`
|
|
18
18
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
19
19
|
*/
|
|
20
|
-
export function getPath(path, base =
|
|
20
|
+
export function getPath(path, base = _LOCATION) {
|
|
21
21
|
try {
|
|
22
|
-
return cleanPath(new URL(path, `http://j.com${base
|
|
22
|
+
return cleanPath(new URL(path, `http://j.com${typeof base === "string" ? base : base.pathname}/`).pathname);
|
|
23
23
|
}
|
|
24
24
|
catch {
|
|
25
25
|
throw new AssertionError("Invalid path", path);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
const _LOCATION = typeof window === "object" ? window.location : "/";
|
|
28
29
|
/** Is a target path active? */
|
|
29
30
|
export function isPathActive(target, current) {
|
|
30
31
|
return target === current;
|
package/util/string.d.ts
CHANGED
|
@@ -67,12 +67,12 @@ export declare const sanitizeLines: (str: string) => string;
|
|
|
67
67
|
* @todo Convert letter-like characters (e.g. `ℝ`) to their ASCII equivalent (e.g. `R`).
|
|
68
68
|
*/
|
|
69
69
|
export declare const simplifyString: (str: string) => string;
|
|
70
|
-
/** Convert a string to a `kebab-case` URL slug, or
|
|
71
|
-
export declare const getOptionalSlug: (str: string) => string |
|
|
70
|
+
/** Convert a string to a `kebab-case` URL slug, or return `undefined` if conversion resulted in an empty ref. */
|
|
71
|
+
export declare const getOptionalSlug: (str: string) => string | undefined;
|
|
72
72
|
export declare function getSlug(str: string): string;
|
|
73
|
-
/** Convert a string to a unique ref e.g. `abc123`, or `
|
|
74
|
-
export declare const getOptionalRef: (str: string) => string |
|
|
75
|
-
/** Convert a string to a unique ref e.g. `abc123`, or throw `AssertionError` */
|
|
73
|
+
/** Convert a string to a unique ref e.g. `abc123`, or return `undefined` if conversion resulted in an empty ref. */
|
|
74
|
+
export declare const getOptionalRef: (str: string) => string | undefined;
|
|
75
|
+
/** Convert a string to a unique ref e.g. `abc123`, or throw `AssertionError` if conversion resulted in an empty ref. */
|
|
76
76
|
export declare function getRef(str: string): string;
|
|
77
77
|
/**
|
|
78
78
|
* Return an array of the separate words and "quoted phrases" found in a string.
|
package/util/string.js
CHANGED
|
@@ -108,23 +108,23 @@ export const simplifyString = (str) => str
|
|
|
108
108
|
.replace(/[^\p{L}\p{N} ]+/gu, "") // Strip characters that aren't letters, numbers, spaces.
|
|
109
109
|
.trim()
|
|
110
110
|
.toLowerCase();
|
|
111
|
-
/** Convert a string to a `kebab-case` URL slug, or
|
|
112
|
-
export const getOptionalSlug = (str) => simplifyString(str).replace(/ /g, "-") ||
|
|
113
|
-
/* Convert a string to a `kebab-case` URL slug, or throw `AssertionError` */
|
|
111
|
+
/** Convert a string to a `kebab-case` URL slug, or return `undefined` if conversion resulted in an empty ref. */
|
|
112
|
+
export const getOptionalSlug = (str) => simplifyString(str).replace(/ /g, "-") || undefined;
|
|
113
|
+
/* Convert a string to a `kebab-case` URL slug, or throw `AssertionError` if conversion resulted in an empty ref. */
|
|
114
114
|
export function getSlug(str) {
|
|
115
115
|
const slug = getOptionalSlug(str);
|
|
116
116
|
if (slug)
|
|
117
117
|
return slug;
|
|
118
|
-
throw new AssertionError(
|
|
118
|
+
throw new AssertionError("Invalid slug", str);
|
|
119
119
|
}
|
|
120
|
-
/** Convert a string to a unique ref e.g. `abc123`, or `
|
|
121
|
-
export const getOptionalRef = (str) => simplifyString(str).replace(/ /g, "") ||
|
|
122
|
-
/** Convert a string to a unique ref e.g. `abc123`, or throw `AssertionError` */
|
|
120
|
+
/** Convert a string to a unique ref e.g. `abc123`, or return `undefined` if conversion resulted in an empty ref. */
|
|
121
|
+
export const getOptionalRef = (str) => simplifyString(str).replace(/ /g, "") || undefined;
|
|
122
|
+
/** Convert a string to a unique ref e.g. `abc123`, or throw `AssertionError` if conversion resulted in an empty ref. */
|
|
123
123
|
export function getRef(str) {
|
|
124
124
|
const ref = getOptionalRef(str);
|
|
125
125
|
if (ref)
|
|
126
126
|
return ref;
|
|
127
|
-
throw new AssertionError(
|
|
127
|
+
throw new AssertionError("Invalid string ref", str);
|
|
128
128
|
}
|
|
129
129
|
/**
|
|
130
130
|
* Return an array of the separate words and "quoted phrases" found in a string.
|
package/util/time.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/** Class representing a time in the day in 24 hour format in the user's current locale. */
|
|
2
2
|
export declare class Time {
|
|
3
|
-
/** Make a new `Time` instance from a date (or any value that can be converted to a date). */
|
|
4
|
-
static fromDate(possible?: unknown): Time | null;
|
|
5
3
|
/** Make a new `Time` instance from a time string. */
|
|
6
|
-
static
|
|
4
|
+
static from(possible?: unknown): Time | undefined;
|
|
7
5
|
readonly time: number;
|
|
8
6
|
constructor(time: number);
|
|
9
7
|
/** Get the number of hours in this time. */
|
|
@@ -34,16 +32,14 @@ export declare class Time {
|
|
|
34
32
|
export declare const TIME_REGEXP: RegExp;
|
|
35
33
|
/** Things that converted to times. */
|
|
36
34
|
export type PossibleTime = Time | Date | number | string;
|
|
37
|
-
/** Things that converted to times or `null` */
|
|
38
|
-
export type PossibleOptionalTime = Time | Date | number | string | null;
|
|
39
35
|
/** Is an unknown value a `Time` instance. */
|
|
40
36
|
export declare const isTime: (value: unknown) => value is Time;
|
|
41
37
|
/**
|
|
42
|
-
* Convert a value to a `Time` instance or `
|
|
38
|
+
* Convert a value to a `Time` instance or `undefined`
|
|
43
39
|
* - Works with possible dates, e.g. `now` or `Date` or `2022-09-12 18:32` or `19827263567`
|
|
44
40
|
* - Works with time strings, e.g. `18:32` or `23:59:59.999`
|
|
45
41
|
*/
|
|
46
|
-
export declare function getOptionalTime(possible: unknown): Time |
|
|
42
|
+
export declare function getOptionalTime(possible: unknown): Time | undefined;
|
|
47
43
|
/** Convert a possible time to a `Time` instance, or throw `AssertionError` if it couldn't be converted. */
|
|
48
44
|
export declare function getTime(possible?: PossibleTime): Time;
|
|
49
45
|
/** Get the time as in `hh:mm` format (hours, minutes), e.g. `13.59` */
|
|
@@ -55,4 +51,4 @@ export declare const getLongTime: (time?: PossibleTime) => string;
|
|
|
55
51
|
/** Format a time as a string based on the browser locale settings. */
|
|
56
52
|
export declare const formatTime: (time?: PossibleTime, precision?: 2 | 3 | 4 | 5 | 6) => string;
|
|
57
53
|
/** Format an optional time as a string based on the browser locale settings. */
|
|
58
|
-
export declare const formatOptionalTime: (time?: unknown, precision?: 2 | 3 | 4 | 5 | 6) => string |
|
|
54
|
+
export declare const formatOptionalTime: (time?: unknown, precision?: 2 | 3 | 4 | 5 | 6) => string | undefined;
|
package/util/time.js
CHANGED
|
@@ -4,18 +4,22 @@ import { getOptionalDate } from "./date.js";
|
|
|
4
4
|
import { wrapNumber } from "./number.js";
|
|
5
5
|
/** Class representing a time in the day in 24 hour format in the user's current locale. */
|
|
6
6
|
export class Time {
|
|
7
|
-
/** Make a new `Time` instance from a date (or any value that can be converted to a date). */
|
|
8
|
-
static fromDate(possible) {
|
|
9
|
-
const date = getOptionalDate(possible);
|
|
10
|
-
return date ? new Time(date.getHours() * HOUR + date.getMinutes() * MINUTE + date.getSeconds() * SECOND + date.getMilliseconds()) : null;
|
|
11
|
-
}
|
|
12
7
|
/** Make a new `Time` instance from a time string. */
|
|
13
|
-
static
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
static from(possible = "now") {
|
|
9
|
+
if (possible === null)
|
|
10
|
+
return undefined;
|
|
11
|
+
if (isTime(possible))
|
|
12
|
+
return possible;
|
|
13
|
+
if (typeof possible === "string") {
|
|
14
|
+
const matches = possible.match(TIME_REGEXP);
|
|
15
|
+
if (matches) {
|
|
16
|
+
const [, h, m, s, ms] = matches;
|
|
17
|
+
return new Time(parseInt(h, 10) * HOUR + parseInt(m, 10) * MINUTE + (typeof s === "string" ? parseInt(s, 10) * SECOND : 0) + (typeof ms === "string" ? parseInt(ms, 10) : 0));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const date = getOptionalDate(possible);
|
|
21
|
+
if (date)
|
|
22
|
+
return new Time(date.getHours() * HOUR + date.getMinutes() * MINUTE + date.getSeconds() * SECOND + date.getMilliseconds());
|
|
19
23
|
}
|
|
20
24
|
/* Total number of milliseconds in this time (always a number between `0` and `86400000` because higher/lower numbers wrap into the next/previous day). */
|
|
21
25
|
time;
|
|
@@ -53,7 +57,7 @@ export class Time {
|
|
|
53
57
|
/** Get a date corresponding to this time. */
|
|
54
58
|
get date() {
|
|
55
59
|
const date = new Date();
|
|
56
|
-
date.setHours(
|
|
60
|
+
date.setHours(this.h, this.m, this.s, this.ms);
|
|
57
61
|
return date;
|
|
58
62
|
}
|
|
59
63
|
/**
|
|
@@ -83,17 +87,15 @@ export const TIME_REGEXP = /([0-9]+):([0-9]+)(?::([0-9]+)(?:.([0-9]+))?)?/;
|
|
|
83
87
|
/** Is an unknown value a `Time` instance. */
|
|
84
88
|
export const isTime = (value) => value instanceof Time;
|
|
85
89
|
/**
|
|
86
|
-
* Convert a value to a `Time` instance or `
|
|
90
|
+
* Convert a value to a `Time` instance or `undefined`
|
|
87
91
|
* - Works with possible dates, e.g. `now` or `Date` or `2022-09-12 18:32` or `19827263567`
|
|
88
92
|
* - Works with time strings, e.g. `18:32` or `23:59:59.999`
|
|
89
93
|
*/
|
|
90
94
|
export function getOptionalTime(possible) {
|
|
91
|
-
|
|
92
|
-
return possible;
|
|
93
|
-
return (typeof possible === "string" && Time.fromString(possible)) || Time.fromDate(possible) || null;
|
|
95
|
+
return Time.from(possible);
|
|
94
96
|
}
|
|
95
97
|
/** Convert a possible time to a `Time` instance, or throw `AssertionError` if it couldn't be converted. */
|
|
96
|
-
export function getTime(possible
|
|
98
|
+
export function getTime(possible) {
|
|
97
99
|
const time = getOptionalTime(possible);
|
|
98
100
|
if (!time)
|
|
99
101
|
throw new AssertionError(`Must be time`, possible);
|
|
@@ -108,4 +110,4 @@ export const getLongTime = (time) => getTime(time).long;
|
|
|
108
110
|
/** Format a time as a string based on the browser locale settings. */
|
|
109
111
|
export const formatTime = (time, precision = 2) => getTime(time).format(precision);
|
|
110
112
|
/** Format an optional time as a string based on the browser locale settings. */
|
|
111
|
-
export const formatOptionalTime = (time, precision = 2) => getOptionalTime(time)?.format(precision)
|
|
113
|
+
export const formatOptionalTime = (time, precision = 2) => getOptionalTime(time)?.format(precision);
|
package/util/url.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { type Optional } from "./optional.js";
|
|
1
2
|
/** Things that can be converted to a URL instance. */
|
|
2
3
|
export type PossibleURL = string | URL;
|
|
3
|
-
export type PossibleOptionalURL = PossibleURL | null;
|
|
4
4
|
/** Is an unknown value a URL? */
|
|
5
5
|
export declare const isURL: (value: unknown) => value is URL;
|
|
6
6
|
/** Assert that an unknown value is a URL. */
|
|
7
7
|
export declare function assertURL(value: unknown): asserts value is URL;
|
|
8
8
|
/** Convert a possible URL to a URL or return `null` if conversion fails. */
|
|
9
|
-
export declare function getOptionalURL(url:
|
|
9
|
+
export declare function getOptionalURL(url: Optional<PossibleURL>, base?: PossibleURL | Location | undefined): URL | undefined;
|
|
10
10
|
/** Convert a possible URL to a URL but throw `AssertionError` if conversion fails. */
|
|
11
|
-
export declare function getURL(possibleURL: PossibleURL, base?:
|
|
11
|
+
export declare function getURL(possibleURL: PossibleURL, base?: PossibleURL): URL;
|
|
12
12
|
/** Just get important part of a URL, e.g. `http://shax.com/test?uid=129483` → `shax.com/test` */
|
|
13
|
-
export declare function formatURL(possibleURL: PossibleURL, base?:
|
|
13
|
+
export declare function formatURL(possibleURL: PossibleURL, base?: PossibleURL): string;
|
package/util/url.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AssertionError } from "../error/AssertionError.js";
|
|
2
|
+
import { notOptional } from "./optional.js";
|
|
2
3
|
/** Is an unknown value a URL? */
|
|
3
4
|
export const isURL = (value) => value instanceof URL;
|
|
4
5
|
/** Assert that an unknown value is a URL. */
|
|
@@ -7,18 +8,19 @@ export function assertURL(value) {
|
|
|
7
8
|
throw new AssertionError("Invalid URL", value);
|
|
8
9
|
}
|
|
9
10
|
/** Convert a possible URL to a URL or return `null` if conversion fails. */
|
|
10
|
-
export function getOptionalURL(url, base =
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
export function getOptionalURL(url, base = _LOCATION) {
|
|
12
|
+
if (notOptional(url)) {
|
|
13
|
+
if (isURL(url))
|
|
14
|
+
return url;
|
|
15
|
+
try {
|
|
16
|
+
return new URL(url, base); // DH: We know `Location` works in URL constructor.
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
//
|
|
20
|
+
}
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
const _LOCATION = typeof window === "object" ? window.location : undefined;
|
|
22
24
|
/** Convert a possible URL to a URL but throw `AssertionError` if conversion fails. */
|
|
23
25
|
export function getURL(possibleURL, base) {
|
|
24
26
|
const url = getOptionalURL(possibleURL, base);
|