Loading CHANGES.md +3 −3 Original line number Diff line number Diff line Loading @@ -128,11 +128,11 @@ the versioning. isn't a TTY (for example, when redirecting to a file) or when the `NO_COLOR` environment variable is set. [[#257], [#341] by Cho Hasang] - The 'fedify lookup' command now displays images depending on user's - The `fedify lookup` command now displays images depending on user's terminal emulator. [[#169], [#348] by Jiwon Kwon] - Supported terminal emulators are `Kitty`, `WezTerm`, `Konsole`, `Warp`, `Wayst`, `st`, and `iterms`. - Supported terminal emulators are Kitty, WezTerm, Konsole, Warp, Wayst, st, and iTerm. Loading deno.json +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ "@logtape/logtape": "jsr:@logtape/logtape@^1.0.0", "@std/assert": "jsr:@std/assert@^1.0.13", "@std/async": "jsr:@std/async@^1.0.13", "@std/encoding": "jsr:@std/encoding@^1.0.10", "@std/fs": "jsr:@std/fs@^1.0.3", "@std/path": "jsr:@std/path@^1.0.6", "@std/yaml": "jsr:@std/yaml@^1.0.8", Loading package.json +0 −3 Original line number Diff line number Diff line Loading @@ -3,8 +3,5 @@ "patchedDependencies": { "vitepress@1.6.3": "patches/vitepress@1.6.3.patch" } }, "dependencies": { "sharp": "^0.34.3" } } packages/cli/src/imagerenderer.ts +13 −18 Original line number Diff line number Diff line import { encodeBase64 } from "@std/encoding/base64"; import sharp from "sharp"; export type TerminalType = "kitty" | "iterm2" | "none"; Loading @@ -16,15 +17,9 @@ type KittyCommand = Record<string, string | number>; export function detectTerminalCapabilities(): TerminalType { const termProgram = (Deno.env.get("TERM_PROGRAM") || "").toLowerCase(); for (const id of KITTY_IDENTIFIERS) { if (termProgram === id) { return "kitty"; } } if (KITTY_IDENTIFIERS.includes(termProgram)) return "kitty"; if (termProgram === "iterm.app") { return "iterm2"; } if (termProgram === "iterm.app") return "iterm2"; return "none"; } Loading Loading @@ -66,8 +61,8 @@ export async function renderImageKitty( imagePath: string, cmd: KittyCommand, ): Promise<void> { const data = await Deno.readFile(imagePath); const base64Data = btoa(String.fromCharCode(...data)); const imageData = await Deno.readFile(imagePath); const base64Data = encodeBase64(imageData); let remaining = base64Data; let isFirst = true; Loading @@ -77,9 +72,9 @@ export async function renderImageKitty( const chunkCmd = { ...(isFirst ? cmd : {}), m: remaining.length > 0 ? 1 : 0, // The required 'm' property m: remaining.length > 0 ? 1 : 0, }; chunkCmd.m = remaining.length > 0 ? 1 : 0; const command = serializeGrCommand(chunkCmd, chunk); Deno.stdout.writeSync(command); Loading @@ -92,7 +87,7 @@ export async function renderImageITerm2( imagePath: string, ): Promise<void> { const imageData = await Deno.readFile(imagePath); const base64Data = btoa(String.fromCharCode(...imageData)); const base64Data = encodeBase64(imageData); const encoder = new TextEncoder(); const command = encoder.encode( Loading @@ -105,10 +100,8 @@ export async function downloadImage(url: string): Promise<string | null> { try { const response = await fetch(url); const imageData = new Uint8Array(await response.arrayBuffer()); const tempDir = Deno.env.get("TMPDIR") || Deno.env.get("TMP") || "/tmp"; const filename = `terminal_image_${Date.now()}_${crypto.randomUUID()}`; const extension = new URL(url).pathname.split(".").pop() || "jpg"; const tempPath = `${tempDir}/${filename}.${extension}`; const tempPath = await Deno.makeTempFile({ suffix: `.${extension}` }); await Deno.writeFile(tempPath, imageData); Loading @@ -118,7 +111,7 @@ export async function downloadImage(url: string): Promise<string | null> { } } export async function renderImage( export async function renderImages( imageUrls: URL[], ): Promise<void> { const graphicsProtocol = await detectTerminalCapabilities(); Loading @@ -134,6 +127,8 @@ export async function renderImage( .resize(300) .toFile(resizedPath); console.log(""); // clear the line before rendering image if (graphicsProtocol === "kitty") { await renderImageKitty(resizedPath, { a: "T", Loading @@ -142,8 +137,8 @@ export async function renderImage( } else if (graphicsProtocol === "iterm2") { await renderImageITerm2(resizedPath); } else { // Skip rendering for unsupported terminals continue; } console.log(""); // clear the line after rendering image } } packages/cli/src/lookup.ts +2 −2 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ import * as colors from "@std/fmt/colors"; import { dirname, isAbsolute, resolve } from "@std/path"; import ora from "ora"; import { getContextLoader, getDocumentLoader } from "./docloader.ts"; import { renderImage } from "./imagerenderer.ts"; import { renderImages } from "./imagerenderer.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colorEnabled, formatCliObjectOutputWithColor } from "./utils.ts"; Loading Loading @@ -137,7 +137,7 @@ export async function writeObjectToStream( imageUrls = await findAllImages(object); } if (!options.output && imageUrls.length > 0) { await renderImage(imageUrls); await renderImages(imageUrls); } } finally { writer.releaseLock(); Loading Loading
CHANGES.md +3 −3 Original line number Diff line number Diff line Loading @@ -128,11 +128,11 @@ the versioning. isn't a TTY (for example, when redirecting to a file) or when the `NO_COLOR` environment variable is set. [[#257], [#341] by Cho Hasang] - The 'fedify lookup' command now displays images depending on user's - The `fedify lookup` command now displays images depending on user's terminal emulator. [[#169], [#348] by Jiwon Kwon] - Supported terminal emulators are `Kitty`, `WezTerm`, `Konsole`, `Warp`, `Wayst`, `st`, and `iterms`. - Supported terminal emulators are Kitty, WezTerm, Konsole, Warp, Wayst, st, and iTerm. Loading
deno.json +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ "@logtape/logtape": "jsr:@logtape/logtape@^1.0.0", "@std/assert": "jsr:@std/assert@^1.0.13", "@std/async": "jsr:@std/async@^1.0.13", "@std/encoding": "jsr:@std/encoding@^1.0.10", "@std/fs": "jsr:@std/fs@^1.0.3", "@std/path": "jsr:@std/path@^1.0.6", "@std/yaml": "jsr:@std/yaml@^1.0.8", Loading
package.json +0 −3 Original line number Diff line number Diff line Loading @@ -3,8 +3,5 @@ "patchedDependencies": { "vitepress@1.6.3": "patches/vitepress@1.6.3.patch" } }, "dependencies": { "sharp": "^0.34.3" } }
packages/cli/src/imagerenderer.ts +13 −18 Original line number Diff line number Diff line import { encodeBase64 } from "@std/encoding/base64"; import sharp from "sharp"; export type TerminalType = "kitty" | "iterm2" | "none"; Loading @@ -16,15 +17,9 @@ type KittyCommand = Record<string, string | number>; export function detectTerminalCapabilities(): TerminalType { const termProgram = (Deno.env.get("TERM_PROGRAM") || "").toLowerCase(); for (const id of KITTY_IDENTIFIERS) { if (termProgram === id) { return "kitty"; } } if (KITTY_IDENTIFIERS.includes(termProgram)) return "kitty"; if (termProgram === "iterm.app") { return "iterm2"; } if (termProgram === "iterm.app") return "iterm2"; return "none"; } Loading Loading @@ -66,8 +61,8 @@ export async function renderImageKitty( imagePath: string, cmd: KittyCommand, ): Promise<void> { const data = await Deno.readFile(imagePath); const base64Data = btoa(String.fromCharCode(...data)); const imageData = await Deno.readFile(imagePath); const base64Data = encodeBase64(imageData); let remaining = base64Data; let isFirst = true; Loading @@ -77,9 +72,9 @@ export async function renderImageKitty( const chunkCmd = { ...(isFirst ? cmd : {}), m: remaining.length > 0 ? 1 : 0, // The required 'm' property m: remaining.length > 0 ? 1 : 0, }; chunkCmd.m = remaining.length > 0 ? 1 : 0; const command = serializeGrCommand(chunkCmd, chunk); Deno.stdout.writeSync(command); Loading @@ -92,7 +87,7 @@ export async function renderImageITerm2( imagePath: string, ): Promise<void> { const imageData = await Deno.readFile(imagePath); const base64Data = btoa(String.fromCharCode(...imageData)); const base64Data = encodeBase64(imageData); const encoder = new TextEncoder(); const command = encoder.encode( Loading @@ -105,10 +100,8 @@ export async function downloadImage(url: string): Promise<string | null> { try { const response = await fetch(url); const imageData = new Uint8Array(await response.arrayBuffer()); const tempDir = Deno.env.get("TMPDIR") || Deno.env.get("TMP") || "/tmp"; const filename = `terminal_image_${Date.now()}_${crypto.randomUUID()}`; const extension = new URL(url).pathname.split(".").pop() || "jpg"; const tempPath = `${tempDir}/${filename}.${extension}`; const tempPath = await Deno.makeTempFile({ suffix: `.${extension}` }); await Deno.writeFile(tempPath, imageData); Loading @@ -118,7 +111,7 @@ export async function downloadImage(url: string): Promise<string | null> { } } export async function renderImage( export async function renderImages( imageUrls: URL[], ): Promise<void> { const graphicsProtocol = await detectTerminalCapabilities(); Loading @@ -134,6 +127,8 @@ export async function renderImage( .resize(300) .toFile(resizedPath); console.log(""); // clear the line before rendering image if (graphicsProtocol === "kitty") { await renderImageKitty(resizedPath, { a: "T", Loading @@ -142,8 +137,8 @@ export async function renderImage( } else if (graphicsProtocol === "iterm2") { await renderImageITerm2(resizedPath); } else { // Skip rendering for unsupported terminals continue; } console.log(""); // clear the line after rendering image } }
packages/cli/src/lookup.ts +2 −2 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ import * as colors from "@std/fmt/colors"; import { dirname, isAbsolute, resolve } from "@std/path"; import ora from "ora"; import { getContextLoader, getDocumentLoader } from "./docloader.ts"; import { renderImage } from "./imagerenderer.ts"; import { renderImages } from "./imagerenderer.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colorEnabled, formatCliObjectOutputWithColor } from "./utils.ts"; Loading Loading @@ -137,7 +137,7 @@ export async function writeObjectToStream( imageUrls = await findAllImages(object); } if (!options.output && imageUrls.length > 0) { await renderImage(imageUrls); await renderImages(imageUrls); } } finally { writer.releaseLock(); Loading