mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 18:01:22 +00:00
WIP: Rewrite export-html with tree sidebar, client-side rendering
- Add tree sidebar with search and filter (Default/All/Labels) - Client-side markdown/syntax highlighting via vendored marked.js + highlight.js - Base64 encode session data to avoid escaping issues - Reuse theme.ts color tokens via getResolvedThemeColors() - Sticky sidebar, responsive mobile layout with overlay - Click tree node to scroll to message - Keyboard shortcuts: Esc to reset, Ctrl/Cmd+F to search
This commit is contained in:
parent
a073477555
commit
256fa575fb
11 changed files with 3195 additions and 1446 deletions
|
|
@ -652,6 +652,91 @@ export function stopThemeWatcher(): void {
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// HTML Export Helpers
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Convert a 256-color index to hex string.
|
||||
* Indices 0-15: basic colors (approximate)
|
||||
* Indices 16-231: 6x6x6 color cube
|
||||
* Indices 232-255: grayscale ramp
|
||||
*/
|
||||
function ansi256ToHex(index: number): string {
|
||||
// Basic colors (0-15) - approximate common terminal values
|
||||
const basicColors = [
|
||||
"#000000",
|
||||
"#800000",
|
||||
"#008000",
|
||||
"#808000",
|
||||
"#000080",
|
||||
"#800080",
|
||||
"#008080",
|
||||
"#c0c0c0",
|
||||
"#808080",
|
||||
"#ff0000",
|
||||
"#00ff00",
|
||||
"#ffff00",
|
||||
"#0000ff",
|
||||
"#ff00ff",
|
||||
"#00ffff",
|
||||
"#ffffff",
|
||||
];
|
||||
if (index < 16) {
|
||||
return basicColors[index];
|
||||
}
|
||||
|
||||
// Color cube (16-231): 6x6x6 = 216 colors
|
||||
if (index < 232) {
|
||||
const cubeIndex = index - 16;
|
||||
const r = Math.floor(cubeIndex / 36);
|
||||
const g = Math.floor((cubeIndex % 36) / 6);
|
||||
const b = cubeIndex % 6;
|
||||
const toHex = (n: number) => (n === 0 ? 0 : 55 + n * 40).toString(16).padStart(2, "0");
|
||||
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||
}
|
||||
|
||||
// Grayscale (232-255): 24 shades
|
||||
const gray = 8 + (index - 232) * 10;
|
||||
const grayHex = gray.toString(16).padStart(2, "0");
|
||||
return `#${grayHex}${grayHex}${grayHex}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resolved theme colors as CSS-compatible hex strings.
|
||||
* Used by HTML export to generate CSS custom properties.
|
||||
*/
|
||||
export function getResolvedThemeColors(themeName?: string): Record<string, string> {
|
||||
const name = themeName ?? getDefaultTheme();
|
||||
const isLight = name === "light";
|
||||
const themeJson = loadThemeJson(name);
|
||||
const resolved = resolveThemeColors(themeJson.colors, themeJson.vars);
|
||||
|
||||
// Default text color for empty values (terminal uses default fg color)
|
||||
const defaultText = isLight ? "#000000" : "#e5e5e7";
|
||||
|
||||
const cssColors: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(resolved)) {
|
||||
if (typeof value === "number") {
|
||||
cssColors[key] = ansi256ToHex(value);
|
||||
} else if (value === "") {
|
||||
// Empty means default terminal color - use sensible fallback for HTML
|
||||
cssColors[key] = defaultText;
|
||||
} else {
|
||||
cssColors[key] = value;
|
||||
}
|
||||
}
|
||||
return cssColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a theme is a "light" theme (for CSS that needs light/dark variants).
|
||||
*/
|
||||
export function isLightTheme(themeName?: string): boolean {
|
||||
// Currently just check the name - could be extended to analyze colors
|
||||
return themeName === "light";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TUI Helpers
|
||||
// ============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue