tinky 1.5.0 → 1.7.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.ja-JP.md +40 -0
- package/README.md +39 -0
- package/README.zh-CN.md +38 -0
- package/lib/components/Text.js +10 -3
- package/lib/core/cell-buffer.d.ts +91 -0
- package/lib/core/cell-buffer.js +346 -0
- package/lib/core/cell-log-update-run.d.ts +40 -0
- package/lib/core/cell-log-update-run.js +526 -0
- package/lib/core/cell-output.d.ts +20 -0
- package/lib/core/cell-output.js +231 -0
- package/lib/core/cell-renderer.d.ts +25 -0
- package/lib/core/cell-renderer.js +60 -0
- package/lib/core/incremental-rendering.d.ts +43 -0
- package/lib/core/incremental-rendering.js +22 -0
- package/lib/core/output.d.ts +21 -6
- package/lib/core/output.js +73 -8
- package/lib/core/render-border.d.ts +2 -12
- package/lib/core/render-border.js +78 -69
- package/lib/core/render-node-to-output.d.ts +2 -2
- package/lib/core/render.d.ts +17 -4
- package/lib/core/renderer.js +9 -6
- package/lib/core/tinky.d.ts +27 -3
- package/lib/core/tinky.js +125 -5
- package/lib/index.d.ts +1 -0
- package/lib/types/ansi.d.ts +5 -0
- package/lib/types/ansi.js +1 -0
- package/lib/utils/ansi-escapes.d.ts +2 -0
- package/lib/utils/ansi-escapes.js +2 -0
- package/lib/utils/colorize.d.ts +5 -0
- package/lib/utils/colorize.js +42 -20
- package/lib/utils/render-background.d.ts +2 -2
- package/lib/utils/render-background.js +4 -3
- package/lib/utils/squash-text-nodes.d.ts +5 -0
- package/lib/utils/squash-text-nodes.js +18 -2
- package/package.json +3 -1
package/lib/utils/colorize.js
CHANGED
|
@@ -5,49 +5,71 @@ const isNamedColor = (color) => {
|
|
|
5
5
|
return color in ansis;
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* Supports named colors, hex codes, RGB values, and ANSI-256 color codes.
|
|
10
|
-
*
|
|
11
|
-
* @param str - The string to colorize.
|
|
12
|
-
* @param color - The color to apply.
|
|
13
|
-
* @param type - Whether to apply the color to the foreground or background.
|
|
14
|
-
* @returns The colorized string.
|
|
8
|
+
* Gets the ANSI style for a color.
|
|
15
9
|
*/
|
|
16
|
-
export const
|
|
10
|
+
export const getStyle = (color, type) => {
|
|
17
11
|
if (!color) {
|
|
18
|
-
return
|
|
12
|
+
return undefined;
|
|
19
13
|
}
|
|
20
14
|
if (isNamedColor(color)) {
|
|
21
15
|
if (type === "foreground") {
|
|
22
|
-
return
|
|
16
|
+
return {
|
|
17
|
+
type: "ansi",
|
|
18
|
+
code: ansis[color].open,
|
|
19
|
+
endCode: ansis[color].close,
|
|
20
|
+
};
|
|
23
21
|
}
|
|
24
22
|
const methodName = `bg${color.charAt(0).toUpperCase() + color.slice(1)}`;
|
|
25
|
-
return
|
|
23
|
+
return {
|
|
24
|
+
type: "ansi",
|
|
25
|
+
code: ansis[methodName].open,
|
|
26
|
+
endCode: ansis[methodName].close,
|
|
27
|
+
};
|
|
26
28
|
}
|
|
27
29
|
if (color.startsWith("#")) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
:
|
|
30
|
+
const style = type === "foreground" ? ansis.hex(color) : ansis.bgHex(color);
|
|
31
|
+
return {
|
|
32
|
+
type: "ansi",
|
|
33
|
+
code: style.open,
|
|
34
|
+
endCode: style.close,
|
|
35
|
+
};
|
|
31
36
|
}
|
|
32
37
|
if (color.startsWith("ansi256")) {
|
|
33
38
|
const matches = ansiRegex.exec(color);
|
|
34
39
|
if (!matches) {
|
|
35
|
-
return
|
|
40
|
+
return undefined;
|
|
36
41
|
}
|
|
37
42
|
const value = Number(matches[1]);
|
|
38
|
-
|
|
43
|
+
const style = type === "foreground" ? ansis.fg(value) : ansis.bg(value);
|
|
44
|
+
return {
|
|
45
|
+
type: "ansi",
|
|
46
|
+
code: style.open,
|
|
47
|
+
endCode: style.close,
|
|
48
|
+
};
|
|
39
49
|
}
|
|
40
50
|
if (color.startsWith("rgb")) {
|
|
41
51
|
const matches = rgbRegex.exec(color);
|
|
42
52
|
if (!matches) {
|
|
43
|
-
return
|
|
53
|
+
return undefined;
|
|
44
54
|
}
|
|
45
55
|
const firstValue = Number(matches[1]);
|
|
46
56
|
const secondValue = Number(matches[2]);
|
|
47
57
|
const thirdValue = Number(matches[3]);
|
|
48
|
-
|
|
49
|
-
? ansis.rgb(firstValue, secondValue, thirdValue)
|
|
50
|
-
: ansis.bgRgb(firstValue, secondValue, thirdValue)
|
|
58
|
+
const style = type === "foreground"
|
|
59
|
+
? ansis.rgb(firstValue, secondValue, thirdValue)
|
|
60
|
+
: ansis.bgRgb(firstValue, secondValue, thirdValue);
|
|
61
|
+
return {
|
|
62
|
+
type: "ansi",
|
|
63
|
+
code: style.open,
|
|
64
|
+
endCode: style.close,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
};
|
|
69
|
+
export const colorize = (str, color, type) => {
|
|
70
|
+
const style = getStyle(color, type);
|
|
71
|
+
if (style) {
|
|
72
|
+
return style.code + str + style.endCode;
|
|
51
73
|
}
|
|
52
74
|
return str;
|
|
53
75
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DOMNode } from "../core/dom.js";
|
|
2
|
-
import { type
|
|
2
|
+
import { type OutputLike } from "../core/output.js";
|
|
3
3
|
/**
|
|
4
4
|
* Renders the background color of a node to the output.
|
|
5
5
|
*
|
|
@@ -8,4 +8,4 @@ import { type Output } from "../core/output.js";
|
|
|
8
8
|
* @param node - The DOM node to render the background for.
|
|
9
9
|
* @param output - The output instance to write to.
|
|
10
10
|
*/
|
|
11
|
-
export declare const renderBackground: (x: number, y: number, node: DOMNode, output:
|
|
11
|
+
export declare const renderBackground: (x: number, y: number, node: DOMNode, output: OutputLike) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getStyle } from "./colorize.js";
|
|
2
2
|
/**
|
|
3
3
|
* Renders the background color of a node to the output.
|
|
4
4
|
*
|
|
@@ -25,8 +25,9 @@ export const renderBackground = (x, y, node, output) => {
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
// Create background fill for each row
|
|
28
|
-
const
|
|
28
|
+
const style = getStyle(node.style.backgroundColor, "background");
|
|
29
|
+
const styles = style ? [style] : [];
|
|
29
30
|
for (let row = 0; row < contentHeight; row++) {
|
|
30
|
-
output.
|
|
31
|
+
output.fill(x + leftBorderWidth, y + topBorderHeight + row, contentWidth, " ", 1, styles);
|
|
31
32
|
}
|
|
32
33
|
};
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type DOMElement } from "../core/dom.js";
|
|
2
|
+
/**
|
|
3
|
+
* Advances the squash cache epoch.
|
|
4
|
+
* Cached results are valid only within one layout/render cycle.
|
|
5
|
+
*/
|
|
6
|
+
export declare const advanceSquashTextEpoch: () => number;
|
|
2
7
|
/**
|
|
3
8
|
* Consolidates multiple text nodes into a single string.
|
|
4
9
|
* Useful for combining adjacent text nodes to minimize write operations.
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
const cache = new WeakMap();
|
|
2
|
+
let currentEpoch = 0;
|
|
3
|
+
/**
|
|
4
|
+
* Advances the squash cache epoch.
|
|
5
|
+
* Cached results are valid only within one layout/render cycle.
|
|
6
|
+
*/
|
|
7
|
+
export const advanceSquashTextEpoch = () => {
|
|
8
|
+
currentEpoch += 1;
|
|
9
|
+
return currentEpoch;
|
|
10
|
+
};
|
|
1
11
|
/**
|
|
2
12
|
* Consolidates multiple text nodes into a single string.
|
|
3
13
|
* Useful for combining adjacent text nodes to minimize write operations.
|
|
@@ -7,7 +17,11 @@
|
|
|
7
17
|
* @returns The consolidated text string.
|
|
8
18
|
*/
|
|
9
19
|
export const squashTextNodes = (node) => {
|
|
10
|
-
|
|
20
|
+
const cached = cache.get(node);
|
|
21
|
+
if (cached && cached.epoch === currentEpoch) {
|
|
22
|
+
return cached.text;
|
|
23
|
+
}
|
|
24
|
+
const parts = [];
|
|
11
25
|
for (let index = 0; index < node.childNodes.length; index++) {
|
|
12
26
|
const childNode = node.childNodes[index];
|
|
13
27
|
if (childNode === undefined) {
|
|
@@ -30,7 +44,9 @@ export const squashTextNodes = (node) => {
|
|
|
30
44
|
nodeText = childNode.internal_transform(nodeText, index);
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
|
-
|
|
47
|
+
parts.push(nodeText);
|
|
34
48
|
}
|
|
49
|
+
const text = parts.join("");
|
|
50
|
+
cache.set(node, { epoch: currentEpoch, text });
|
|
35
51
|
return text;
|
|
36
52
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinky",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "React for CLIs, re-imagined with the Taffy engine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
34
|
"test": "bun test",
|
|
35
|
+
"benchmark": "bun run benchmark/index.ts",
|
|
35
36
|
"build": "tsc && npm run docs",
|
|
36
37
|
"lint": "eslint src/**/*.ts",
|
|
37
38
|
"prepublish": "npm run build",
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
"eslint": "^9.39.2",
|
|
83
84
|
"eslint-plugin-react": "^7.37.5",
|
|
84
85
|
"husky": "^9.1.7",
|
|
86
|
+
"ink": "^6.7.0",
|
|
85
87
|
"jiti": "^2.6.1",
|
|
86
88
|
"lint-staged": "^16.2.7",
|
|
87
89
|
"prettier": "^3.7.4",
|