@hardlydifficult/text 1.0.0 → 1.0.2
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/README.md +24 -0
- package/dist/formatDuration.d.ts +14 -0
- package/dist/formatDuration.d.ts.map +1 -0
- package/dist/formatDuration.js +44 -0
- package/dist/formatDuration.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/slugify.d.ts +15 -0
- package/dist/slugify.d.ts.map +1 -0
- package/dist/slugify.js +35 -0
- package/dist/slugify.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,3 +75,27 @@ for (const chunk of chunks) {
|
|
|
75
75
|
await channel.send(chunk);
|
|
76
76
|
}
|
|
77
77
|
```
|
|
78
|
+
|
|
79
|
+
### `slugify(input: string, maxLength?: number): string`
|
|
80
|
+
|
|
81
|
+
Convert a string to a URL/filename-safe slug. Lowercases, replaces non-alphanumeric runs with hyphens, truncates at word boundaries.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { slugify } from "@hardlydifficult/text";
|
|
85
|
+
|
|
86
|
+
slugify("My Feature Name!"); // "my-feature-name"
|
|
87
|
+
slugify("My Feature Name!", 10); // "my-feature"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### `formatDuration(ms: number): string`
|
|
91
|
+
|
|
92
|
+
Format milliseconds as a short human-readable duration. Shows at most two units, skipping trailing zeros.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { formatDuration } from "@hardlydifficult/text";
|
|
96
|
+
|
|
97
|
+
formatDuration(125_000); // "2m 5s"
|
|
98
|
+
formatDuration(3_600_000); // "1h"
|
|
99
|
+
formatDuration(500); // "<1s"
|
|
100
|
+
formatDuration(90_000_000); // "1d 1h"
|
|
101
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a duration in milliseconds as a short human-readable string.
|
|
3
|
+
*
|
|
4
|
+
* Shows at most two units (biggest first), skipping trailing zeros.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* formatDuration(125_000) // "2m 5s"
|
|
9
|
+
* formatDuration(3_600_000) // "1h"
|
|
10
|
+
* formatDuration(500) // "<1s"
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatDuration(ms: number): string;
|
|
14
|
+
//# sourceMappingURL=formatDuration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDuration.d.ts","sourceRoot":"","sources":["../src/formatDuration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CA6BjD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDuration = formatDuration;
|
|
4
|
+
/**
|
|
5
|
+
* Format a duration in milliseconds as a short human-readable string.
|
|
6
|
+
*
|
|
7
|
+
* Shows at most two units (biggest first), skipping trailing zeros.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* formatDuration(125_000) // "2m 5s"
|
|
12
|
+
* formatDuration(3_600_000) // "1h"
|
|
13
|
+
* formatDuration(500) // "<1s"
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
function formatDuration(ms) {
|
|
17
|
+
if (ms < 1000) {
|
|
18
|
+
return "<1s";
|
|
19
|
+
}
|
|
20
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
21
|
+
const seconds = totalSeconds % 60;
|
|
22
|
+
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
23
|
+
const minutes = totalMinutes % 60;
|
|
24
|
+
const totalHours = Math.floor(totalMinutes / 60);
|
|
25
|
+
const hours = totalHours % 24;
|
|
26
|
+
const days = Math.floor(totalHours / 24);
|
|
27
|
+
if (days > 0) {
|
|
28
|
+
return hours > 0
|
|
29
|
+
? `${String(days)}d ${String(hours)}h`
|
|
30
|
+
: `${String(days)}d`;
|
|
31
|
+
}
|
|
32
|
+
if (totalHours > 0) {
|
|
33
|
+
return minutes > 0
|
|
34
|
+
? `${String(hours)}h ${String(minutes)}m`
|
|
35
|
+
: `${String(hours)}h`;
|
|
36
|
+
}
|
|
37
|
+
if (totalMinutes > 0) {
|
|
38
|
+
return seconds > 0
|
|
39
|
+
? `${String(minutes)}m ${String(seconds)}s`
|
|
40
|
+
: `${String(minutes)}m`;
|
|
41
|
+
}
|
|
42
|
+
return `${String(seconds)}s`;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=formatDuration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDuration.js","sourceRoot":"","sources":["../src/formatDuration.ts"],"names":[],"mappings":";;AAYA,wCA6BC;AAzCD;;;;;;;;;;;GAWG;AACH,SAAgB,cAAc,CAAC,EAAU;IACvC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,UAAU,GAAG,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;IAEzC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,OAAO,KAAK,GAAG,CAAC;YACd,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG;YACtC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IACzB,CAAC;IACD,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,OAAO,GAAG,CAAC;YAChB,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG;YACzC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;IAC1B,CAAC;IACD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,OAAO,GAAG,CAAC;YAChB,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG;YAC3C,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;AAC/B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { getErrorMessage, formatError, formatErrorForLog } from "./errors.js";
|
|
2
2
|
export { replaceTemplate, extractPlaceholders } from "./template.js";
|
|
3
3
|
export { chunkText } from "./chunkText.js";
|
|
4
|
+
export { slugify } from "./slugify.js";
|
|
5
|
+
export { formatDuration } from "./formatDuration.js";
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.chunkText = exports.extractPlaceholders = exports.replaceTemplate = exports.formatErrorForLog = exports.formatError = exports.getErrorMessage = void 0;
|
|
3
|
+
exports.formatDuration = exports.slugify = exports.chunkText = exports.extractPlaceholders = exports.replaceTemplate = exports.formatErrorForLog = exports.formatError = exports.getErrorMessage = void 0;
|
|
4
4
|
var errors_js_1 = require("./errors.js");
|
|
5
5
|
Object.defineProperty(exports, "getErrorMessage", { enumerable: true, get: function () { return errors_js_1.getErrorMessage; } });
|
|
6
6
|
Object.defineProperty(exports, "formatError", { enumerable: true, get: function () { return errors_js_1.formatError; } });
|
|
@@ -10,4 +10,8 @@ Object.defineProperty(exports, "replaceTemplate", { enumerable: true, get: funct
|
|
|
10
10
|
Object.defineProperty(exports, "extractPlaceholders", { enumerable: true, get: function () { return template_js_1.extractPlaceholders; } });
|
|
11
11
|
var chunkText_js_1 = require("./chunkText.js");
|
|
12
12
|
Object.defineProperty(exports, "chunkText", { enumerable: true, get: function () { return chunkText_js_1.chunkText; } });
|
|
13
|
+
var slugify_js_1 = require("./slugify.js");
|
|
14
|
+
Object.defineProperty(exports, "slugify", { enumerable: true, get: function () { return slugify_js_1.slugify; } });
|
|
15
|
+
var formatDuration_js_1 = require("./formatDuration.js");
|
|
16
|
+
Object.defineProperty(exports, "formatDuration", { enumerable: true, get: function () { return formatDuration_js_1.formatDuration; } });
|
|
13
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA8E;AAArE,4GAAA,eAAe,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AACxD,6CAAqE;AAA5D,8GAAA,eAAe,OAAA;AAAE,kHAAA,mBAAmB,OAAA;AAC7C,+CAA2C;AAAlC,yGAAA,SAAS,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA8E;AAArE,4GAAA,eAAe,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AACxD,6CAAqE;AAA5D,8GAAA,eAAe,OAAA;AAAE,kHAAA,mBAAmB,OAAA;AAC7C,+CAA2C;AAAlC,yGAAA,SAAS,OAAA;AAClB,2CAAuC;AAA9B,qGAAA,OAAO,OAAA;AAChB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a string to a URL/filename-safe slug.
|
|
3
|
+
*
|
|
4
|
+
* Lowercases, replaces non-alphanumeric runs with single hyphens,
|
|
5
|
+
* and trims leading/trailing hyphens. When `maxLength` is provided,
|
|
6
|
+
* truncates at a hyphen boundary to avoid cutting mid-word.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* slugify("My Feature Name!") // "my-feature-name"
|
|
11
|
+
* slugify("My Feature Name!", 10) // "my-feature"
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function slugify(input: string, maxLength?: number): string;
|
|
15
|
+
//# sourceMappingURL=slugify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slugify.d.ts","sourceRoot":"","sources":["../src/slugify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAqBjE"}
|
package/dist/slugify.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.slugify = slugify;
|
|
4
|
+
/**
|
|
5
|
+
* Convert a string to a URL/filename-safe slug.
|
|
6
|
+
*
|
|
7
|
+
* Lowercases, replaces non-alphanumeric runs with single hyphens,
|
|
8
|
+
* and trims leading/trailing hyphens. When `maxLength` is provided,
|
|
9
|
+
* truncates at a hyphen boundary to avoid cutting mid-word.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* slugify("My Feature Name!") // "my-feature-name"
|
|
14
|
+
* slugify("My Feature Name!", 10) // "my-feature"
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
function slugify(input, maxLength) {
|
|
18
|
+
let slug = input
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
21
|
+
.replace(/^-+|-+$/g, "");
|
|
22
|
+
if (maxLength !== undefined && slug.length > maxLength) {
|
|
23
|
+
const cutAtBoundary = slug[maxLength] === "-";
|
|
24
|
+
slug = slug.slice(0, maxLength);
|
|
25
|
+
if (!cutAtBoundary) {
|
|
26
|
+
const lastHyphen = slug.lastIndexOf("-");
|
|
27
|
+
if (lastHyphen > 0) {
|
|
28
|
+
slug = slug.slice(0, lastHyphen);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
slug = slug.replace(/-+$/, "");
|
|
32
|
+
}
|
|
33
|
+
return slug;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=slugify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slugify.js","sourceRoot":"","sources":["../src/slugify.ts"],"names":[],"mappings":";;AAaA,0BAqBC;AAlCD;;;;;;;;;;;;GAYG;AACH,SAAgB,OAAO,CAAC,KAAa,EAAE,SAAkB;IACvD,IAAI,IAAI,GAAG,KAAK;SACb,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAE3B,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;QAC9C,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAEhC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;gBACnB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|