@silvery/term 0.3.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 +54 -0
- package/src/adapters/canvas-adapter.ts +356 -0
- package/src/adapters/dom-adapter.ts +452 -0
- package/src/adapters/flexily-zero-adapter.ts +368 -0
- package/src/adapters/terminal-adapter.ts +305 -0
- package/src/adapters/yoga-adapter.ts +370 -0
- package/src/ansi/ansi.ts +251 -0
- package/src/ansi/constants.ts +76 -0
- package/src/ansi/detection.ts +441 -0
- package/src/ansi/hyperlink.ts +38 -0
- package/src/ansi/index.ts +201 -0
- package/src/ansi/patch-console.ts +159 -0
- package/src/ansi/sgr-codes.ts +34 -0
- package/src/ansi/storybook.ts +209 -0
- package/src/ansi/term.ts +724 -0
- package/src/ansi/types.ts +202 -0
- package/src/ansi/underline.ts +156 -0
- package/src/ansi/utils.ts +65 -0
- package/src/ansi-sanitize.ts +509 -0
- package/src/app.ts +571 -0
- package/src/bound-term.ts +94 -0
- package/src/bracketed-paste.ts +75 -0
- package/src/browser-renderer.ts +174 -0
- package/src/buffer.ts +1984 -0
- package/src/clipboard.ts +74 -0
- package/src/cursor-query.ts +85 -0
- package/src/device-attrs.ts +228 -0
- package/src/devtools.ts +123 -0
- package/src/dom/index.ts +194 -0
- package/src/errors.ts +39 -0
- package/src/focus-reporting.ts +48 -0
- package/src/hit-registry-core.ts +228 -0
- package/src/hit-registry.ts +176 -0
- package/src/index.ts +458 -0
- package/src/input.ts +119 -0
- package/src/inspector.ts +155 -0
- package/src/kitty-detect.ts +95 -0
- package/src/kitty-manager.ts +160 -0
- package/src/layout-engine.ts +296 -0
- package/src/layout.ts +26 -0
- package/src/measurer.ts +74 -0
- package/src/mode-query.ts +106 -0
- package/src/mouse-events.ts +419 -0
- package/src/mouse.ts +83 -0
- package/src/non-tty.ts +223 -0
- package/src/osc-markers.ts +32 -0
- package/src/osc-palette.ts +169 -0
- package/src/output.ts +406 -0
- package/src/pane-manager.ts +248 -0
- package/src/pipeline/CLAUDE.md +587 -0
- package/src/pipeline/content-phase-adapter.ts +976 -0
- package/src/pipeline/content-phase.ts +1765 -0
- package/src/pipeline/helpers.ts +42 -0
- package/src/pipeline/index.ts +416 -0
- package/src/pipeline/layout-phase.ts +686 -0
- package/src/pipeline/measure-phase.ts +198 -0
- package/src/pipeline/measure-stats.ts +21 -0
- package/src/pipeline/output-phase.ts +2593 -0
- package/src/pipeline/render-box.ts +343 -0
- package/src/pipeline/render-helpers.ts +243 -0
- package/src/pipeline/render-text.ts +1255 -0
- package/src/pipeline/types.ts +161 -0
- package/src/pipeline.ts +29 -0
- package/src/pixel-size.ts +119 -0
- package/src/render-adapter.ts +179 -0
- package/src/renderer.ts +1330 -0
- package/src/runtime/create-app.tsx +1845 -0
- package/src/runtime/create-buffer.ts +18 -0
- package/src/runtime/create-runtime.ts +325 -0
- package/src/runtime/diff.ts +56 -0
- package/src/runtime/event-handlers.ts +254 -0
- package/src/runtime/index.ts +119 -0
- package/src/runtime/keys.ts +8 -0
- package/src/runtime/layout.ts +164 -0
- package/src/runtime/run.tsx +318 -0
- package/src/runtime/term-provider.ts +399 -0
- package/src/runtime/terminal-lifecycle.ts +246 -0
- package/src/runtime/tick.ts +219 -0
- package/src/runtime/types.ts +210 -0
- package/src/scheduler.ts +723 -0
- package/src/screenshot.ts +57 -0
- package/src/scroll-region.ts +69 -0
- package/src/scroll-utils.ts +97 -0
- package/src/term-def.ts +267 -0
- package/src/terminal-caps.ts +5 -0
- package/src/terminal-colors.ts +216 -0
- package/src/termtest.ts +224 -0
- package/src/text-sizing.ts +109 -0
- package/src/toolbelt/index.ts +72 -0
- package/src/unicode.ts +1763 -0
- package/src/xterm/index.ts +491 -0
- package/src/xterm/xterm-provider.ts +204 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console patching with subscribable store for useSyncExternalStore.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ConsoleEntry, ConsoleMethod } from "./types"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Aggregate counts of console output by severity.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConsoleStats {
|
|
11
|
+
total: number
|
|
12
|
+
errors: number
|
|
13
|
+
warnings: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A patched console that intercepts methods and accumulates entries.
|
|
18
|
+
* Compatible with React's useSyncExternalStore.
|
|
19
|
+
*/
|
|
20
|
+
export interface PatchedConsole extends Disposable {
|
|
21
|
+
/** Read current entries (for useSyncExternalStore). Empty when capture=false. */
|
|
22
|
+
getSnapshot(): readonly ConsoleEntry[]
|
|
23
|
+
|
|
24
|
+
/** Get aggregate counts (total, errors, warnings). Works in all modes. */
|
|
25
|
+
getStats(): ConsoleStats
|
|
26
|
+
|
|
27
|
+
/** Subscribe to changes - called when new entry arrives. Returns unsubscribe function. */
|
|
28
|
+
subscribe(onStoreChange: () => void): () => void
|
|
29
|
+
|
|
30
|
+
dispose(): void
|
|
31
|
+
[Symbol.dispose](): void
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const METHODS: ConsoleMethod[] = ["log", "info", "warn", "error", "debug"]
|
|
35
|
+
|
|
36
|
+
const STDERR_METHODS = new Set<ConsoleMethod>(["error", "warn"])
|
|
37
|
+
|
|
38
|
+
export interface PatchConsoleOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Suppress original console output when true.
|
|
41
|
+
* Use in TUI mode where you want console output only in a component.
|
|
42
|
+
*/
|
|
43
|
+
suppress?: boolean
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Store full entries in memory (default: true).
|
|
47
|
+
* Set to false for count-only mode — getSnapshot() returns empty array,
|
|
48
|
+
* but getStats() still tracks counts. Avoids unbounded memory growth.
|
|
49
|
+
*/
|
|
50
|
+
capture?: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Patch console methods to intercept and track output.
|
|
55
|
+
* Returns a disposable that restores original methods.
|
|
56
|
+
*
|
|
57
|
+
* @param console - The console object to patch
|
|
58
|
+
* @param options - Configuration options
|
|
59
|
+
* @param options.suppress - If true, don't call original methods (for TUI mode)
|
|
60
|
+
* @param options.capture - If false, only count entries (no memory storage)
|
|
61
|
+
*/
|
|
62
|
+
export function patchConsole(console: Console, options?: PatchConsoleOptions): PatchedConsole {
|
|
63
|
+
const suppress = options?.suppress ?? false
|
|
64
|
+
const capture = options?.capture ?? true
|
|
65
|
+
|
|
66
|
+
// Entry storage (only when capture=true)
|
|
67
|
+
const entries: ConsoleEntry[] = []
|
|
68
|
+
// Snapshot must be a new reference on each change for useSyncExternalStore
|
|
69
|
+
// (React uses Object.is to detect changes — same reference = no re-render)
|
|
70
|
+
let snapshot: readonly ConsoleEntry[] = entries
|
|
71
|
+
const EMPTY: readonly ConsoleEntry[] = Object.freeze([])
|
|
72
|
+
|
|
73
|
+
// Stats (always tracked)
|
|
74
|
+
const stats: ConsoleStats = { total: 0, errors: 0, warnings: 0 }
|
|
75
|
+
|
|
76
|
+
const subscribers = new Set<() => void>()
|
|
77
|
+
|
|
78
|
+
// Save original methods
|
|
79
|
+
const originals = new Map<ConsoleMethod, Console[ConsoleMethod]>()
|
|
80
|
+
for (const method of METHODS) {
|
|
81
|
+
originals.set(method, console[method].bind(console))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Batch subscriber notifications to prevent synchronous feedback loops.
|
|
85
|
+
// Without batching, console.debug() during a React render triggers
|
|
86
|
+
// useSyncExternalStore → re-render → more console output → infinite loop.
|
|
87
|
+
let notifyPending = false
|
|
88
|
+
|
|
89
|
+
function scheduleNotify() {
|
|
90
|
+
if (notifyPending) return
|
|
91
|
+
notifyPending = true
|
|
92
|
+
queueMicrotask(() => {
|
|
93
|
+
notifyPending = false
|
|
94
|
+
subscribers.forEach((subscriber) => subscriber())
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Replace with interceptors
|
|
99
|
+
for (const method of METHODS) {
|
|
100
|
+
const original = originals.get(method)!
|
|
101
|
+
console[method] = (...args: unknown[]) => {
|
|
102
|
+
// Update stats
|
|
103
|
+
stats.total++
|
|
104
|
+
if (method === "error") stats.errors++
|
|
105
|
+
else if (method === "warn") stats.warnings++
|
|
106
|
+
|
|
107
|
+
// Store entry if capturing
|
|
108
|
+
if (capture) {
|
|
109
|
+
const entry: ConsoleEntry = {
|
|
110
|
+
method,
|
|
111
|
+
args,
|
|
112
|
+
stream: STDERR_METHODS.has(method) ? "stderr" : "stdout",
|
|
113
|
+
}
|
|
114
|
+
entries.push(entry)
|
|
115
|
+
snapshot = entries.slice()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Call original unless suppressed (TUI mode)
|
|
119
|
+
if (!suppress) {
|
|
120
|
+
original(...args)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Notify subscribers (batched via microtask)
|
|
124
|
+
scheduleNotify()
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function restore() {
|
|
129
|
+
for (const method of METHODS) {
|
|
130
|
+
console[method] = originals.get(method)!
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
getSnapshot(): readonly ConsoleEntry[] {
|
|
136
|
+
return capture ? snapshot : EMPTY
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
getStats(): ConsoleStats {
|
|
140
|
+
return { ...stats }
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
subscribe(onStoreChange: () => void): () => void {
|
|
144
|
+
subscribers.add(onStoreChange)
|
|
145
|
+
return () => {
|
|
146
|
+
subscribers.delete(onStoreChange)
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
dispose() {
|
|
151
|
+
restore()
|
|
152
|
+
subscribers.clear()
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
[Symbol.dispose]() {
|
|
156
|
+
this.dispose()
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SGR (Select Graphic Rendition) color code helpers.
|
|
3
|
+
*
|
|
4
|
+
* Shared by buffer.ts (styleToAnsiCodes) and output-phase.ts (styleTransition).
|
|
5
|
+
* Emits the shortest possible SGR code string for a given color.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Emit the shortest SGR code string for a foreground color.
|
|
10
|
+
* - Basic 0-7: 4-bit code (30+N)
|
|
11
|
+
* - Extended 8-255: 256-color (38;5;N)
|
|
12
|
+
* - RGB: true color (38;2;R;G;B)
|
|
13
|
+
*/
|
|
14
|
+
export function fgColorCode(color: number | { r: number; g: number; b: number }): string {
|
|
15
|
+
if (typeof color === "number") {
|
|
16
|
+
if (color >= 0 && color <= 7) return `${30 + color}`
|
|
17
|
+
return `38;5;${color}`
|
|
18
|
+
}
|
|
19
|
+
return `38;2;${color.r};${color.g};${color.b}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Emit the shortest SGR code string for a background color.
|
|
24
|
+
* - Basic 0-7: 4-bit code (40+N)
|
|
25
|
+
* - Extended 8-255: 256-color (48;5;N)
|
|
26
|
+
* - RGB: true color (48;2;R;G;B)
|
|
27
|
+
*/
|
|
28
|
+
export function bgColorCode(color: number | { r: number; g: number; b: number }): string {
|
|
29
|
+
if (typeof color === "number") {
|
|
30
|
+
if (color >= 0 && color <= 7) return `${40 + color}`
|
|
31
|
+
return `48;5;${color}`
|
|
32
|
+
}
|
|
33
|
+
return `48;2;${color.r};${color.g};${color.b}`
|
|
34
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* chalk-x Storybook - Visual Feature Catalog
|
|
4
|
+
*
|
|
5
|
+
* Renders all chalk-x features for visual inspection.
|
|
6
|
+
* Run: bun vendor/silvery/packages/ansi/src/storybook.ts
|
|
7
|
+
*
|
|
8
|
+
* NOTE: Extended underline styles only render in modern terminals
|
|
9
|
+
* (Ghostty, Kitty, WezTerm, iTerm2). Other terminals will show
|
|
10
|
+
* regular underlines as fallback.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
createTerm,
|
|
15
|
+
curlyUnderline,
|
|
16
|
+
dottedUnderline,
|
|
17
|
+
dashedUnderline,
|
|
18
|
+
doubleUnderline,
|
|
19
|
+
underlineColor,
|
|
20
|
+
styledUnderline,
|
|
21
|
+
hyperlink,
|
|
22
|
+
detectExtendedUnderline,
|
|
23
|
+
displayLength,
|
|
24
|
+
stripAnsi,
|
|
25
|
+
} from "./index"
|
|
26
|
+
|
|
27
|
+
using term = createTerm({ color: "truecolor" })
|
|
28
|
+
|
|
29
|
+
const divider = "═".repeat(60)
|
|
30
|
+
const subDivider = "─".repeat(40)
|
|
31
|
+
|
|
32
|
+
function section(title: string): void {
|
|
33
|
+
console.log()
|
|
34
|
+
console.log(term.bold.cyan(divider))
|
|
35
|
+
console.log(term.bold.cyan(` ${title}`))
|
|
36
|
+
console.log(term.bold.cyan(divider))
|
|
37
|
+
console.log()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function subsection(title: string): void {
|
|
41
|
+
console.log(term.dim(subDivider))
|
|
42
|
+
console.log(term.bold(title))
|
|
43
|
+
console.log()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// Terminal Info
|
|
48
|
+
// =============================================================================
|
|
49
|
+
|
|
50
|
+
section("Terminal Information")
|
|
51
|
+
|
|
52
|
+
console.log(` TERM: ${process.env.TERM ?? "(not set)"}`)
|
|
53
|
+
console.log(` TERM_PROGRAM: ${process.env.TERM_PROGRAM ?? "(not set)"}`)
|
|
54
|
+
console.log(
|
|
55
|
+
` Extended underline support: ${detectExtendedUnderline() ? term.green("Yes") : term.red("No (fallback mode)")}`,
|
|
56
|
+
)
|
|
57
|
+
console.log()
|
|
58
|
+
console.log(term.dim(" Note: This storybook forces extended mode for display."))
|
|
59
|
+
console.log(term.dim(" Your terminal may show fallbacks if not supported."))
|
|
60
|
+
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// Extended Underline Styles
|
|
63
|
+
// =============================================================================
|
|
64
|
+
|
|
65
|
+
section("Extended Underline Styles")
|
|
66
|
+
|
|
67
|
+
subsection("Comparison with standard underline")
|
|
68
|
+
|
|
69
|
+
console.log(` Standard: ${term.underline("regular underline")}`)
|
|
70
|
+
console.log(` Double: ${doubleUnderline("double underline")}`)
|
|
71
|
+
console.log(` Curly: ${curlyUnderline("curly/wavy underline")}`)
|
|
72
|
+
console.log(` Dotted: ${dottedUnderline("dotted underline")}`)
|
|
73
|
+
console.log(` Dashed: ${dashedUnderline("dashed underline")}`)
|
|
74
|
+
console.log()
|
|
75
|
+
|
|
76
|
+
subsection("Side by side")
|
|
77
|
+
|
|
78
|
+
console.log(
|
|
79
|
+
` ${term.underline("standard")} | ${doubleUnderline("double")} | ${curlyUnderline("curly")} | ${dottedUnderline("dotted")} | ${dashedUnderline("dashed")}`,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
// =============================================================================
|
|
83
|
+
// Underline Color
|
|
84
|
+
// =============================================================================
|
|
85
|
+
|
|
86
|
+
section("Independent Underline Color")
|
|
87
|
+
|
|
88
|
+
subsection("Basic colors")
|
|
89
|
+
|
|
90
|
+
console.log(` Red: ${underlineColor(255, 0, 0, "error message")}`)
|
|
91
|
+
console.log(` Orange: ${underlineColor(255, 165, 0, "warning message")}`)
|
|
92
|
+
console.log(` Yellow: ${underlineColor(255, 255, 0, "caution message")}`)
|
|
93
|
+
console.log(` Green: ${underlineColor(0, 255, 0, "success message")}`)
|
|
94
|
+
console.log(` Blue: ${underlineColor(0, 128, 255, "info message")}`)
|
|
95
|
+
console.log(` Purple: ${underlineColor(128, 0, 255, "special message")}`)
|
|
96
|
+
console.log()
|
|
97
|
+
|
|
98
|
+
subsection("With text color (independent)")
|
|
99
|
+
|
|
100
|
+
console.log(` ${term.red(underlineColor(0, 255, 0, "Red text, green underline"))}`)
|
|
101
|
+
console.log(` ${term.blue(underlineColor(255, 165, 0, "Blue text, orange underline"))}`)
|
|
102
|
+
console.log(` ${term.white(underlineColor(255, 0, 0, "White text, red underline"))}`)
|
|
103
|
+
|
|
104
|
+
// =============================================================================
|
|
105
|
+
// Combined Style + Color
|
|
106
|
+
// =============================================================================
|
|
107
|
+
|
|
108
|
+
section("Combined Style + Color")
|
|
109
|
+
|
|
110
|
+
subsection("Curly with colors (like spell-check)")
|
|
111
|
+
|
|
112
|
+
console.log(` Spelling error: ${styledUnderline("curly", [255, 0, 0], "teh")} → the`)
|
|
113
|
+
console.log(` Grammar issue: ${styledUnderline("curly", [0, 128, 255], "alot")} → a lot`)
|
|
114
|
+
console.log(` Style warning: ${styledUnderline("curly", [0, 180, 0], "very unique")} → unique`)
|
|
115
|
+
console.log()
|
|
116
|
+
|
|
117
|
+
subsection("Dotted with colors (embedded content)")
|
|
118
|
+
|
|
119
|
+
console.log(` From inbox: ${styledUnderline("dotted", [100, 149, 237], "Review docs")}`)
|
|
120
|
+
console.log(` From projects: ${styledUnderline("dotted", [147, 112, 219], "Sprint planning")}`)
|
|
121
|
+
console.log()
|
|
122
|
+
|
|
123
|
+
subsection("Dashed with colors (drafts/tentative)")
|
|
124
|
+
|
|
125
|
+
console.log(` Draft: ${styledUnderline("dashed", [128, 128, 128], "WIP: New feature")}`)
|
|
126
|
+
console.log(` Tentative: ${styledUnderline("dashed", [169, 169, 169], "Maybe: Refactor auth")}`)
|
|
127
|
+
|
|
128
|
+
// =============================================================================
|
|
129
|
+
// Hyperlinks
|
|
130
|
+
// =============================================================================
|
|
131
|
+
|
|
132
|
+
section("OSC 8 Hyperlinks")
|
|
133
|
+
|
|
134
|
+
subsection("Basic hyperlinks (click to open in terminal)")
|
|
135
|
+
|
|
136
|
+
console.log(` Website: ${hyperlink("Google", "https://google.com")}`)
|
|
137
|
+
console.log(` File: ${hyperlink("README.md", "file:///Users/beorn/README.md")}`)
|
|
138
|
+
console.log(` Custom: ${hyperlink("Open in VSCode", "vscode://file/path/to/file")}`)
|
|
139
|
+
console.log()
|
|
140
|
+
|
|
141
|
+
subsection("Styled hyperlinks")
|
|
142
|
+
|
|
143
|
+
console.log(` Underlined: ${term.underline(hyperlink("Underlined link", "https://example.com"))}`)
|
|
144
|
+
console.log(` Colored: ${term.blue(hyperlink("Blue link", "https://example.com"))}`)
|
|
145
|
+
console.log(` Bold: ${term.bold(hyperlink("Bold link", "https://example.com"))}`)
|
|
146
|
+
console.log(` Combined: ${term.bold.blue.underline(hyperlink("Styled link", "https://example.com"))}`)
|
|
147
|
+
|
|
148
|
+
// =============================================================================
|
|
149
|
+
// ANSI Utilities
|
|
150
|
+
// =============================================================================
|
|
151
|
+
|
|
152
|
+
section("ANSI Utilities")
|
|
153
|
+
|
|
154
|
+
subsection("stripAnsi() - Remove escape codes")
|
|
155
|
+
|
|
156
|
+
const styled = curlyUnderline("Hello ") + term.bold.red("World")
|
|
157
|
+
console.log(` Styled: "${styled}"`)
|
|
158
|
+
console.log(` Stripped: "${stripAnsi(styled)}"`)
|
|
159
|
+
console.log()
|
|
160
|
+
|
|
161
|
+
subsection("displayLength() - Visual character count")
|
|
162
|
+
|
|
163
|
+
const coloredText = term.red("Red") + " and " + term.blue("Blue")
|
|
164
|
+
console.log(` Text: "${coloredText}"`)
|
|
165
|
+
console.log(` string.length: ${coloredText.length}`)
|
|
166
|
+
console.log(` displayLength: ${displayLength(coloredText)}`)
|
|
167
|
+
|
|
168
|
+
// =============================================================================
|
|
169
|
+
// Use Cases
|
|
170
|
+
// =============================================================================
|
|
171
|
+
|
|
172
|
+
section("Practical Use Cases")
|
|
173
|
+
|
|
174
|
+
subsection("IDE-style error highlighting")
|
|
175
|
+
|
|
176
|
+
console.log(` const ${styledUnderline("curly", [255, 0, 0], "x")} = undefined;`)
|
|
177
|
+
console.log(` ${term.red("^")} ${term.dim("Variable 'x' is declared but never used")}`)
|
|
178
|
+
console.log()
|
|
179
|
+
|
|
180
|
+
subsection("Task manager styling")
|
|
181
|
+
|
|
182
|
+
console.log(` ${term.green("✓")} ${term.dim.strikethrough("Completed task")}`)
|
|
183
|
+
console.log(` ${term.yellow("◐")} ${styledUnderline("curly", [255, 180, 0], "Due today: Submit report")}`)
|
|
184
|
+
console.log(` ${term.red("○")} ${styledUnderline("curly", [255, 80, 80], "Overdue: Fix critical bug")}`)
|
|
185
|
+
console.log(` ${term.blue("○")} ${dottedUnderline("Embedded from [[Projects]]")}`)
|
|
186
|
+
console.log(` ${term.gray("○")} ${dashedUnderline("Draft: New feature idea")}`)
|
|
187
|
+
console.log()
|
|
188
|
+
|
|
189
|
+
subsection("Documentation with clickable links")
|
|
190
|
+
|
|
191
|
+
console.log(` See ${hyperlink("API Reference", "https://docs.example.com/api")} for details.`)
|
|
192
|
+
console.log(` Implementation in ${hyperlink("src/index.ts", "file:///path/src/index.ts")}`)
|
|
193
|
+
|
|
194
|
+
// =============================================================================
|
|
195
|
+
// Summary
|
|
196
|
+
// =============================================================================
|
|
197
|
+
|
|
198
|
+
section("Summary")
|
|
199
|
+
|
|
200
|
+
console.log(" chalk-x provides:")
|
|
201
|
+
console.log(" • Extended underline styles (curly, dotted, dashed, double)")
|
|
202
|
+
console.log(" • Independent underline color (RGB)")
|
|
203
|
+
console.log(" • Combined style + color")
|
|
204
|
+
console.log(" • OSC 8 hyperlinks")
|
|
205
|
+
console.log(" • ANSI utilities (stripAnsi, displayLength)")
|
|
206
|
+
console.log(" • Graceful fallback for unsupported terminals")
|
|
207
|
+
console.log()
|
|
208
|
+
console.log(term.dim(" All features degrade gracefully in basic terminals."))
|
|
209
|
+
console.log()
|