cc98-cli 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/CHANGELOG.md +14 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +49 -3
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/storage/settings-store.d.ts +12 -0
- package/dist/storage/settings-store.d.ts.map +1 -0
- package/dist/storage/settings-store.js +46 -0
- package/dist/storage/settings-store.js.map +1 -0
- package/dist/tui/ansi.d.ts.map +1 -1
- package/dist/tui/ansi.js +5 -1
- package/dist/tui/ansi.js.map +1 -1
- package/dist/tui/app.js +1 -1
- package/dist/tui/app.js.map +1 -1
- package/dist/tui/components/content.d.ts +2 -0
- package/dist/tui/components/content.d.ts.map +1 -1
- package/dist/tui/components/content.js +47 -9
- package/dist/tui/components/content.js.map +1 -1
- package/dist/tui/components/status.d.ts +3 -0
- package/dist/tui/components/status.d.ts.map +1 -1
- package/dist/tui/components/status.js +21 -8
- package/dist/tui/components/status.js.map +1 -1
- package/dist/tui/components/utils.d.ts.map +1 -1
- package/dist/tui/components/utils.js +33 -12
- package/dist/tui/components/utils.js.map +1 -1
- package/dist/tui/controller.d.ts +36 -1
- package/dist/tui/controller.d.ts.map +1 -1
- package/dist/tui/controller.js +802 -124
- package/dist/tui/controller.js.map +1 -1
- package/dist/tui/emoji-art.d.ts +11 -0
- package/dist/tui/emoji-art.d.ts.map +1 -0
- package/dist/tui/emoji-art.js +371 -0
- package/dist/tui/emoji-art.js.map +1 -0
- package/dist/tui/emoji-renderer.d.ts +16 -0
- package/dist/tui/emoji-renderer.d.ts.map +1 -0
- package/dist/tui/emoji-renderer.js +110 -0
- package/dist/tui/emoji-renderer.js.map +1 -0
- package/dist/tui/image-renderer.d.ts +46 -0
- package/dist/tui/image-renderer.d.ts.map +1 -0
- package/dist/tui/image-renderer.js +259 -0
- package/dist/tui/image-renderer.js.map +1 -0
- package/dist/tui/keybindings.d.ts +24 -0
- package/dist/tui/keybindings.d.ts.map +1 -0
- package/dist/tui/keybindings.js +207 -0
- package/dist/tui/keybindings.js.map +1 -0
- package/dist/tui/navigation.d.ts.map +1 -1
- package/dist/tui/navigation.js +4 -0
- package/dist/tui/navigation.js.map +1 -1
- package/dist/tui/renderer.d.ts.map +1 -1
- package/dist/tui/renderer.js +181 -11
- package/dist/tui/renderer.js.map +1 -1
- package/dist/tui/state/store.d.ts.map +1 -1
- package/dist/tui/state/store.js +13 -2
- package/dist/tui/state/store.js.map +1 -1
- package/dist/tui/state/types.d.ts +24 -0
- package/dist/tui/state/types.d.ts.map +1 -1
- package/dist/tui/terminal-capabilities.d.ts +24 -0
- package/dist/tui/terminal-capabilities.d.ts.map +1 -0
- package/dist/tui/terminal-capabilities.js +55 -0
- package/dist/tui/terminal-capabilities.js.map +1 -0
- package/dist/tui/terminal.js +1 -1
- package/dist/tui/terminal.js.map +1 -1
- package/dist/tui/topic-reader.d.ts +9 -1
- package/dist/tui/topic-reader.d.ts.map +1 -1
- package/dist/tui/topic-reader.js +30 -14
- package/dist/tui/topic-reader.js.map +1 -1
- package/dist/tui/ubb-renderer.d.ts +5 -1
- package/dist/tui/ubb-renderer.d.ts.map +1 -1
- package/dist/tui/ubb-renderer.js +71 -25
- package/dist/tui/ubb-renderer.js.map +1 -1
- package/dist/update.d.ts +4 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +71 -11
- package/dist/update.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +10 -2
- package/dist/version.js.map +1 -1
- package/package.json +2 -1
- package/dist/tui/components/layout.d.ts +0 -3
- package/dist/tui/components/layout.d.ts.map +0 -1
- package/dist/tui/components/layout.js +0 -453
- package/dist/tui/components/layout.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CC98_LOGO_ART, type PixelArt } from "./emoji-art.js";
|
|
2
|
+
export { CC98_LOGO_ART };
|
|
3
|
+
export interface EmojiCategory {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly source: string;
|
|
7
|
+
readonly codes: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const EMOJI_CATEGORIES: readonly EmojiCategory[];
|
|
10
|
+
export declare function isEmojiCode(code: string): boolean;
|
|
11
|
+
export declare function getEmojiArt(code: string): PixelArt | undefined;
|
|
12
|
+
export declare function renderEmojiCode(code: string): string | undefined;
|
|
13
|
+
export declare function renderCc98Logo(): string;
|
|
14
|
+
export declare function normalizeEmojiCode(code: string): string;
|
|
15
|
+
export declare function renderPixelArt(art: PixelArt): string;
|
|
16
|
+
//# sourceMappingURL=emoji-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-renderer.d.ts","sourceRoot":"","sources":["../../src/tui/emoji-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAKzE,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAMpD,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAE9D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIhE;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAyBD,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAsBpD"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { CC98_LOGO_ART, EMOJI_ART } from "./emoji-art.js";
|
|
2
|
+
const reset = "\x1b[0m";
|
|
3
|
+
const transparent = ".";
|
|
4
|
+
export { CC98_LOGO_ART };
|
|
5
|
+
export const EMOJI_CATEGORIES = [
|
|
6
|
+
makeCategory("ac-white", "AC 娘", "ac-white", (code) => /^ac\d{2,4}$/.test(code)),
|
|
7
|
+
makeCategory("CC98", "CC98 专属", "CC98", (code) => /^cc98\d{2}$/.test(code)),
|
|
8
|
+
makeCategory("em", "经典表情", "em", (code) => /^em\d{2}$/.test(code)),
|
|
9
|
+
makeCategory("ms", "雀魂/麻将", "ms", (code) => /^ms\d{2}$/.test(code)),
|
|
10
|
+
makeCategory("tb", "贴吧系", "tb", (code) => /^tb\d{2}$/.test(code)),
|
|
11
|
+
];
|
|
12
|
+
export function isEmojiCode(code) {
|
|
13
|
+
return normalizeEmojiCode(code) in EMOJI_ART;
|
|
14
|
+
}
|
|
15
|
+
export function getEmojiArt(code) {
|
|
16
|
+
return EMOJI_ART[normalizeEmojiCode(code)];
|
|
17
|
+
}
|
|
18
|
+
export function renderEmojiCode(code) {
|
|
19
|
+
const normalized = normalizeEmojiCode(code);
|
|
20
|
+
const art = EMOJI_ART[normalized];
|
|
21
|
+
return art ? renderPixelArt(art) : undefined;
|
|
22
|
+
}
|
|
23
|
+
export function renderCc98Logo() {
|
|
24
|
+
return renderPixelArt(CC98_LOGO_ART);
|
|
25
|
+
}
|
|
26
|
+
export function normalizeEmojiCode(code) {
|
|
27
|
+
return code.trim().toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
function makeCategory(id, label, source, match) {
|
|
30
|
+
return {
|
|
31
|
+
id,
|
|
32
|
+
label,
|
|
33
|
+
source,
|
|
34
|
+
codes: Object.keys(EMOJI_ART).filter(match).sort(compareEmojiCode),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function compareEmojiCode(left, right) {
|
|
38
|
+
const leftParts = splitEmojiCode(left);
|
|
39
|
+
const rightParts = splitEmojiCode(right);
|
|
40
|
+
if (leftParts.prefix !== rightParts.prefix) {
|
|
41
|
+
return leftParts.prefix.localeCompare(rightParts.prefix);
|
|
42
|
+
}
|
|
43
|
+
return leftParts.number - rightParts.number;
|
|
44
|
+
}
|
|
45
|
+
function splitEmojiCode(code) {
|
|
46
|
+
const match = code.match(/^([a-z]+)(\d+)$/i);
|
|
47
|
+
return match ? { prefix: match[1].toLowerCase(), number: Number(match[2]) } : { prefix: code, number: 0 };
|
|
48
|
+
}
|
|
49
|
+
export function renderPixelArt(art) {
|
|
50
|
+
const output = [];
|
|
51
|
+
for (let y = 0; y < art.height; y += 2) {
|
|
52
|
+
const upper = art.rows[y] ?? "";
|
|
53
|
+
const lower = art.rows[y + 1] ?? "";
|
|
54
|
+
let line = "";
|
|
55
|
+
for (let x = 0; x < art.width; x += 1) {
|
|
56
|
+
const upperColor = colorAt(art, upper[x]);
|
|
57
|
+
const lowerColor = colorAt(art, lower[x]);
|
|
58
|
+
if (upperColor && lowerColor) {
|
|
59
|
+
line += `${reset}${fg(upperColor)}${bg(lowerColor)}▀`;
|
|
60
|
+
}
|
|
61
|
+
else if (upperColor) {
|
|
62
|
+
line += `${reset}${fg(upperColor)}▀`;
|
|
63
|
+
}
|
|
64
|
+
else if (lowerColor) {
|
|
65
|
+
line += `${reset}${fg(lowerColor)}▄`;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
line += `${reset} `;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
output.push(`${line}${reset}`);
|
|
72
|
+
}
|
|
73
|
+
return output.join("\n");
|
|
74
|
+
}
|
|
75
|
+
function colorAt(art, value) {
|
|
76
|
+
if (!value || value === transparent)
|
|
77
|
+
return undefined;
|
|
78
|
+
const index = decodeIndex(value);
|
|
79
|
+
return art.palette[index];
|
|
80
|
+
}
|
|
81
|
+
function decodeIndex(value) {
|
|
82
|
+
const code = value.codePointAt(0) ?? 0;
|
|
83
|
+
if (code >= 48 && code <= 57)
|
|
84
|
+
return code - 48;
|
|
85
|
+
if (code >= 65 && code <= 90)
|
|
86
|
+
return code - 65 + 10;
|
|
87
|
+
if (code >= 97 && code <= 122)
|
|
88
|
+
return code - 97 + 36;
|
|
89
|
+
if (value === "+")
|
|
90
|
+
return 62;
|
|
91
|
+
if (value === "-")
|
|
92
|
+
return 63;
|
|
93
|
+
return -1;
|
|
94
|
+
}
|
|
95
|
+
function fg(color) {
|
|
96
|
+
const { r, g, b } = parseColor(color);
|
|
97
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
98
|
+
}
|
|
99
|
+
function bg(color) {
|
|
100
|
+
const { r, g, b } = parseColor(color);
|
|
101
|
+
return `\x1b[48;2;${r};${g};${b}m`;
|
|
102
|
+
}
|
|
103
|
+
function parseColor(color) {
|
|
104
|
+
return {
|
|
105
|
+
r: parseInt(color.slice(0, 2), 16),
|
|
106
|
+
g: parseInt(color.slice(2, 4), 16),
|
|
107
|
+
b: parseInt(color.slice(4, 6), 16),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=emoji-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-renderer.js","sourceRoot":"","sources":["../../src/tui/emoji-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface ImageRenderOptions {
|
|
2
|
+
/** Maximum width in terminal columns */
|
|
3
|
+
maxWidth?: number;
|
|
4
|
+
/** Maximum height in terminal rows */
|
|
5
|
+
maxHeight?: number;
|
|
6
|
+
/** Whether to preserve aspect ratio (default: true) */
|
|
7
|
+
preserveAspectRatio?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface RenderedImage {
|
|
10
|
+
/** The ANSI escape sequence to display the image */
|
|
11
|
+
escapeSequence: string;
|
|
12
|
+
/** Number of terminal rows the image occupies */
|
|
13
|
+
rows: number;
|
|
14
|
+
/** Number of terminal columns the image occupies */
|
|
15
|
+
cols: number;
|
|
16
|
+
/** Original image width (if detectable) */
|
|
17
|
+
originalWidth?: number;
|
|
18
|
+
/** Original image height (if detectable) */
|
|
19
|
+
originalHeight?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ImageDimensions {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function getImageDimensionsSync(filePath: string): ImageDimensions | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Render a local image file to an ANSI escape sequence
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderLocalImage(filePath: string, options?: ImageRenderOptions): Promise<RenderedImage | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Render a cached local image synchronously for the TUI render path.
|
|
32
|
+
*/
|
|
33
|
+
export declare function renderLocalImageSync(filePath: string, options?: ImageRenderOptions): RenderedImage | null;
|
|
34
|
+
/**
|
|
35
|
+
* Render image from URL (download if needed, then render)
|
|
36
|
+
*/
|
|
37
|
+
export declare function renderImageFromUrl(url: string, options?: ImageRenderOptions): Promise<RenderedImage | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Generate a placeholder text for terminals that don't support images
|
|
40
|
+
*/
|
|
41
|
+
export declare function getImagePlaceholder(url: string, index: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Generate help text for image actions
|
|
44
|
+
*/
|
|
45
|
+
export declare function getImageActions(): string;
|
|
46
|
+
//# sourceMappingURL=image-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-renderer.d.ts","sourceRoot":"","sources":["../../src/tui/image-renderer.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAOpF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAU/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GAC/B,aAAa,GAAG,IAAI,CAUtB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAW/B;AAoND;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYtE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// Inline image rendering for supported terminals
|
|
2
|
+
// Supports iTerm2 Inline Images Protocol and Kitty Graphics Protocol
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { getImageCache } from "../storage/image-cache.js";
|
|
7
|
+
import { detectTerminalCapabilities, getImageProtocol } from "./terminal-capabilities.js";
|
|
8
|
+
export function getImageDimensionsSync(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
const data = readFileSync(filePath);
|
|
11
|
+
return parseImageDimensions(data);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render a local image file to an ANSI escape sequence
|
|
19
|
+
*/
|
|
20
|
+
export async function renderLocalImage(filePath, options = {}) {
|
|
21
|
+
const protocol = getImageProtocol();
|
|
22
|
+
if (!isSupportedProtocol(protocol))
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const data = await readFile(filePath);
|
|
26
|
+
return renderImageData(protocol, filePath, data, options);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Render a cached local image synchronously for the TUI render path.
|
|
34
|
+
*/
|
|
35
|
+
export function renderLocalImageSync(filePath, options = {}) {
|
|
36
|
+
const protocol = getImageProtocol();
|
|
37
|
+
if (!isSupportedProtocol(protocol))
|
|
38
|
+
return null;
|
|
39
|
+
try {
|
|
40
|
+
const data = readFileSync(filePath);
|
|
41
|
+
return renderImageData(protocol, filePath, data, options);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Render image from URL (download if needed, then render)
|
|
49
|
+
*/
|
|
50
|
+
export async function renderImageFromUrl(url, options = {}) {
|
|
51
|
+
const protocol = getImageProtocol();
|
|
52
|
+
if (!isSupportedProtocol(protocol))
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
const cache = getImageCache();
|
|
56
|
+
const localPath = await cache.getOrDownload(url);
|
|
57
|
+
return renderLocalImage(localPath, options);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* iTerm2 Inline Images Protocol
|
|
65
|
+
* @see https://iterm2.com/documentation-images.html
|
|
66
|
+
*/
|
|
67
|
+
function renderImageData(protocol, filePath, data, options) {
|
|
68
|
+
switch (protocol) {
|
|
69
|
+
case "iterm2":
|
|
70
|
+
return wrapForTerminal(renderIterm2(data.toString("base64"), options));
|
|
71
|
+
case "kitty":
|
|
72
|
+
return wrapForTerminal(renderKitty(filePath, options));
|
|
73
|
+
case "sixel":
|
|
74
|
+
return renderSixel(filePath, options);
|
|
75
|
+
default:
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function renderIterm2(base64, options) {
|
|
80
|
+
const params = [];
|
|
81
|
+
// Preserve aspect ratio
|
|
82
|
+
if (options.preserveAspectRatio !== false) {
|
|
83
|
+
params.push("preserveAspectRatio=1");
|
|
84
|
+
}
|
|
85
|
+
// iTerm2 is most reliable when width/height are passed as pixels.
|
|
86
|
+
// Estimate from terminal cells so layout can still reserve text rows.
|
|
87
|
+
if (options.maxWidth) {
|
|
88
|
+
params.push(`width=${Math.max(1, Math.floor(options.maxWidth * 8))}px`);
|
|
89
|
+
}
|
|
90
|
+
if (options.maxHeight) {
|
|
91
|
+
params.push(`height=${Math.max(1, Math.floor(options.maxHeight * 18))}px`);
|
|
92
|
+
}
|
|
93
|
+
// Inline=1 means display in terminal (not as a separate window)
|
|
94
|
+
params.push("inline=1");
|
|
95
|
+
const paramStr = params.join(";");
|
|
96
|
+
// OSC 1337 ; File=<params> : <base64-data> BEL
|
|
97
|
+
const escapeSequence = `\x1b]1337;File=${paramStr}:${base64}\x07`;
|
|
98
|
+
// Estimate rows based on maxWidth (assuming 2:1 char aspect ratio)
|
|
99
|
+
const rows = options.maxHeight ?? Math.ceil((options.maxWidth ?? 40) * 0.5);
|
|
100
|
+
const cols = options.maxWidth ?? 40;
|
|
101
|
+
return { escapeSequence, rows, cols };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Kitty Graphics Protocol
|
|
105
|
+
* @see https://sw.kovidgoyal.net/kitty/graphics-protocol/
|
|
106
|
+
*/
|
|
107
|
+
function renderKitty(filePath, options) {
|
|
108
|
+
// Use file transfer so Kitty can decode PNG/JPEG/GIF/WebP/SVG itself.
|
|
109
|
+
let controlData = "a=t,t=f";
|
|
110
|
+
if (options.maxWidth) {
|
|
111
|
+
controlData += `,c=${Math.max(1, Math.floor(options.maxWidth))}`; // columns
|
|
112
|
+
}
|
|
113
|
+
if (options.maxHeight) {
|
|
114
|
+
controlData += `,r=${Math.max(1, Math.floor(options.maxHeight))}`; // rows
|
|
115
|
+
}
|
|
116
|
+
const pathData = Buffer.from(filePath, "utf8").toString("base64");
|
|
117
|
+
const escapeSequence = `\x1b_G${controlData};${pathData}\x1b\\`;
|
|
118
|
+
const rows = options.maxHeight ?? Math.ceil((options.maxWidth ?? 40) * 0.5);
|
|
119
|
+
const cols = options.maxWidth ?? 40;
|
|
120
|
+
return { escapeSequence, rows, cols };
|
|
121
|
+
}
|
|
122
|
+
function renderSixel(filePath, options) {
|
|
123
|
+
const cols = Math.max(1, Math.floor(options.maxWidth ?? 24));
|
|
124
|
+
const rows = Math.max(1, Math.floor(options.maxHeight ?? 7));
|
|
125
|
+
const widthPx = cols * 8;
|
|
126
|
+
const img2sixel = spawnSync("img2sixel", ["-w", String(widthPx), filePath], {
|
|
127
|
+
encoding: "utf8",
|
|
128
|
+
maxBuffer: 8 * 1024 * 1024
|
|
129
|
+
});
|
|
130
|
+
if (img2sixel.status === 0 && img2sixel.stdout) {
|
|
131
|
+
return wrapForTerminal({ escapeSequence: img2sixel.stdout, rows, cols });
|
|
132
|
+
}
|
|
133
|
+
const chafa = spawnSync("chafa", [`--size=${cols}x${rows}`, "--format=sixels", filePath], {
|
|
134
|
+
encoding: "utf8",
|
|
135
|
+
maxBuffer: 8 * 1024 * 1024
|
|
136
|
+
});
|
|
137
|
+
if (chafa.status === 0 && chafa.stdout) {
|
|
138
|
+
return wrapForTerminal({ escapeSequence: chafa.stdout, rows, cols });
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function wrapForTerminal(image) {
|
|
143
|
+
const capabilities = detectTerminalCapabilities();
|
|
144
|
+
if (!capabilities.passthrough) {
|
|
145
|
+
return image;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...image,
|
|
149
|
+
escapeSequence: wrapTmuxPassthrough(image.escapeSequence)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function wrapTmuxPassthrough(sequence) {
|
|
153
|
+
return `\x1bPtmux;${sequence.replace(/\x1b/g, "\x1b\x1b")}\x1b\\`;
|
|
154
|
+
}
|
|
155
|
+
function isSupportedProtocol(protocol) {
|
|
156
|
+
return protocol === "iterm2" || protocol === "kitty" || protocol === "sixel";
|
|
157
|
+
}
|
|
158
|
+
function parseImageDimensions(data) {
|
|
159
|
+
if (data.length >= 24 && data.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) {
|
|
160
|
+
return {
|
|
161
|
+
width: data.readUInt32BE(16),
|
|
162
|
+
height: data.readUInt32BE(20)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (data.length >= 10 && data.toString("ascii", 0, 3) === "GIF") {
|
|
166
|
+
return {
|
|
167
|
+
width: data.readUInt16LE(6),
|
|
168
|
+
height: data.readUInt16LE(8)
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (data.length >= 12 && data.readUInt16BE(0) === 0xffd8) {
|
|
172
|
+
return parseJpegDimensions(data);
|
|
173
|
+
}
|
|
174
|
+
if (data.length >= 30 && data.toString("ascii", 0, 4) === "RIFF" && data.toString("ascii", 8, 12) === "WEBP") {
|
|
175
|
+
return parseWebpDimensions(data);
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
function parseJpegDimensions(data) {
|
|
180
|
+
let offset = 2;
|
|
181
|
+
while (offset + 9 < data.length) {
|
|
182
|
+
if (data[offset] !== 0xff) {
|
|
183
|
+
offset += 1;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const marker = data[offset + 1];
|
|
187
|
+
offset += 2;
|
|
188
|
+
if (marker === 0xd9 || marker === 0xda) {
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
if (offset + 2 > data.length) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
const length = data.readUInt16BE(offset);
|
|
195
|
+
if (length < 2 || offset + length > data.length) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
if ((marker >= 0xc0 && marker <= 0xc3) ||
|
|
199
|
+
(marker >= 0xc5 && marker <= 0xc7) ||
|
|
200
|
+
(marker >= 0xc9 && marker <= 0xcb) ||
|
|
201
|
+
(marker >= 0xcd && marker <= 0xcf)) {
|
|
202
|
+
return {
|
|
203
|
+
height: data.readUInt16BE(offset + 3),
|
|
204
|
+
width: data.readUInt16BE(offset + 5)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
offset += length;
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
function parseWebpDimensions(data) {
|
|
212
|
+
const type = data.toString("ascii", 12, 16);
|
|
213
|
+
if (type === "VP8 " && data.length >= 30) {
|
|
214
|
+
return {
|
|
215
|
+
width: data.readUInt16LE(26) & 0x3fff,
|
|
216
|
+
height: data.readUInt16LE(28) & 0x3fff
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (type === "VP8L" && data.length >= 25) {
|
|
220
|
+
const bits = data.readUInt32LE(21);
|
|
221
|
+
return {
|
|
222
|
+
width: (bits & 0x3fff) + 1,
|
|
223
|
+
height: ((bits >> 14) & 0x3fff) + 1
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (type === "VP8X" && data.length >= 30) {
|
|
227
|
+
return {
|
|
228
|
+
width: readUInt24LE(data, 24) + 1,
|
|
229
|
+
height: readUInt24LE(data, 27) + 1
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
function readUInt24LE(data, offset) {
|
|
235
|
+
return data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Generate a placeholder text for terminals that don't support images
|
|
239
|
+
*/
|
|
240
|
+
export function getImagePlaceholder(url, index) {
|
|
241
|
+
// Shorten URL for display
|
|
242
|
+
let shortUrl = url;
|
|
243
|
+
try {
|
|
244
|
+
const parsed = new URL(url);
|
|
245
|
+
const fileName = parsed.pathname.split("/").filter(Boolean).at(-1) ?? "";
|
|
246
|
+
shortUrl = `${parsed.host}/${fileName}`;
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
// Keep original if URL parsing fails
|
|
250
|
+
}
|
|
251
|
+
return `[image ${index}] ${shortUrl}`;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Generate help text for image actions
|
|
255
|
+
*/
|
|
256
|
+
export function getImageActions() {
|
|
257
|
+
return ` o 打开 c 复制图片`;
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=image-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-renderer.js","sourceRoot":"","sources":["../../src/tui/image-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type KeybindingAction = "moveUp" | "moveDown" | "moveLeft" | "moveRight" | "confirm" | "back" | "search" | "refresh" | "menu" | "help" | "quit" | "topicScrollUp" | "topicScrollDown" | "topicNextPage" | "topicPrevPage" | "topicNextFloor" | "topicPrevFloor" | "topicJumpPage" | "topicJumpFloor" | "topicJumpLast" | "topicFavorite" | "topicLike" | "topicDislike" | "topicUser" | "topicVote" | "topicReaction" | "topicOpenImage" | "topicCopyLink" | "topicRefresh" | "listNext" | "listPrev" | "listOpen" | "listBack" | "listRefresh" | "searchToggleMode" | "searchNext" | "searchPrev" | "searchExecute" | "searchClose" | "menuNext" | "menuPrev" | "menuExecute" | "menuClose" | "inputConfirm" | "inputCancel" | "inputBackspace";
|
|
2
|
+
export interface KeybindingConfig {
|
|
3
|
+
[action: string]: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare const DEFAULT_KEYBINDINGS: KeybindingConfig;
|
|
6
|
+
export declare class KeybindingManager {
|
|
7
|
+
private config;
|
|
8
|
+
private configPath;
|
|
9
|
+
private loaded;
|
|
10
|
+
constructor();
|
|
11
|
+
load(): Promise<void>;
|
|
12
|
+
save(): Promise<void>;
|
|
13
|
+
private mergeConfig;
|
|
14
|
+
getKeys(action: KeybindingAction): string[];
|
|
15
|
+
matches(key: string, action: KeybindingAction): boolean;
|
|
16
|
+
getConfig(): KeybindingConfig;
|
|
17
|
+
updateAction(action: KeybindingAction, keys: string[]): void;
|
|
18
|
+
resetToDefault(): void;
|
|
19
|
+
getActionDescription(action: KeybindingAction): string;
|
|
20
|
+
formatKey(key: string): string;
|
|
21
|
+
formatActionKeys(action: KeybindingAction): string;
|
|
22
|
+
}
|
|
23
|
+
export declare function getKeybindingManager(): KeybindingManager;
|
|
24
|
+
//# sourceMappingURL=keybindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../../src/tui/keybindings.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GAExB,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,SAAS,GACT,MAAM,GAEN,QAAQ,GACR,SAAS,GACT,MAAM,GACN,MAAM,GACN,MAAM,GAEN,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,WAAW,GACX,cAAc,GACd,WAAW,GACX,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,cAAc,GAEd,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,aAAa,GAEb,kBAAkB,GAClB,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,aAAa,GAEb,UAAU,GACV,UAAU,GACV,aAAa,GACb,WAAW,GAEX,cAAc,GACd,aAAa,GACb,gBAAgB,CAAC;AAGrB,MAAM,WAAW,gBAAgB;IAC/B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAGD,eAAO,MAAM,mBAAmB,EAAE,gBAsDjC,CAAC;AAGF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;;IAQjB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE;IAK3C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO;IAMvD,SAAS,IAAI,gBAAgB;IAK7B,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAK5D,cAAc,IAAI,IAAI;IAKtB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM;IAqDtD,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAgB9B,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM;CAInD;AAKD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAKxD"}
|