@alchemy.run/sigil 0.0.0-alpha.3 → 0.0.0-alpha.5
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 +23 -13
- package/THIRD_PARTY_NOTICES.md +70 -23
- package/dist/Text-D5HUf3Fj.d.ts +452 -0
- package/dist/ansi.d.ts +137 -143
- package/dist/ansi.js +87 -2
- package/dist/capabilities.d.ts +5 -0
- package/dist/capabilities.js +3 -0
- package/dist/cell-_ZVhbfl0.js +44 -0
- package/dist/color-CkbalRqK.js +2 -0
- package/dist/color-policy-BMzMwV7Q.d.ts +22 -0
- package/dist/color-policy-SVj1pYTA.js +560 -0
- package/dist/color-profile-DHhQHY55.js +36 -0
- package/dist/color-profile-u0Nhe9Nv.d.ts +97 -0
- package/dist/color.d.ts +21 -0
- package/dist/color.js +3 -0
- package/dist/cursor-position-D2LAkRG0.d.ts +7 -0
- package/dist/detect-Bh4yGP6w.d.ts +186 -0
- package/dist/detect-BuTXtY6e.js +373 -0
- package/dist/{devtools-BhYGjb7h.js → devtools-DbthxoD1.js} +22 -23
- package/dist/env-YVw64yZS.js +9 -0
- package/dist/escapes-CB_6CWOE.d.ts +72 -0
- package/dist/geometry-BxXOzJgo.d.ts +11 -0
- package/dist/index-Bmc2tRPk.d.ts +21 -0
- package/dist/index.d.ts +235 -754
- package/dist/index.js +1362 -3001
- package/dist/osc-CCH7xDoS.js +71 -0
- package/dist/osc-Cn0fw77g.d.ts +23 -0
- package/dist/paint-C19minOS.d.ts +81 -0
- package/dist/query-vaIeGOkH.d.ts +152 -0
- package/dist/router.d.ts +392 -0
- package/dist/router.js +709 -0
- package/dist/sample-Cqw1bjUL.js +445 -0
- package/dist/screen-BOh__-65.js +324 -0
- package/dist/screen-BReKIheE.d.ts +40 -0
- package/dist/screen.d.ts +5 -0
- package/dist/screen.js +5 -0
- package/dist/semantic-text-style-DIMzC7xt.js +91 -0
- package/dist/serialize-BTkAZgw1.js +79 -0
- package/dist/session-BJmzX2NJ.js +664 -0
- package/dist/sgr-BhwaWAJB.js +246 -0
- package/dist/store-CgrG9K4y.d.ts +72 -0
- package/dist/string-width-CijQwpIk.js +69 -0
- package/dist/strip-BvU4toXG.js +6 -0
- package/dist/terminal.d.ts +118 -0
- package/dist/terminal.js +2 -0
- package/dist/tokenize-AjqbvtiT.js +1242 -0
- package/dist/tokenize-Dx1y_l5H.d.ts +57 -0
- package/dist/truncate-D31fhU6i.js +562 -0
- package/dist/use-focus-C2sciZOo.js +1335 -0
- package/package.json +43 -17
- package/src/ansi/chalk.ts +12 -53
- package/src/ansi/cursor.ts +2 -4
- package/src/ansi/east-asian-width.ts +44 -0
- package/src/ansi/escapes.ts +18 -26
- package/src/ansi/graphemes.ts +8 -0
- package/src/ansi/hyperlink.ts +44 -0
- package/src/ansi/index.ts +14 -14
- package/src/ansi/osc.ts +77 -0
- package/src/ansi/sgr.ts +2 -5
- package/src/ansi/slice.ts +1 -1
- package/src/ansi/string-width.ts +91 -206
- package/src/ansi/strip.ts +13 -33
- package/src/ansi/tokenize.ts +96 -169
- package/src/ansi/truncate.ts +5 -3
- package/src/ansi/wrap.ts +13 -14
- package/src/ansi-tokenizer.ts +1 -1
- package/src/capabilities/color-policy.ts +34 -0
- package/src/capabilities/detect.ts +594 -0
- package/src/capabilities/index.ts +37 -0
- package/src/capabilities/query.ts +657 -0
- package/src/capabilities/store.ts +379 -0
- package/src/color/index.ts +3 -0
- package/src/color/paint.ts +169 -0
- package/src/color/palette.ts +48 -0
- package/src/color/sample.ts +323 -0
- package/src/color.ts +1 -0
- package/src/components/AnsiText.tsx +42 -0
- package/src/components/App.tsx +109 -22
- package/src/components/BackgroundContext.ts +2 -3
- package/src/components/Box.tsx +43 -60
- package/src/components/CursorContext.ts +1 -1
- package/src/components/ErrorBoundary.tsx +1 -1
- package/src/components/ErrorOverview.tsx +8 -7
- package/src/components/Hyperlink.tsx +56 -0
- package/src/components/Spacer.tsx +1 -1
- package/src/components/Static.tsx +1 -1
- package/src/components/StderrContext.ts +0 -2
- package/src/components/StdinContext.ts +0 -1
- package/src/components/StdoutContext.ts +1 -3
- package/src/components/TerminalOscContext.ts +25 -0
- package/src/components/Text.tsx +23 -46
- package/src/components/Transform.tsx +2 -2
- package/src/cursor-position.ts +1 -1
- package/src/devtools.ts +84 -24
- package/src/dom.ts +11 -8
- package/src/env.ts +12 -0
- package/src/get-max-width.ts +1 -1
- package/src/global.d.ts +6 -4
- package/src/{boxes.ts → glyphs.ts} +17 -18
- package/src/hooks/use-animation.ts +1 -1
- package/src/hooks/use-app.ts +1 -1
- package/src/hooks/use-box-metrics.ts +1 -1
- package/src/hooks/use-capabilities.ts +73 -0
- package/src/hooks/use-cursor.ts +3 -3
- package/src/hooks/use-focus-manager.ts +1 -1
- package/src/hooks/use-focus.ts +5 -6
- package/src/hooks/use-input.ts +4 -4
- package/src/hooks/use-is-screen-reader-enabled.ts +1 -1
- package/src/hooks/use-paste.ts +2 -2
- package/src/hooks/use-stderr.ts +1 -1
- package/src/hooks/use-stdin.ts +1 -1
- package/src/hooks/use-stdout.ts +1 -1
- package/src/hooks/use-terminal-osc.ts +59 -0
- package/src/hooks/use-window-size.ts +2 -2
- package/src/index.ts +88 -44
- package/src/ink.tsx +620 -745
- package/src/input-parser.ts +1 -1
- package/src/instances.ts +1 -1
- package/src/kitty-keyboard.ts +128 -0
- package/src/measure-element.ts +1 -1
- package/src/measure-text.ts +2 -2
- package/src/{render-node-to-output.ts → paint-tree.ts} +78 -53
- package/src/parse-keypress.ts +4 -5
- package/src/parse-stack-line.ts +0 -1
- package/src/patch-console.ts +44 -0
- package/src/reconciler.ts +36 -62
- package/src/render-background.ts +37 -16
- package/src/render-border.ts +97 -64
- package/src/render-frame.ts +83 -0
- package/src/render-to-string.ts +24 -9
- package/src/render.ts +24 -16
- package/src/router/components.tsx +343 -0
- package/src/router/context.ts +41 -0
- package/src/router/history.ts +194 -0
- package/src/router/hooks.tsx +391 -0
- package/src/router/index.ts +34 -0
- package/src/router/matcher.ts +571 -0
- package/src/sanitize-ansi.ts +1 -1
- package/src/screen/ansi.ts +184 -0
- package/src/screen/canvas.ts +137 -0
- package/src/screen/cell.ts +138 -0
- package/src/screen/color-profile.ts +47 -0
- package/src/screen/geometry.ts +9 -0
- package/src/screen/index.ts +6 -0
- package/src/screen/screen.ts +272 -0
- package/src/screen/serialize.ts +129 -0
- package/src/screen.ts +1 -0
- package/src/semantic-text-style.ts +118 -0
- package/src/signal-exit.ts +4 -5
- package/src/squash-text-nodes.ts +4 -7
- package/src/stream.ts +2 -4
- package/src/structured-text.ts +321 -0
- package/src/styles.ts +16 -17
- package/src/terminal/index.ts +2 -0
- package/src/terminal/inline-presenter.ts +120 -0
- package/src/terminal/input.ts +86 -0
- package/src/terminal/render-scheduler.ts +37 -0
- package/src/terminal/screen-presenter.ts +188 -0
- package/src/terminal/session.ts +407 -0
- package/src/terminal-size.ts +9 -8
- package/src/terminal.ts +1 -0
- package/src/testing/browser.ts +588 -0
- package/src/testing/emulators.ts +205 -0
- package/src/testing/explorer-app/index.html +12 -0
- package/src/testing/explorer-app/main.ts +381 -0
- package/src/testing/explorer-app/style.css +194 -0
- package/src/testing/explorer-app/tsconfig.json +15 -0
- package/src/testing/explorer-app/vite-env.d.ts +1 -0
- package/src/testing/index.ts +26 -0
- package/src/testing/keys.ts +56 -0
- package/src/testing/live.ts +85 -0
- package/src/testing/matchers.ts +70 -0
- package/src/testing/public.ts +94 -0
- package/src/testing/terminal.ts +349 -0
- package/src/testing/vitest.ts +157 -0
- package/src/transform-adapter.ts +14 -0
- package/src/types.ts +1 -6
- package/src/utils.ts +2 -2
- package/src/wrap-text.ts +4 -4
- package/src/yoga/config.ts +2 -2
- package/src/yoga/core/absoluteLayout.ts +15 -15
- package/src/yoga/core/baseline.ts +3 -3
- package/src/yoga/core/cache.ts +4 -4
- package/src/yoga/core/calculateLayout.ts +33 -27
- package/src/yoga/core/config.ts +1 -1
- package/src/yoga/core/flexLine.ts +3 -3
- package/src/yoga/core/helpers.ts +3 -3
- package/src/yoga/core/layoutResults.ts +4 -4
- package/src/yoga/core/node.ts +16 -16
- package/src/yoga/core/pixelGrid.ts +4 -4
- package/src/yoga/core/style.ts +11 -11
- package/src/yoga/core/types.ts +2 -2
- package/src/yoga/index.ts +6 -6
- package/src/yoga/node.ts +8 -8
- package/dist/sgr-CMfEpjSk.d.ts +0 -91
- package/dist/truncate-CBiyyZzw.js +0 -2156
- package/src/ansi/supports-color.ts +0 -213
- package/src/ansi/widest-line.ts +0 -12
- package/src/auto-bind.ts +0 -41
- package/src/colorize.ts +0 -60
- package/src/devtools-window-polyfill.ts +0 -73
- package/src/indent-string.ts +0 -16
- package/src/is-in-ci.ts +0 -7
- package/src/log-update.ts +0 -370
- package/src/output.ts +0 -308
- package/src/renderer.ts +0 -73
- package/src/write-synchronized.ts +0 -9
package/src/components/Box.tsx
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
|
-
import {
|
|
2
|
+
import { useContext, type PropsWithChildren, type Ref } from "react";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { type
|
|
6
|
-
import { type
|
|
7
|
-
import { accessibilityContext } from "./AccessibilityContext.ts";
|
|
8
|
-
import { backgroundContext } from "./BackgroundContext.ts";
|
|
4
|
+
import { accessibilityContext } from "#/components/AccessibilityContext.ts";
|
|
5
|
+
import { type DOMElement } from "#/dom.ts";
|
|
6
|
+
import { type Styles } from "#/styles.ts";
|
|
9
7
|
|
|
10
|
-
export type Props =
|
|
8
|
+
export type Props = Omit<Styles, "textWrap"> & {
|
|
11
9
|
/**
|
|
12
10
|
A label for the element for screen readers.
|
|
13
11
|
*/
|
|
@@ -60,58 +58,43 @@ export type Props = Except<Styles, "textWrap"> & {
|
|
|
60
58
|
/**
|
|
61
59
|
`<Box>` is an essential Ink component to build your layout. It's like `<div style="display: flex">` in the browser.
|
|
62
60
|
*/
|
|
63
|
-
export
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (isScreenReaderEnabled && ariaHidden) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
61
|
+
export function Box({
|
|
62
|
+
children,
|
|
63
|
+
ref,
|
|
64
|
+
backgroundColor,
|
|
65
|
+
"aria-label": ariaLabel,
|
|
66
|
+
"aria-hidden": ariaHidden,
|
|
67
|
+
"aria-role": role,
|
|
68
|
+
"aria-state": ariaState,
|
|
69
|
+
...style
|
|
70
|
+
}: PropsWithChildren<Props> & { readonly ref?: Ref<DOMElement> }) {
|
|
71
|
+
const { isScreenReaderEnabled } = useContext(accessibilityContext);
|
|
72
|
+
const label = ariaLabel ? <ink-text>{ariaLabel}</ink-text> : undefined;
|
|
73
|
+
if (isScreenReaderEnabled && ariaHidden) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
77
|
+
const boxElement = (
|
|
78
|
+
<ink-box
|
|
79
|
+
ref={ref}
|
|
80
|
+
style={{
|
|
81
|
+
flexWrap: "nowrap",
|
|
82
|
+
flexDirection: "row",
|
|
83
|
+
flexGrow: 0,
|
|
84
|
+
flexShrink: 1,
|
|
85
|
+
...style,
|
|
86
|
+
backgroundColor,
|
|
87
|
+
overflowX: style.overflowX ?? style.overflow ?? "visible",
|
|
88
|
+
overflowY: style.overflowY ?? style.overflow ?? "visible",
|
|
89
|
+
}}
|
|
90
|
+
internal_accessibility={{
|
|
91
|
+
role,
|
|
92
|
+
state: ariaState,
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
{isScreenReaderEnabled && label ? label : children}
|
|
96
|
+
</ink-box>
|
|
97
|
+
);
|
|
103
98
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return (
|
|
107
|
-
<backgroundContext.Provider value={backgroundColor}>
|
|
108
|
-
{boxElement}
|
|
109
|
-
</backgroundContext.Provider>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return boxElement;
|
|
114
|
-
},
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
Box.displayName = "Box";
|
|
99
|
+
return boxElement;
|
|
100
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
4
|
import { cwd } from "node:process";
|
|
4
5
|
|
|
5
|
-
import { codeExcerpt, type CodeExcerpt } from "
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { codeExcerpt, type CodeExcerpt } from "#/code-excerpt.ts";
|
|
7
|
+
import { Box } from "#/components/Box.tsx";
|
|
8
|
+
import { Text } from "#/components/Text.tsx";
|
|
9
|
+
import { parseStackLine } from "#/parse-stack-line.ts";
|
|
9
10
|
|
|
10
11
|
// Error's source file is reported as file:///home/user/file.js
|
|
11
12
|
// This function removes the file://[cwd] part
|
|
@@ -25,8 +26,8 @@ export function ErrorOverview({ error }: Props) {
|
|
|
25
26
|
let lineWidth = 0;
|
|
26
27
|
const stackLineCounts = new Map<string, number>();
|
|
27
28
|
|
|
28
|
-
if (filePath && origin?.line &&
|
|
29
|
-
const sourceCode =
|
|
29
|
+
if (filePath && origin?.line && existsSync(filePath)) {
|
|
30
|
+
const sourceCode = readFileSync(filePath, "utf8");
|
|
30
31
|
excerpt = codeExcerpt(sourceCode, origin.line);
|
|
31
32
|
|
|
32
33
|
if (excerpt) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** @jsxImportSource react */
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
import { link } from "#/ansi/escapes.ts";
|
|
5
|
+
import { detectHyperlinkSupport } from "#/capabilities/detect.ts";
|
|
6
|
+
import { Text, type Props as TextProps } from "#/components/Text.tsx";
|
|
7
|
+
import { Transform } from "#/components/Transform.tsx";
|
|
8
|
+
import { useStdout } from "#/hooks/use-stdout.ts";
|
|
9
|
+
|
|
10
|
+
export type Props = Omit<TextProps, "children"> & {
|
|
11
|
+
/**
|
|
12
|
+
The URL the hyperlink points to.
|
|
13
|
+
*/
|
|
14
|
+
readonly url: string;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
When the terminal does not support OSC 8 hyperlinks, append the URL in
|
|
18
|
+
parentheses after the text so it stays reachable. Set to `false` to render
|
|
19
|
+
the text alone.
|
|
20
|
+
|
|
21
|
+
@default true
|
|
22
|
+
*/
|
|
23
|
+
readonly fallback?: boolean;
|
|
24
|
+
|
|
25
|
+
readonly children?: ReactNode;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
A clickable OSC 8 hyperlink — the counterpart to the router's `<Link>`, which
|
|
30
|
+
navigates between screens. On terminals without hyperlink support it falls
|
|
31
|
+
back to `text (url)`.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<Hyperlink url="https://example.com">Documentation</Hyperlink>
|
|
35
|
+
```
|
|
36
|
+
*/
|
|
37
|
+
export function Hyperlink({ url, fallback = true, children, ...textProps }: Props) {
|
|
38
|
+
const { stdout } = useStdout();
|
|
39
|
+
|
|
40
|
+
if (!detectHyperlinkSupport(stdout)) {
|
|
41
|
+
return (
|
|
42
|
+
<Text {...textProps}>
|
|
43
|
+
{children}
|
|
44
|
+
{fallback ? <Text dimColor> ({url})</Text> : null}
|
|
45
|
+
</Text>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// OSC 8 sequences are zero-width, so wrapping after layout is safe. The
|
|
50
|
+
// transform runs per output line, giving every line its own complete pair.
|
|
51
|
+
return (
|
|
52
|
+
<Transform transform={(text) => link(text, url)}>
|
|
53
|
+
<Text {...textProps}>{children}</Text>
|
|
54
|
+
</Transform>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
|
|
3
|
+
import type { ClipboardSelection, TerminalProgressState } from "#/ansi/osc.ts";
|
|
4
|
+
|
|
5
|
+
export type TerminalOsc = {
|
|
6
|
+
readonly publishProgress: (owner: symbol, state: TerminalProgressState, value?: number) => void;
|
|
7
|
+
readonly copyToClipboard: (text: string, selection?: ClipboardSelection) => void;
|
|
8
|
+
readonly publishTitle: (owner: symbol, title?: string) => void;
|
|
9
|
+
readonly setWorkingDirectory: (directory: URL | string) => void;
|
|
10
|
+
readonly notify: (title: string) => void;
|
|
11
|
+
readonly setPointerShape: (shape: string) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const noop = () => {};
|
|
15
|
+
|
|
16
|
+
export const TerminalOscContext = createContext<TerminalOsc>({
|
|
17
|
+
publishProgress: noop,
|
|
18
|
+
copyToClipboard: noop,
|
|
19
|
+
publishTitle: noop,
|
|
20
|
+
setWorkingDirectory: noop,
|
|
21
|
+
notify: noop,
|
|
22
|
+
setPointerShape: noop,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
TerminalOscContext.displayName = "InternalTerminalOscContext";
|
package/src/components/Text.tsx
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
2
|
import { useContext, type ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { backgroundContext } from "./BackgroundContext.ts";
|
|
4
|
+
import type { Paint } from "#/color/paint.ts";
|
|
5
|
+
import { accessibilityContext } from "#/components/AccessibilityContext.ts";
|
|
6
|
+
import { cellAttributes } from "#/screen/cell.ts";
|
|
7
|
+
import { parseSemanticColor } from "#/semantic-text-style.ts";
|
|
8
|
+
import { type Styles } from "#/styles.ts";
|
|
10
9
|
|
|
11
10
|
export type Props = {
|
|
12
11
|
/**
|
|
@@ -22,12 +21,12 @@ export type Props = {
|
|
|
22
21
|
/**
|
|
23
22
|
Change text color. Ink uses Chalk under the hood, so all its functionality is supported.
|
|
24
23
|
*/
|
|
25
|
-
readonly color?:
|
|
24
|
+
readonly color?: Paint;
|
|
26
25
|
|
|
27
26
|
/**
|
|
28
27
|
Same as `color`, but for the background.
|
|
29
28
|
*/
|
|
30
|
-
readonly backgroundColor?:
|
|
29
|
+
readonly backgroundColor?: Paint;
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
Dim the color (make it less bright).
|
|
@@ -85,49 +84,27 @@ export function Text({
|
|
|
85
84
|
"aria-hidden": ariaHidden = false,
|
|
86
85
|
}: Props) {
|
|
87
86
|
const { isScreenReaderEnabled } = useContext(accessibilityContext);
|
|
88
|
-
const inheritedBackgroundColor = useContext(backgroundContext);
|
|
89
87
|
const childrenOrAriaLabel = isScreenReaderEnabled && ariaLabel ? ariaLabel : children;
|
|
90
88
|
|
|
91
89
|
if (childrenOrAriaLabel === undefined || childrenOrAriaLabel === null) {
|
|
92
90
|
return null;
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (bold) {
|
|
111
|
-
text = chalk.bold(text);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (italic) {
|
|
115
|
-
text = chalk.italic(text);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (underline) {
|
|
119
|
-
text = chalk.underline(text);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (strikethrough) {
|
|
123
|
-
text = chalk.strikethrough(text);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (inverse) {
|
|
127
|
-
text = chalk.inverse(text);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return text;
|
|
93
|
+
const foreground = typeof color === "object" ? color : parseSemanticColor(color);
|
|
94
|
+
const background =
|
|
95
|
+
typeof backgroundColor === "object" ? backgroundColor : parseSemanticColor(backgroundColor);
|
|
96
|
+
const semanticStyle = {
|
|
97
|
+
...(foreground ? { foreground } : {}),
|
|
98
|
+
...(background ? { background } : {}),
|
|
99
|
+
...(color === "" ? { resetForeground: true } : {}),
|
|
100
|
+
...(backgroundColor === "" ? { resetBackground: true } : {}),
|
|
101
|
+
...(underline ? { underline: "single" as const } : {}),
|
|
102
|
+
attributes:
|
|
103
|
+
(dimColor ? cellAttributes.faint : 0) +
|
|
104
|
+
(bold ? cellAttributes.bold : 0) +
|
|
105
|
+
(italic ? cellAttributes.italic : 0) +
|
|
106
|
+
(strikethrough ? cellAttributes.strikethrough : 0) +
|
|
107
|
+
(inverse ? cellAttributes.inverse : 0),
|
|
131
108
|
};
|
|
132
109
|
|
|
133
110
|
if (isScreenReaderEnabled && ariaHidden) {
|
|
@@ -137,7 +114,7 @@ export function Text({
|
|
|
137
114
|
return (
|
|
138
115
|
<ink-text
|
|
139
116
|
style={{ flexGrow: 0, flexShrink: 1, flexDirection: "row", textWrap: wrap }}
|
|
140
|
-
|
|
117
|
+
internal_textStyle={semanticStyle}
|
|
141
118
|
>
|
|
142
119
|
{childrenOrAriaLabel}
|
|
143
120
|
</ink-text>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
2
|
import { useContext, type ReactNode } from "react";
|
|
3
3
|
|
|
4
|
-
import { accessibilityContext } from "
|
|
4
|
+
import { accessibilityContext } from "#/components/AccessibilityContext.ts";
|
|
5
5
|
|
|
6
6
|
export type Props = {
|
|
7
7
|
/**
|
|
@@ -10,7 +10,7 @@ export type Props = {
|
|
|
10
10
|
readonly accessibilityLabel?: string;
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
|
|
13
|
+
Compatibility function that transforms the ANSI serialization of this subtree.
|
|
14
14
|
*/
|
|
15
15
|
readonly transform: (children: string, index: number) => string;
|
|
16
16
|
|
package/src/cursor-position.ts
CHANGED
package/src/devtools.ts
CHANGED
|
@@ -1,41 +1,101 @@
|
|
|
1
|
-
|
|
1
|
+
import { setTimeout } from "node:timers";
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
// Node 22.4+ ships a stable browser-compatible WebSocket client, so no `ws`
|
|
4
|
+
// dependency is needed. react-devtools-core resolves the constructor via the
|
|
5
|
+
// `window`/`ws` globals defined here.
|
|
6
|
+
Object.defineProperties(globalThis, {
|
|
7
|
+
ws: { value: WebSocket },
|
|
8
|
+
window: { value: globalThis },
|
|
9
|
+
self: { value: globalThis },
|
|
10
|
+
});
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
// Filter out Ink's internal components from devtools for a cleaner view.
|
|
13
|
+
// Also, since `react-devtools-shared` package isn't published on npm, we can't
|
|
14
|
+
// use its types, that's why there are hard-coded values in `type` fields below.
|
|
15
|
+
// See https://github.com/facebook/react/blob/edf6eac8a181860fd8a2d076a43806f1237495a1/packages/react-devtools-shared/src/types.js#L24
|
|
16
|
+
Object.defineProperty(globalThis, "__REACT_DEVTOOLS_COMPONENT_FILTERS__", {
|
|
17
|
+
value: [
|
|
18
|
+
{
|
|
19
|
+
// ComponentFilterElementType
|
|
20
|
+
type: 1,
|
|
21
|
+
// ElementTypeHostComponent
|
|
22
|
+
value: 7,
|
|
23
|
+
isEnabled: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
// ComponentFilterDisplayName
|
|
27
|
+
type: 2,
|
|
28
|
+
value: "InternalApp",
|
|
29
|
+
isEnabled: true,
|
|
30
|
+
isValid: true,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
// ComponentFilterDisplayName
|
|
34
|
+
type: 2,
|
|
35
|
+
value: "InternalAppContext",
|
|
36
|
+
isEnabled: true,
|
|
37
|
+
isValid: true,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
// ComponentFilterDisplayName
|
|
41
|
+
type: 2,
|
|
42
|
+
value: "InternalStdoutContext",
|
|
43
|
+
isEnabled: true,
|
|
44
|
+
isValid: true,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
// ComponentFilterDisplayName
|
|
48
|
+
type: 2,
|
|
49
|
+
value: "InternalStderrContext",
|
|
50
|
+
isEnabled: true,
|
|
51
|
+
isValid: true,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
// ComponentFilterDisplayName
|
|
55
|
+
type: 2,
|
|
56
|
+
value: "InternalStdinContext",
|
|
57
|
+
isEnabled: true,
|
|
58
|
+
isValid: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
// ComponentFilterDisplayName
|
|
62
|
+
type: 2,
|
|
63
|
+
value: "InternalFocusContext",
|
|
64
|
+
isEnabled: true,
|
|
65
|
+
isValid: true,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const isDevToolsReachable = () =>
|
|
71
|
+
new Promise<boolean>((resolve) => {
|
|
12
72
|
const socket = new WebSocket("ws://localhost:8097");
|
|
13
73
|
|
|
74
|
+
const settle = (reachable: boolean) => {
|
|
75
|
+
clearTimeout(timeout);
|
|
76
|
+
socket.close();
|
|
77
|
+
resolve(reachable);
|
|
78
|
+
};
|
|
79
|
+
|
|
14
80
|
const timeout = setTimeout(() => {
|
|
15
|
-
|
|
16
|
-
resolve(false);
|
|
81
|
+
settle(false);
|
|
17
82
|
}, 2000);
|
|
18
83
|
// Don't let the timeout keep the process alive on its own
|
|
19
84
|
timeout.unref();
|
|
20
85
|
|
|
21
|
-
socket.
|
|
22
|
-
|
|
23
|
-
socket.terminate();
|
|
24
|
-
resolve(true);
|
|
86
|
+
socket.addEventListener("open", () => {
|
|
87
|
+
settle(true);
|
|
25
88
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
clearTimeout(timeout);
|
|
29
|
-
socket.terminate();
|
|
30
|
-
resolve(false);
|
|
89
|
+
socket.addEventListener("error", () => {
|
|
90
|
+
settle(false);
|
|
31
91
|
});
|
|
32
92
|
});
|
|
33
93
|
|
|
34
94
|
if (await isDevToolsReachable()) {
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
95
|
+
// @ts-expect-error: react-devtools-core is not typed
|
|
96
|
+
const devtools = await import("react-devtools-core");
|
|
97
|
+
devtools.initialize();
|
|
98
|
+
devtools.connectToDevTools();
|
|
39
99
|
} else {
|
|
40
100
|
console.warn(
|
|
41
101
|
"SIGIL_DEV is set to true, but the React DevTools server is not running. Start it with:\n\n$ npx react-devtools\n",
|
package/src/dom.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { measureText } from "
|
|
2
|
-
import {
|
|
3
|
-
import { squashTextNodes } from "
|
|
4
|
-
import { type Styles } from "
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { measureText } from "#/measure-text.ts";
|
|
2
|
+
import type { SemanticTextStyle } from "#/semantic-text-style.ts";
|
|
3
|
+
import { squashTextNodes } from "#/squash-text-nodes.ts";
|
|
4
|
+
import { type Styles } from "#/styles.ts";
|
|
5
|
+
import { type AnsiTransformer } from "#/transform-adapter.ts";
|
|
6
|
+
import { wrapText } from "#/wrap-text.ts";
|
|
7
|
+
import { Yoga, type Node as YogaNode } from "#/yoga/index.ts";
|
|
7
8
|
|
|
8
9
|
type InkNode = {
|
|
9
10
|
parentNode: DOMElement | undefined;
|
|
@@ -24,7 +25,9 @@ export type DOMElement = {
|
|
|
24
25
|
nodeName: ElementNames;
|
|
25
26
|
attributes: Record<string, DOMNodeAttribute>;
|
|
26
27
|
childNodes: DOMNode[];
|
|
27
|
-
|
|
28
|
+
internal_ansi?: boolean;
|
|
29
|
+
internal_transform?: AnsiTransformer;
|
|
30
|
+
internal_textStyle?: SemanticTextStyle;
|
|
28
31
|
|
|
29
32
|
internal_accessibility?: {
|
|
30
33
|
role?:
|
|
@@ -101,7 +104,7 @@ export const createNode = (nodeName: ElementNames): DOMElement => {
|
|
|
101
104
|
};
|
|
102
105
|
|
|
103
106
|
if (nodeName === "ink-text") {
|
|
104
|
-
node.yogaNode?.setMeasureFunc(measureTextNode
|
|
107
|
+
node.yogaNode?.setMeasureFunc((width) => measureTextNode(node, width));
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
return node;
|
package/src/env.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Every modern CI provider sets CI=1 (or CI=true), so any non-empty value
|
|
2
|
+
export const isInCi = Boolean(process.env.CI);
|
|
3
|
+
|
|
4
|
+
export const isSigilDev = process.env.SIGIL_DEV === "true";
|
|
5
|
+
|
|
6
|
+
export const isScreenReader = process.env.SIGIL_SCREEN_READER === "true";
|
|
7
|
+
|
|
8
|
+
export const isWindows = process.platform === "win32";
|
|
9
|
+
|
|
10
|
+
export const isMacos = process.platform === "darwin";
|
|
11
|
+
|
|
12
|
+
export const isTty = (stream: NodeJS.ReadableStream) => "isTTY" in stream && stream.isTTY === true;
|
package/src/get-max-width.ts
CHANGED
package/src/global.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type ReactNode, type Key, type Ref } from "react";
|
|
2
2
|
|
|
3
|
-
import { type DOMElement } from "
|
|
4
|
-
import {
|
|
5
|
-
import { type
|
|
3
|
+
import { type DOMElement } from "#/dom.ts";
|
|
4
|
+
import type { SemanticTextStyle } from "#/semantic-text-style.ts";
|
|
5
|
+
import { type Styles } from "#/styles.ts";
|
|
6
6
|
|
|
7
7
|
declare module "react" {
|
|
8
8
|
namespace JSX {
|
|
@@ -20,7 +20,7 @@ declare namespace Ink {
|
|
|
20
20
|
children?: ReactNode;
|
|
21
21
|
key?: Key;
|
|
22
22
|
ref?: Ref<DOMElement>;
|
|
23
|
-
style?:
|
|
23
|
+
style?: Omit<Styles, "textWrap">;
|
|
24
24
|
internal_accessibility?: DOMElement["internal_accessibility"];
|
|
25
25
|
};
|
|
26
26
|
|
|
@@ -30,7 +30,9 @@ declare namespace Ink {
|
|
|
30
30
|
style?: Styles;
|
|
31
31
|
|
|
32
32
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
33
|
+
internal_ansi?: boolean;
|
|
33
34
|
internal_transform?: (children: string, index: number) => string;
|
|
35
|
+
internal_textStyle?: SemanticTextStyle;
|
|
34
36
|
internal_accessibility?: DOMElement["internal_accessibility"];
|
|
35
37
|
};
|
|
36
38
|
}
|