mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-16 08:25:14 +02:00
Render a lowercase ktx half-block wordmark with the brand-orange gradient above the `ktx setup` intro on interactive TTYs. The banner degrades through truecolor, xterm-256, and monochrome, and is skipped on non-TTY, non-Unicode, or too-narrow terminals. Extract shared color/Unicode capability detection into io helpers (shouldUseColorOutput, colorDepthForOutput, unicodeSupported) so the banner and doctor report route through one implementation.
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
/**
|
|
* The `ktx setup` intro banner: a lowercase ktx wordmark drawn with
|
|
* half-block glyphs over the brand-orange gradient, followed by the product
|
|
* tagline. Rendering is a pure function of the options so output stays
|
|
* deterministic in tests.
|
|
*/
|
|
|
|
interface KtxBannerRow {
|
|
art: string;
|
|
/** Truecolor gradient stop; the middle row is ktx orange #f97316. */
|
|
rgb: readonly [number, number, number];
|
|
/** Closest xterm-256 color to {@link KtxBannerRow.rgb}. */
|
|
ansi256: number;
|
|
}
|
|
|
|
const WORDMARK: readonly KtxBannerRow[] = [
|
|
{ art: '███ ███', rgb: [253, 186, 116], ansi256: 215 },
|
|
{ art: '███ ▄██▀ ▀▀███▀▀ ▀██▄ ▄██▀', rgb: [251, 146, 60], ansi256: 214 },
|
|
{ art: '███▄██▀ ███ ▀████▀', rgb: [249, 115, 22], ansi256: 208 },
|
|
{ art: '███▀██▄ ███ ▄████▄', rgb: [234, 88, 12], ansi256: 202 },
|
|
{ art: '███ ▀██▄ ███ ▄██▀ ▀██▄', rgb: [194, 65, 12], ansi256: 166 },
|
|
];
|
|
|
|
const TAGLINE = 'context layer for data agents';
|
|
const INDENT = ' ';
|
|
|
|
const BANNER_WIDTH = Math.max(...WORDMARK.map((row) => row.art.length), TAGLINE.length) + INDENT.length;
|
|
|
|
export interface KtxSetupBannerOptions {
|
|
/** Terminal width in columns. */
|
|
columns: number;
|
|
/** Color depth in bits, as reported by `tty.WriteStream#getColorDepth`; 1 disables color. */
|
|
colorDepth: number;
|
|
/** Whether the terminal renders Unicode block glyphs. */
|
|
unicode: boolean;
|
|
}
|
|
|
|
/**
|
|
* Returns the banner block ending right above the clack intro line, or an
|
|
* empty string when the terminal cannot display it (no Unicode support or
|
|
* too narrow).
|
|
*/
|
|
export function renderKtxSetupBanner(options: KtxSetupBannerOptions): string {
|
|
if (!options.unicode || options.columns < BANNER_WIDTH) {
|
|
return '';
|
|
}
|
|
const art = WORDMARK.map((row) => INDENT + colorizeBannerRow(row, options.colorDepth));
|
|
const tagline = INDENT + (options.colorDepth > 1 ? `\u001b[2m${TAGLINE}\u001b[22m` : TAGLINE);
|
|
return `\n${art.join('\n')}\n\n${tagline}\n\n`;
|
|
}
|
|
|
|
function colorizeBannerRow(row: KtxBannerRow, colorDepth: number): string {
|
|
if (colorDepth >= 24) {
|
|
const [r, g, b] = row.rgb;
|
|
return `\u001b[38;2;${r};${g};${b}m${row.art}\u001b[39m`;
|
|
}
|
|
if (colorDepth >= 8) {
|
|
return `\u001b[38;5;${row.ansi256}m${row.art}\u001b[39m`;
|
|
}
|
|
return row.art;
|
|
}
|