@forthtilliath/ts-kit 0.4.0 → 0.5.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/README.md +15 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/markdown/index.d.ts +2 -0
- package/dist/markdown/index.d.ts.map +1 -0
- package/dist/markdown/index.js +1 -0
- package/dist/markdown/parseChangelogNotes.d.ts +16 -0
- package/dist/markdown/parseChangelogNotes.d.ts.map +1 -0
- package/dist/markdown/parseChangelogNotes.js +43 -0
- package/dist/version/compareVersions.d.ts +7 -0
- package/dist/version/compareVersions.d.ts.map +1 -0
- package/dist/version/compareVersions.js +17 -0
- package/dist/version/index.d.ts +2 -0
- package/dist/version/index.d.ts.map +1 -0
- package/dist/version/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @forthtilliath/ts-kit
|
|
2
2
|
|
|
3
3
|
Framework-agnostic TypeScript utility functions — arrays, objects, strings,
|
|
4
|
-
async control-flow, dates, numbers, browser file downloads,
|
|
5
|
-
`Array` extensions with better type-narrowing.
|
|
4
|
+
async control-flow, dates, numbers, browser file downloads, changelog/version
|
|
5
|
+
parsing, and a couple of `Array` extensions with better type-narrowing.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -103,6 +103,14 @@ import { chunk } from "@forthtilliath/ts-kit/array/chunk";
|
|
|
103
103
|
- `randomId()` — `crypto.randomUUID()` with fallbacks for older/insecure
|
|
104
104
|
contexts.
|
|
105
105
|
|
|
106
|
+
### `markdown`
|
|
107
|
+
|
|
108
|
+
- `parseChangelogNotes(notes)` — parses a small subset of Markdown
|
|
109
|
+
(`### heading`, `- item`, `**bold**`) commonly found in GitHub release
|
|
110
|
+
notes into a list of typed blocks (`heading` / `item` / `text`, each with
|
|
111
|
+
`bold`-aware segments), ready for a UI layer to render without a full
|
|
112
|
+
Markdown dependency.
|
|
113
|
+
|
|
106
114
|
### `maths`
|
|
107
115
|
|
|
108
116
|
- `sum(numbers)` — sum of an array of numbers.
|
|
@@ -144,6 +152,11 @@ import { chunk } from "@forthtilliath/ts-kit/array/chunk";
|
|
|
144
152
|
- `escapeHtml(text)` — basic HTML entity escaping (`&`, `<`, `>`, `"`) for
|
|
145
153
|
inserting user text into an HTML template.
|
|
146
154
|
|
|
155
|
+
### `version`
|
|
156
|
+
|
|
157
|
+
- `compareVersions(a, b)` — compares two `"x.y.z"` version strings, segment
|
|
158
|
+
by segment; `-1`/`0`/`1`.
|
|
159
|
+
|
|
147
160
|
## Scripts
|
|
148
161
|
|
|
149
162
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,10 @@ export * from "./classes/index.js";
|
|
|
4
4
|
export * from "./date/index.js";
|
|
5
5
|
export * from "./files/index.js";
|
|
6
6
|
export * from "./id/index.js";
|
|
7
|
+
export * from "./markdown/index.js";
|
|
7
8
|
export * from "./maths/index.js";
|
|
8
9
|
export * from "./number/index.js";
|
|
9
10
|
export * from "./object/index.js";
|
|
10
11
|
export * from "./string/index.js";
|
|
12
|
+
export * from "./version/index.js";
|
|
11
13
|
//# 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":"AAKA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,9 @@ export * from "./classes/index.js";
|
|
|
9
9
|
export * from "./date/index.js";
|
|
10
10
|
export * from "./files/index.js";
|
|
11
11
|
export * from "./id/index.js";
|
|
12
|
+
export * from "./markdown/index.js";
|
|
12
13
|
export * from "./maths/index.js";
|
|
13
14
|
export * from "./number/index.js";
|
|
14
15
|
export * from "./object/index.js";
|
|
15
16
|
export * from "./string/index.js";
|
|
17
|
+
export * from "./version/index.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markdown/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./parseChangelogNotes.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ChangelogSegment {
|
|
2
|
+
text: string;
|
|
3
|
+
bold: boolean;
|
|
4
|
+
}
|
|
5
|
+
export type ChangelogBlock = {
|
|
6
|
+
type: "heading";
|
|
7
|
+
text: string;
|
|
8
|
+
} | {
|
|
9
|
+
type: "item";
|
|
10
|
+
segments: ChangelogSegment[];
|
|
11
|
+
} | {
|
|
12
|
+
type: "text";
|
|
13
|
+
segments: ChangelogSegment[];
|
|
14
|
+
};
|
|
15
|
+
export declare function parseChangelogNotes(notes: string): ChangelogBlock[];
|
|
16
|
+
//# sourceMappingURL=parseChangelogNotes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseChangelogNotes.d.ts","sourceRoot":"","sources":["../../src/markdown/parseChangelogNotes.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC;AAsBnD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,EAAE,CAiBnE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// GitHub release notes (and changelogs in general) are usually written in a
|
|
2
|
+
// small subset of Markdown ("### Heading", "- item", "**bold**"). Rendered
|
|
3
|
+
// as-is in a plain UI text node, the raw syntax shows up unstyled — this
|
|
4
|
+
// parser turns it into a small set of typed blocks a UI layer can render
|
|
5
|
+
// (heading / bullet item / plain text), without pulling in a full Markdown
|
|
6
|
+
// dependency for this narrow use case.
|
|
7
|
+
function parseInlineSegments(text) {
|
|
8
|
+
const segments = [];
|
|
9
|
+
const boldPattern = /\*\*(.+?)\*\*/g;
|
|
10
|
+
let lastIndex = 0;
|
|
11
|
+
let match;
|
|
12
|
+
while ((match = boldPattern.exec(text)) !== null) {
|
|
13
|
+
if (match.index > lastIndex) {
|
|
14
|
+
segments.push({ text: text.slice(lastIndex, match.index), bold: false });
|
|
15
|
+
}
|
|
16
|
+
// The capture group is mandatory in the pattern, so it always matches —
|
|
17
|
+
// the `?? ""` fallback is only here to satisfy `noUncheckedIndexedAccess`.
|
|
18
|
+
segments.push({ text: match[1] ?? "", bold: true });
|
|
19
|
+
lastIndex = boldPattern.lastIndex;
|
|
20
|
+
}
|
|
21
|
+
if (lastIndex < text.length) {
|
|
22
|
+
segments.push({ text: text.slice(lastIndex), bold: false });
|
|
23
|
+
}
|
|
24
|
+
return segments;
|
|
25
|
+
}
|
|
26
|
+
export function parseChangelogNotes(notes) {
|
|
27
|
+
return notes
|
|
28
|
+
.split("\n")
|
|
29
|
+
.map((line) => line.trim())
|
|
30
|
+
.filter((line) => line.length > 0)
|
|
31
|
+
.map((line) => {
|
|
32
|
+
if (line.startsWith("### ")) {
|
|
33
|
+
return { type: "heading", text: line.slice(4).trim() };
|
|
34
|
+
}
|
|
35
|
+
if (line.startsWith("- ")) {
|
|
36
|
+
return {
|
|
37
|
+
type: "item",
|
|
38
|
+
segments: parseInlineSegments(line.slice(2).trim()),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return { type: "text", segments: parseInlineSegments(line) };
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compareVersions.d.ts","sourceRoot":"","sources":["../../src/version/compareVersions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU5D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two "x.y.z" version strings, segment by segment.
|
|
3
|
+
*
|
|
4
|
+
* @returns -1 if `a` < `b`, 0 if they're equal, 1 if `a` > `b`.
|
|
5
|
+
*/
|
|
6
|
+
export function compareVersions(a, b) {
|
|
7
|
+
const partsA = a.split(".").map(Number);
|
|
8
|
+
const partsB = b.split(".").map(Number);
|
|
9
|
+
const length = Math.max(partsA.length, partsB.length);
|
|
10
|
+
for (let i = 0; i < length; i++) {
|
|
11
|
+
const numA = partsA[i] ?? 0;
|
|
12
|
+
const numB = partsB[i] ?? 0;
|
|
13
|
+
if (numA !== numB)
|
|
14
|
+
return numA > numB ? 1 : -1;
|
|
15
|
+
}
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/version/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./compareVersions.js";
|