@mariozechner/pi-tui 0.7.17 → 0.7.18
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.
|
@@ -1,29 +1,43 @@
|
|
|
1
1
|
import type { Component } from "../tui.js";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Default text styling for markdown content.
|
|
4
|
+
* Applied to all text unless overridden by markdown formatting.
|
|
5
|
+
*/
|
|
6
|
+
export interface DefaultTextStyle {
|
|
7
|
+
/** Foreground color - named color or hex string like "#ff0000" */
|
|
8
|
+
color?: string;
|
|
9
|
+
/** Background color - named color or hex string like "#ff0000" */
|
|
10
|
+
bgColor?: string;
|
|
11
|
+
/** Bold text */
|
|
12
|
+
bold?: boolean;
|
|
13
|
+
/** Italic text */
|
|
14
|
+
italic?: boolean;
|
|
15
|
+
/** Strikethrough text */
|
|
16
|
+
strikethrough?: boolean;
|
|
17
|
+
/** Underline text */
|
|
18
|
+
underline?: boolean;
|
|
19
|
+
}
|
|
3
20
|
export declare class Markdown implements Component {
|
|
4
21
|
private text;
|
|
5
|
-
private bgColor?;
|
|
6
|
-
private fgColor?;
|
|
7
|
-
private customBgRgb?;
|
|
8
22
|
private paddingX;
|
|
9
23
|
private paddingY;
|
|
24
|
+
private defaultTextStyle?;
|
|
10
25
|
private cachedText?;
|
|
11
26
|
private cachedWidth?;
|
|
12
27
|
private cachedLines?;
|
|
13
|
-
constructor(text?: string,
|
|
14
|
-
r: number;
|
|
15
|
-
g: number;
|
|
16
|
-
b: number;
|
|
17
|
-
}, paddingX?: number, paddingY?: number);
|
|
28
|
+
constructor(text?: string, paddingX?: number, paddingY?: number, defaultTextStyle?: DefaultTextStyle);
|
|
18
29
|
setText(text: string): void;
|
|
19
|
-
setBgColor(bgColor?: Color): void;
|
|
20
|
-
setFgColor(fgColor?: Color): void;
|
|
21
|
-
setCustomBgRgb(customBgRgb?: {
|
|
22
|
-
r: number;
|
|
23
|
-
g: number;
|
|
24
|
-
b: number;
|
|
25
|
-
}): void;
|
|
26
30
|
render(width: number): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Apply only background color from default style.
|
|
33
|
+
* Used for padding lines that don't have text content.
|
|
34
|
+
*/
|
|
35
|
+
private applyBgColor;
|
|
36
|
+
/**
|
|
37
|
+
* Apply default text style to a string.
|
|
38
|
+
* This is the base styling applied to all text content.
|
|
39
|
+
*/
|
|
40
|
+
private applyDefaultStyle;
|
|
27
41
|
private renderToken;
|
|
28
42
|
private renderInlineTokens;
|
|
29
43
|
private wrapLine;
|
|
@@ -42,5 +56,4 @@ export declare class Markdown implements Component {
|
|
|
42
56
|
*/
|
|
43
57
|
private renderTable;
|
|
44
58
|
}
|
|
45
|
-
export {};
|
|
46
59
|
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,KAAK,KAAK,GACP,OAAO,GACP,KAAK,GACL,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,OAAO,GACP,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,UAAU,GACV,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,SAAS,GACT,QAAQ,CAAC;AAEZ,qBAAa,QAAS,YAAW,SAAS;IACzC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAC,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAC,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAC,CAAsC;IAC1D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IAGzB,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;IAE/B,YACC,IAAI,GAAE,MAAW,EACjB,OAAO,CAAC,EAAE,KAAK,EACf,OAAO,CAAC,EAAE,KAAK,EACf,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EACjD,QAAQ,GAAE,MAAU,EACpB,QAAQ,GAAE,MAAU,EAQpB;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAM1B;IAED,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAMhC;IAED,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAMhC;IAED,cAAc,CAAC,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAMtE;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwG9B;IAED,OAAO,CAAC,WAAW;IAyFnB,OAAO,CAAC,kBAAkB;IAwD1B,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,cAAc;IAmFtB;;OAEG;IACH,OAAO,CAAC,UAAU;IA8ClB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAsCtB;;OAEG;IACH,OAAO,CAAC,WAAW;CAqDnB","sourcesContent":["import chalk from \"chalk\";\nimport { marked, type Token } from \"marked\";\nimport type { Component } from \"../tui.js\";\nimport { visibleWidth } from \"../utils.js\";\n\ntype Color =\n\t| \"black\"\n\t| \"red\"\n\t| \"green\"\n\t| \"yellow\"\n\t| \"blue\"\n\t| \"magenta\"\n\t| \"cyan\"\n\t| \"white\"\n\t| \"gray\"\n\t| \"bgBlack\"\n\t| \"bgRed\"\n\t| \"bgGreen\"\n\t| \"bgYellow\"\n\t| \"bgBlue\"\n\t| \"bgMagenta\"\n\t| \"bgCyan\"\n\t| \"bgWhite\"\n\t| \"bgGray\";\n\nexport class Markdown implements Component {\n\tprivate text: string;\n\tprivate bgColor?: Color;\n\tprivate fgColor?: Color;\n\tprivate customBgRgb?: { r: number; g: number; b: number };\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(\n\t\ttext: string = \"\",\n\t\tbgColor?: Color,\n\t\tfgColor?: Color,\n\t\tcustomBgRgb?: { r: number; g: number; b: number },\n\t\tpaddingX: number = 1,\n\t\tpaddingY: number = 1,\n\t) {\n\t\tthis.text = text;\n\t\tthis.bgColor = bgColor;\n\t\tthis.fgColor = fgColor;\n\t\tthis.customBgRgb = customBgRgb;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\t// Invalidate cache when text changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetBgColor(bgColor?: Color): void {\n\t\tthis.bgColor = bgColor;\n\t\t// Invalidate cache when color changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetFgColor(fgColor?: Color): void {\n\t\tthis.fgColor = fgColor;\n\t\t// Invalidate cache when color changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetCustomBgRgb(customBgRgb?: { r: number; g: number; b: number }): void {\n\t\tthis.customBgRgb = customBgRgb;\n\t\t// Invalidate cache when color changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Check cache\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\t// Calculate available width for content (subtract horizontal padding)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\t// Don't render anything if there's no actual text\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\t// Update cache\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\t// Replace tabs with 3 spaces for consistent rendering\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Parse markdown to HTML-like tokens\n\t\tconst tokens = marked.lexer(normalizedText);\n\n\t\t// Convert tokens to styled terminal output\n\t\tconst renderedLines: string[] = [];\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst nextToken = tokens[i + 1];\n\t\t\tconst tokenLines = this.renderToken(token, contentWidth, nextToken?.type);\n\t\t\trenderedLines.push(...tokenLines);\n\t\t}\n\n\t\t// Wrap lines to fit content width\n\t\tconst wrappedLines: string[] = [];\n\t\tfor (const line of renderedLines) {\n\t\t\twrappedLines.push(...this.wrapLine(line, contentWidth));\n\t\t}\n\n\t\t// Add padding and apply colors\n\t\tconst leftPad = \" \".repeat(this.paddingX);\n\t\tconst paddedLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\t// Calculate visible length\n\t\t\tconst visibleLength = visibleWidth(line);\n\t\t\t// Right padding to fill to width (accounting for left padding and content)\n\t\t\tconst rightPadLength = Math.max(0, width - this.paddingX - visibleLength);\n\t\t\tconst rightPad = \" \".repeat(rightPadLength);\n\n\t\t\t// Add left padding, content, and right padding\n\t\t\tlet paddedLine = leftPad + line + rightPad;\n\n\t\t\t// Apply foreground color if specified\n\t\t\tif (this.fgColor) {\n\t\t\t\tpaddedLine = (chalk as any)[this.fgColor](paddedLine);\n\t\t\t}\n\n\t\t\t// Apply background color if specified\n\t\t\tif (this.customBgRgb) {\n\t\t\t\tpaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(paddedLine);\n\t\t\t} else if (this.bgColor) {\n\t\t\t\tpaddedLine = (chalk as any)[this.bgColor](paddedLine);\n\t\t\t}\n\n\t\t\tpaddedLines.push(paddedLine);\n\t\t}\n\n\t\t// Add top padding (empty lines)\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst topPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tlet emptyPaddedLine = emptyLine;\n\t\t\tif (this.customBgRgb) {\n\t\t\t\temptyPaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);\n\t\t\t} else if (this.bgColor) {\n\t\t\t\temptyPaddedLine = (chalk as any)[this.bgColor](emptyPaddedLine);\n\t\t\t}\n\t\t\ttopPadding.push(emptyPaddedLine);\n\t\t}\n\n\t\t// Add bottom padding (empty lines)\n\t\tconst bottomPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tlet emptyPaddedLine = emptyLine;\n\t\t\tif (this.customBgRgb) {\n\t\t\t\temptyPaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);\n\t\t\t} else if (this.bgColor) {\n\t\t\t\temptyPaddedLine = (chalk as any)[this.bgColor](emptyPaddedLine);\n\t\t\t}\n\t\t\tbottomPadding.push(emptyPaddedLine);\n\t\t}\n\n\t\t// Combine top padding, content, and bottom padding\n\t\tconst result = [...topPadding, ...paddedLines, ...bottomPadding];\n\n\t\t// Update cache\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n\n\tprivate renderToken(token: Token, width: number, nextTokenType?: string): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tswitch (token.type) {\n\t\t\tcase \"heading\": {\n\t\t\t\tconst headingLevel = token.depth;\n\t\t\t\tconst headingPrefix = \"#\".repeat(headingLevel) + \" \";\n\t\t\t\tconst headingText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tif (headingLevel === 1) {\n\t\t\t\t\tlines.push(chalk.bold.underline.yellow(headingText));\n\t\t\t\t} else if (headingLevel === 2) {\n\t\t\t\t\tlines.push(chalk.bold.yellow(headingText));\n\t\t\t\t} else {\n\t\t\t\t\tlines.push(chalk.bold(headingPrefix + headingText));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after headings\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"paragraph\": {\n\t\t\t\tconst paragraphText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(paragraphText);\n\t\t\t\t// Don't add spacing if next token is space or list\n\t\t\t\tif (nextTokenType && nextTokenType !== \"list\" && nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"code\": {\n\t\t\t\tlines.push(chalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\t// Split code by newlines and style each line\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(chalk.dim(\" \") + chalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(chalk.gray(\"```\"));\n\t\t\t\tlines.push(\"\"); // Add spacing after code blocks\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst listLines = this.renderList(token as any, 0);\n\t\t\t\tlines.push(...listLines);\n\t\t\t\t// Don't add spacing after lists if a space token follows\n\t\t\t\t// (the space token will handle it)\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"table\": {\n\t\t\t\tconst tableLines = this.renderTable(token as any);\n\t\t\t\tlines.push(...tableLines);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"blockquote\": {\n\t\t\t\tconst quoteText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tconst quoteLines = quoteText.split(\"\\n\");\n\t\t\t\tfor (const quoteLine of quoteLines) {\n\t\t\t\t\tlines.push(chalk.gray(\"│ \") + chalk.italic(quoteLine));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after blockquotes\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"hr\":\n\t\t\t\tlines.push(chalk.gray(\"─\".repeat(Math.min(width, 80))));\n\t\t\t\tlines.push(\"\"); // Add spacing after horizontal rules\n\t\t\t\tbreak;\n\n\t\t\tcase \"html\":\n\t\t\t\t// Skip HTML for terminal output\n\t\t\t\tbreak;\n\n\t\t\tcase \"space\":\n\t\t\t\t// Space tokens represent blank lines in markdown\n\t\t\t\tlines.push(\"\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// Handle any other token types as plain text\n\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\tlines.push(token.text);\n\t\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate renderInlineTokens(tokens: Token[]): string {\n\t\tlet result = \"\";\n\n\t\tfor (const token of tokens) {\n\t\t\tswitch (token.type) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// Text tokens in list items can have nested tokens for inline formatting\n\t\t\t\t\tif (token.tokens && token.tokens.length > 0) {\n\t\t\t\t\t\tresult += this.renderInlineTokens(token.tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += token.text;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"strong\":\n\t\t\t\t\tresult += chalk.bold(this.renderInlineTokens(token.tokens || []));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"em\":\n\t\t\t\t\tresult += chalk.italic(this.renderInlineTokens(token.tokens || []));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"codespan\":\n\t\t\t\t\tresult += chalk.gray(\"`\") + chalk.cyan(token.text) + chalk.gray(\"`\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"link\": {\n\t\t\t\t\tconst linkText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\t// If link text matches href, only show the link once\n\t\t\t\t\tif (linkText === token.href) {\n\t\t\t\t\t\tresult += chalk.underline.blue(linkText);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += chalk.underline.blue(linkText) + chalk.gray(` (${token.href})`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"br\":\n\t\t\t\t\tresult += \"\\n\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"del\":\n\t\t\t\t\tresult += chalk.strikethrough(this.renderInlineTokens(token.tokens || []));\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t// Handle any other inline token types as plain text\n\t\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\t\tresult += token.text;\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate wrapLine(line: string, width: number): string[] {\n\t\t// Handle ANSI escape codes properly when wrapping\n\t\tconst wrapped: string[] = [];\n\n\t\t// Handle undefined or null lines\n\t\tif (!line) {\n\t\t\treturn [\"\"];\n\t\t}\n\n\t\t// Split by newlines first - wrap each line individually\n\t\tconst splitLines = line.split(\"\\n\");\n\t\tfor (const splitLine of splitLines) {\n\t\t\tconst visibleLength = visibleWidth(splitLine);\n\n\t\t\tif (visibleLength <= width) {\n\t\t\t\twrapped.push(splitLine);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// This line needs wrapping\n\t\t\twrapped.push(...this.wrapSingleLine(splitLine, width));\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\tprivate wrapSingleLine(line: string, width: number): string[] {\n\t\tconst wrapped: string[] = [];\n\n\t\t// Track active ANSI codes to preserve them across wrapped lines\n\t\tconst activeAnsiCodes: string[] = [];\n\t\tlet currentLine = \"\";\n\t\tlet currentLength = 0;\n\t\tlet i = 0;\n\n\t\twhile (i < line.length) {\n\t\t\tif (line[i] === \"\\x1b\" && line[i + 1] === \"[\") {\n\t\t\t\t// ANSI escape sequence - parse and track it\n\t\t\t\tlet j = i + 2;\n\t\t\t\twhile (j < line.length && line[j] && !/[mGKHJ]/.test(line[j]!)) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < line.length) {\n\t\t\t\t\tconst ansiCode = line.substring(i, j + 1);\n\t\t\t\t\tcurrentLine += ansiCode;\n\n\t\t\t\t\t// Track styling codes (ending with 'm')\n\t\t\t\t\tif (line[j] === \"m\") {\n\t\t\t\t\t\t// Reset code\n\t\t\t\t\t\tif (ansiCode === \"\\x1b[0m\" || ansiCode === \"\\x1b[m\") {\n\t\t\t\t\t\t\tactiveAnsiCodes.length = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Add to active codes (replacing similar ones)\n\t\t\t\t\t\t\tactiveAnsiCodes.push(ansiCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ti = j + 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Incomplete ANSI sequence at end - don't include it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Regular character - extract full grapheme cluster\n\t\t\t\t// Handle multi-byte characters (emoji, surrogate pairs, etc.)\n\t\t\t\tlet char: string;\n\t\t\t\tlet charByteLength: number;\n\n\t\t\t\t// Check for surrogate pair (emoji and other multi-byte chars)\n\t\t\t\tconst codePoint = line.charCodeAt(i);\n\t\t\t\tif (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < line.length) {\n\t\t\t\t\t// High surrogate - get the pair\n\t\t\t\t\tchar = line.substring(i, i + 2);\n\t\t\t\t\tcharByteLength = 2;\n\t\t\t\t} else {\n\t\t\t\t\t// Regular character\n\t\t\t\t\tchar = line[i];\n\t\t\t\t\tcharByteLength = 1;\n\t\t\t\t}\n\n\t\t\t\tconst charWidth = visibleWidth(char);\n\n\t\t\t\t// Check if adding this character would exceed width\n\t\t\t\tif (currentLength + charWidth > width) {\n\t\t\t\t\t// Need to wrap - close current line with reset if needed\n\t\t\t\t\tif (activeAnsiCodes.length > 0) {\n\t\t\t\t\t\twrapped.push(currentLine + \"\\x1b[0m\");\n\t\t\t\t\t\t// Start new line with active codes\n\t\t\t\t\t\tcurrentLine = activeAnsiCodes.join(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\twrapped.push(currentLine);\n\t\t\t\t\t\tcurrentLine = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tcurrentLength = 0;\n\t\t\t\t}\n\n\t\t\t\tcurrentLine += char;\n\t\t\t\tcurrentLength += charWidth;\n\t\t\t\ti += charByteLength;\n\t\t\t}\n\t\t}\n\n\t\tif (currentLine) {\n\t\t\twrapped.push(currentLine);\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\t/**\n\t * Render a list with proper nesting support\n\t */\n\tprivate renderList(token: Token & { items: any[]; ordered: boolean }, depth: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst indent = \" \".repeat(depth);\n\n\t\tfor (let i = 0; i < token.items.length; i++) {\n\t\t\tconst item = token.items[i];\n\t\t\tconst bullet = token.ordered ? `${i + 1}. ` : \"- \";\n\n\t\t\t// Process item tokens to handle nested lists\n\t\t\tconst itemLines = this.renderListItem(item.tokens || [], depth);\n\n\t\t\tif (itemLines.length > 0) {\n\t\t\t\t// First line - check if it's a nested list\n\t\t\t\t// A nested list will start with indent (spaces) followed by cyan bullet\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = /^\\s+\\x1b\\[36m[-\\d]/.test(firstLine); // starts with spaces + cyan + bullet char\n\n\t\t\t\tif (isNestedList) {\n\t\t\t\t\t// This is a nested list, just add it as-is (already has full indent)\n\t\t\t\t\tlines.push(firstLine);\n\t\t\t\t} else {\n\t\t\t\t\t// Regular text content - add indent and bullet\n\t\t\t\t\tlines.push(indent + chalk.cyan(bullet) + firstLine);\n\t\t\t\t}\n\n\t\t\t\t// Rest of the lines\n\t\t\t\tfor (let j = 1; j < itemLines.length; j++) {\n\t\t\t\t\tconst line = itemLines[j];\n\t\t\t\t\tconst isNestedListLine = /^\\s+\\x1b\\[36m[-\\d]/.test(line); // starts with spaces + cyan + bullet char\n\n\t\t\t\t\tif (isNestedListLine) {\n\t\t\t\t\t\t// Nested list line - already has full indent\n\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular content - add parent indent + 2 spaces for continuation\n\t\t\t\t\t\tlines.push(indent + \" \" + line);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlines.push(indent + chalk.cyan(bullet));\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render list item tokens, handling nested lists\n\t * Returns lines WITHOUT the parent indent (renderList will add it)\n\t */\n\tprivate renderListItem(tokens: Token[], parentDepth: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tfor (const token of tokens) {\n\t\t\tif (token.type === \"list\") {\n\t\t\t\t// Nested list - render with one additional indent level\n\t\t\t\t// These lines will have their own indent, so we just add them as-is\n\t\t\t\tconst nestedLines = this.renderList(token as any, parentDepth + 1);\n\t\t\t\tlines.push(...nestedLines);\n\t\t\t} else if (token.type === \"text\") {\n\t\t\t\t// Text content (may have inline tokens)\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.tokens && token.tokens.length > 0 ? this.renderInlineTokens(token.tokens) : token.text || \"\";\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"paragraph\") {\n\t\t\t\t// Paragraph in list item\n\t\t\t\tconst text = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"code\") {\n\t\t\t\t// Code block in list item\n\t\t\t\tlines.push(chalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(chalk.dim(\" \") + chalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(chalk.gray(\"```\"));\n\t\t\t} else {\n\t\t\t\t// Other token types - try to render as inline\n\t\t\t\tconst text = this.renderInlineTokens([token]);\n\t\t\t\tif (text) {\n\t\t\t\t\tlines.push(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render a table\n\t */\n\tprivate renderTable(token: Token & { header: any[]; rows: any[][] }): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// Calculate column widths\n\t\tconst columnWidths: number[] = [];\n\n\t\t// Check header\n\t\tfor (let i = 0; i < token.header.length; i++) {\n\t\t\tconst headerText = this.renderInlineTokens(token.header[i].tokens || []);\n\t\t\tconst width = visibleWidth(headerText);\n\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t}\n\n\t\t// Check rows\n\t\tfor (const row of token.rows) {\n\t\t\tfor (let i = 0; i < row.length; i++) {\n\t\t\t\tconst cellText = this.renderInlineTokens(row[i].tokens || []);\n\t\t\t\tconst width = visibleWidth(cellText);\n\t\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t\t}\n\t\t}\n\n\t\t// Limit column widths to reasonable max\n\t\tconst maxColWidth = 40;\n\t\tfor (let i = 0; i < columnWidths.length; i++) {\n\t\t\tcolumnWidths[i] = Math.min(columnWidths[i], maxColWidth);\n\t\t}\n\n\t\t// Render header\n\t\tconst headerCells = token.header.map((cell, i) => {\n\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\treturn chalk.bold(text.padEnd(columnWidths[i]));\n\t\t});\n\t\tlines.push(\"│ \" + headerCells.join(\" │ \") + \" │\");\n\n\t\t// Render separator\n\t\tconst separatorCells = columnWidths.map((width) => \"─\".repeat(width));\n\t\tlines.push(\"├─\" + separatorCells.join(\"─┼─\") + \"─┤\");\n\n\t\t// Render rows\n\t\tfor (const row of token.rows) {\n\t\t\tconst rowCells = row.map((cell, i) => {\n\t\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\t\tconst visWidth = visibleWidth(text);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, columnWidths[i] - visWidth));\n\t\t\t\treturn text + padding;\n\t\t\t});\n\t\t\tlines.push(\"│ \" + rowCells.join(\" │ \") + \" │\");\n\t\t}\n\n\t\tlines.push(\"\"); // Add spacing after table\n\t\treturn lines;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAM3C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kBAAkB;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yBAAyB;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,QAAS,YAAW,SAAS;IACzC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAG5C,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;IAE/B,YAAY,IAAI,GAAE,MAAW,EAAE,QAAQ,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU,EAAE,gBAAgB,CAAC,EAAE,gBAAgB,EAK7G;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAM1B;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAuF9B;IAED;;;OAGG;IACH,OAAO,CAAC,YAAY;IAiBpB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAsDzB,OAAO,CAAC,WAAW;IAyFnB,OAAO,CAAC,kBAAkB;IAyE1B,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,cAAc;IAmFtB;;OAEG;IACH,OAAO,CAAC,UAAU;IA8ClB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAsCtB;;OAEG;IACH,OAAO,CAAC,WAAW;CAqDnB","sourcesContent":["import { Chalk } from \"chalk\";\nimport { marked, type Token } from \"marked\";\nimport type { Component } from \"../tui.js\";\nimport { visibleWidth } from \"../utils.js\";\n\n// Use a chalk instance with color level 3 for consistent ANSI output\nconst colorChalk = new Chalk({ level: 3 });\n\n/**\n * Default text styling for markdown content.\n * Applied to all text unless overridden by markdown formatting.\n */\nexport interface DefaultTextStyle {\n\t/** Foreground color - named color or hex string like \"#ff0000\" */\n\tcolor?: string;\n\t/** Background color - named color or hex string like \"#ff0000\" */\n\tbgColor?: string;\n\t/** Bold text */\n\tbold?: boolean;\n\t/** Italic text */\n\titalic?: boolean;\n\t/** Strikethrough text */\n\tstrikethrough?: boolean;\n\t/** Underline text */\n\tunderline?: boolean;\n}\n\nexport class Markdown implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate defaultTextStyle?: DefaultTextStyle;\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(text: string = \"\", paddingX: number = 1, paddingY: number = 1, defaultTextStyle?: DefaultTextStyle) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.defaultTextStyle = defaultTextStyle;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\t// Invalidate cache when text changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Check cache\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\t// Calculate available width for content (subtract horizontal padding)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\t// Don't render anything if there's no actual text\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\t// Update cache\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\t// Replace tabs with 3 spaces for consistent rendering\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Parse markdown to HTML-like tokens\n\t\tconst tokens = marked.lexer(normalizedText);\n\n\t\t// Convert tokens to styled terminal output\n\t\tconst renderedLines: string[] = [];\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst nextToken = tokens[i + 1];\n\t\t\tconst tokenLines = this.renderToken(token, contentWidth, nextToken?.type);\n\t\t\trenderedLines.push(...tokenLines);\n\t\t}\n\n\t\t// Wrap lines to fit content width\n\t\tconst wrappedLines: string[] = [];\n\t\tfor (const line of renderedLines) {\n\t\t\twrappedLines.push(...this.wrapLine(line, contentWidth));\n\t\t}\n\n\t\t// Add padding and apply background color if specified\n\t\tconst leftPad = \" \".repeat(this.paddingX);\n\t\tconst paddedLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\t// Calculate visible length\n\t\t\tconst visibleLength = visibleWidth(line);\n\t\t\t// Right padding to fill to width (accounting for left padding and content)\n\t\t\tconst rightPadLength = Math.max(0, width - this.paddingX - visibleLength);\n\t\t\tconst rightPad = \" \".repeat(rightPadLength);\n\n\t\t\t// Add left padding, content, and right padding\n\t\t\tlet paddedLine = leftPad + line + rightPad;\n\n\t\t\t// Apply background color to entire line if specified\n\t\t\tif (this.defaultTextStyle?.bgColor) {\n\t\t\t\tpaddedLine = this.applyBgColor(paddedLine);\n\t\t\t}\n\n\t\t\tpaddedLines.push(paddedLine);\n\t\t}\n\n\t\t// Add top padding (empty lines)\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst topPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst paddedEmptyLine = this.defaultTextStyle?.bgColor ? this.applyBgColor(emptyLine) : emptyLine;\n\t\t\ttopPadding.push(paddedEmptyLine);\n\t\t}\n\n\t\t// Add bottom padding (empty lines)\n\t\tconst bottomPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst paddedEmptyLine = this.defaultTextStyle?.bgColor ? this.applyBgColor(emptyLine) : emptyLine;\n\t\t\tbottomPadding.push(paddedEmptyLine);\n\t\t}\n\n\t\t// Combine top padding, content, and bottom padding\n\t\tconst result = [...topPadding, ...paddedLines, ...bottomPadding];\n\n\t\t// Update cache\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n\n\t/**\n\t * Apply only background color from default style.\n\t * Used for padding lines that don't have text content.\n\t */\n\tprivate applyBgColor(text: string): string {\n\t\tif (!this.defaultTextStyle?.bgColor) {\n\t\t\treturn text;\n\t\t}\n\n\t\tif (this.defaultTextStyle.bgColor.startsWith(\"#\")) {\n\t\t\t// Hex color\n\t\t\tconst hex = this.defaultTextStyle.bgColor.substring(1);\n\t\t\tconst r = Number.parseInt(hex.substring(0, 2), 16);\n\t\t\tconst g = Number.parseInt(hex.substring(2, 4), 16);\n\t\t\tconst b = Number.parseInt(hex.substring(4, 6), 16);\n\t\t\treturn colorChalk.bgRgb(r, g, b)(text);\n\t\t}\n\t\t// Named background color (bgRed, bgBlue, etc.)\n\t\treturn (colorChalk as any)[this.defaultTextStyle.bgColor](text);\n\t}\n\n\t/**\n\t * Apply default text style to a string.\n\t * This is the base styling applied to all text content.\n\t */\n\tprivate applyDefaultStyle(text: string): string {\n\t\tif (!this.defaultTextStyle) {\n\t\t\treturn text;\n\t\t}\n\n\t\tlet styled = text;\n\n\t\t// Apply color\n\t\tif (this.defaultTextStyle.color) {\n\t\t\tif (this.defaultTextStyle.color.startsWith(\"#\")) {\n\t\t\t\t// Hex color\n\t\t\t\tconst hex = this.defaultTextStyle.color.substring(1);\n\t\t\t\tconst r = Number.parseInt(hex.substring(0, 2), 16);\n\t\t\t\tconst g = Number.parseInt(hex.substring(2, 4), 16);\n\t\t\t\tconst b = Number.parseInt(hex.substring(4, 6), 16);\n\t\t\t\tstyled = colorChalk.rgb(r, g, b)(styled);\n\t\t\t} else {\n\t\t\t\t// Named color\n\t\t\t\tstyled = (colorChalk as any)[this.defaultTextStyle.color](styled);\n\t\t\t}\n\t\t}\n\n\t\t// Apply background color\n\t\tif (this.defaultTextStyle.bgColor) {\n\t\t\tif (this.defaultTextStyle.bgColor.startsWith(\"#\")) {\n\t\t\t\t// Hex color\n\t\t\t\tconst hex = this.defaultTextStyle.bgColor.substring(1);\n\t\t\t\tconst r = Number.parseInt(hex.substring(0, 2), 16);\n\t\t\t\tconst g = Number.parseInt(hex.substring(2, 4), 16);\n\t\t\t\tconst b = Number.parseInt(hex.substring(4, 6), 16);\n\t\t\t\tstyled = colorChalk.bgRgb(r, g, b)(styled);\n\t\t\t} else {\n\t\t\t\t// Named background color (bgRed, bgBlue, etc.)\n\t\t\t\tstyled = (colorChalk as any)[this.defaultTextStyle.bgColor](styled);\n\t\t\t}\n\t\t}\n\n\t\t// Apply text decorations\n\t\tif (this.defaultTextStyle.bold) {\n\t\t\tstyled = colorChalk.bold(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.italic) {\n\t\t\tstyled = colorChalk.italic(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.strikethrough) {\n\t\t\tstyled = colorChalk.strikethrough(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.underline) {\n\t\t\tstyled = colorChalk.underline(styled);\n\t\t}\n\n\t\treturn styled;\n\t}\n\n\tprivate renderToken(token: Token, width: number, nextTokenType?: string): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tswitch (token.type) {\n\t\t\tcase \"heading\": {\n\t\t\t\tconst headingLevel = token.depth;\n\t\t\t\tconst headingPrefix = \"#\".repeat(headingLevel) + \" \";\n\t\t\t\tconst headingText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tif (headingLevel === 1) {\n\t\t\t\t\tlines.push(colorChalk.bold.underline.yellow(headingText));\n\t\t\t\t} else if (headingLevel === 2) {\n\t\t\t\t\tlines.push(colorChalk.bold.yellow(headingText));\n\t\t\t\t} else {\n\t\t\t\t\tlines.push(colorChalk.bold(headingPrefix + headingText));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after headings\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"paragraph\": {\n\t\t\t\tconst paragraphText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(paragraphText);\n\t\t\t\t// Don't add spacing if next token is space or list\n\t\t\t\tif (nextTokenType && nextTokenType !== \"list\" && nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"code\": {\n\t\t\t\tlines.push(colorChalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\t// Split code by newlines and style each line\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(colorChalk.dim(\" \") + colorChalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(colorChalk.gray(\"```\"));\n\t\t\t\tlines.push(\"\"); // Add spacing after code blocks\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst listLines = this.renderList(token as any, 0);\n\t\t\t\tlines.push(...listLines);\n\t\t\t\t// Don't add spacing after lists if a space token follows\n\t\t\t\t// (the space token will handle it)\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"table\": {\n\t\t\t\tconst tableLines = this.renderTable(token as any);\n\t\t\t\tlines.push(...tableLines);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"blockquote\": {\n\t\t\t\tconst quoteText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tconst quoteLines = quoteText.split(\"\\n\");\n\t\t\t\tfor (const quoteLine of quoteLines) {\n\t\t\t\t\tlines.push(colorChalk.gray(\"│ \") + colorChalk.italic(quoteLine));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after blockquotes\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"hr\":\n\t\t\t\tlines.push(colorChalk.gray(\"─\".repeat(Math.min(width, 80))));\n\t\t\t\tlines.push(\"\"); // Add spacing after horizontal rules\n\t\t\t\tbreak;\n\n\t\t\tcase \"html\":\n\t\t\t\t// Skip HTML for terminal output\n\t\t\t\tbreak;\n\n\t\t\tcase \"space\":\n\t\t\t\t// Space tokens represent blank lines in markdown\n\t\t\t\tlines.push(\"\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// Handle any other token types as plain text\n\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\tlines.push(token.text);\n\t\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate renderInlineTokens(tokens: Token[]): string {\n\t\tlet result = \"\";\n\n\t\tfor (const token of tokens) {\n\t\t\tswitch (token.type) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// Text tokens in list items can have nested tokens for inline formatting\n\t\t\t\t\tif (token.tokens && token.tokens.length > 0) {\n\t\t\t\t\t\tresult += this.renderInlineTokens(token.tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Apply default style to plain text\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"strong\": {\n\t\t\t\t\t// Apply bold, then reapply default style after\n\t\t\t\t\tconst boldContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += colorChalk.bold(boldContent) + this.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"em\": {\n\t\t\t\t\t// Apply italic, then reapply default style after\n\t\t\t\t\tconst italicContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += colorChalk.italic(italicContent) + this.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"codespan\":\n\t\t\t\t\t// Apply code styling, then reapply default style after\n\t\t\t\t\tresult +=\n\t\t\t\t\t\tcolorChalk.gray(\"`\") +\n\t\t\t\t\t\tcolorChalk.cyan(token.text) +\n\t\t\t\t\t\tcolorChalk.gray(\"`\") +\n\t\t\t\t\t\tthis.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"link\": {\n\t\t\t\t\tconst linkText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\t// If link text matches href, only show the link once\n\t\t\t\t\tif (linkText === token.href) {\n\t\t\t\t\t\tresult += colorChalk.underline.blue(linkText) + this.applyDefaultStyle(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult +=\n\t\t\t\t\t\t\tcolorChalk.underline.blue(linkText) +\n\t\t\t\t\t\t\tcolorChalk.gray(` (${token.href})`) +\n\t\t\t\t\t\t\tthis.applyDefaultStyle(\"\");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"br\":\n\t\t\t\t\tresult += \"\\n\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"del\": {\n\t\t\t\t\tconst delContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += colorChalk.strikethrough(delContent) + this.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\t// Handle any other inline token types as plain text\n\t\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate wrapLine(line: string, width: number): string[] {\n\t\t// Handle ANSI escape codes properly when wrapping\n\t\tconst wrapped: string[] = [];\n\n\t\t// Handle undefined or null lines\n\t\tif (!line) {\n\t\t\treturn [\"\"];\n\t\t}\n\n\t\t// Split by newlines first - wrap each line individually\n\t\tconst splitLines = line.split(\"\\n\");\n\t\tfor (const splitLine of splitLines) {\n\t\t\tconst visibleLength = visibleWidth(splitLine);\n\n\t\t\tif (visibleLength <= width) {\n\t\t\t\twrapped.push(splitLine);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// This line needs wrapping\n\t\t\twrapped.push(...this.wrapSingleLine(splitLine, width));\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\tprivate wrapSingleLine(line: string, width: number): string[] {\n\t\tconst wrapped: string[] = [];\n\n\t\t// Track active ANSI codes to preserve them across wrapped lines\n\t\tconst activeAnsiCodes: string[] = [];\n\t\tlet currentLine = \"\";\n\t\tlet currentLength = 0;\n\t\tlet i = 0;\n\n\t\twhile (i < line.length) {\n\t\t\tif (line[i] === \"\\x1b\" && line[i + 1] === \"[\") {\n\t\t\t\t// ANSI escape sequence - parse and track it\n\t\t\t\tlet j = i + 2;\n\t\t\t\twhile (j < line.length && line[j] && !/[mGKHJ]/.test(line[j]!)) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < line.length) {\n\t\t\t\t\tconst ansiCode = line.substring(i, j + 1);\n\t\t\t\t\tcurrentLine += ansiCode;\n\n\t\t\t\t\t// Track styling codes (ending with 'm')\n\t\t\t\t\tif (line[j] === \"m\") {\n\t\t\t\t\t\t// Reset code\n\t\t\t\t\t\tif (ansiCode === \"\\x1b[0m\" || ansiCode === \"\\x1b[m\") {\n\t\t\t\t\t\t\tactiveAnsiCodes.length = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Add to active codes (replacing similar ones)\n\t\t\t\t\t\t\tactiveAnsiCodes.push(ansiCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ti = j + 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Incomplete ANSI sequence at end - don't include it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Regular character - extract full grapheme cluster\n\t\t\t\t// Handle multi-byte characters (emoji, surrogate pairs, etc.)\n\t\t\t\tlet char: string;\n\t\t\t\tlet charByteLength: number;\n\n\t\t\t\t// Check for surrogate pair (emoji and other multi-byte chars)\n\t\t\t\tconst codePoint = line.charCodeAt(i);\n\t\t\t\tif (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < line.length) {\n\t\t\t\t\t// High surrogate - get the pair\n\t\t\t\t\tchar = line.substring(i, i + 2);\n\t\t\t\t\tcharByteLength = 2;\n\t\t\t\t} else {\n\t\t\t\t\t// Regular character\n\t\t\t\t\tchar = line[i];\n\t\t\t\t\tcharByteLength = 1;\n\t\t\t\t}\n\n\t\t\t\tconst charWidth = visibleWidth(char);\n\n\t\t\t\t// Check if adding this character would exceed width\n\t\t\t\tif (currentLength + charWidth > width) {\n\t\t\t\t\t// Need to wrap - close current line with reset if needed\n\t\t\t\t\tif (activeAnsiCodes.length > 0) {\n\t\t\t\t\t\twrapped.push(currentLine + \"\\x1b[0m\");\n\t\t\t\t\t\t// Start new line with active codes\n\t\t\t\t\t\tcurrentLine = activeAnsiCodes.join(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\twrapped.push(currentLine);\n\t\t\t\t\t\tcurrentLine = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tcurrentLength = 0;\n\t\t\t\t}\n\n\t\t\t\tcurrentLine += char;\n\t\t\t\tcurrentLength += charWidth;\n\t\t\t\ti += charByteLength;\n\t\t\t}\n\t\t}\n\n\t\tif (currentLine) {\n\t\t\twrapped.push(currentLine);\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\t/**\n\t * Render a list with proper nesting support\n\t */\n\tprivate renderList(token: Token & { items: any[]; ordered: boolean }, depth: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst indent = \" \".repeat(depth);\n\n\t\tfor (let i = 0; i < token.items.length; i++) {\n\t\t\tconst item = token.items[i];\n\t\t\tconst bullet = token.ordered ? `${i + 1}. ` : \"- \";\n\n\t\t\t// Process item tokens to handle nested lists\n\t\t\tconst itemLines = this.renderListItem(item.tokens || [], depth);\n\n\t\t\tif (itemLines.length > 0) {\n\t\t\t\t// First line - check if it's a nested list\n\t\t\t\t// A nested list will start with indent (spaces) followed by cyan bullet\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = /^\\s+\\x1b\\[36m[-\\d]/.test(firstLine); // starts with spaces + cyan + bullet char\n\n\t\t\t\tif (isNestedList) {\n\t\t\t\t\t// This is a nested list, just add it as-is (already has full indent)\n\t\t\t\t\tlines.push(firstLine);\n\t\t\t\t} else {\n\t\t\t\t\t// Regular text content - add indent and bullet\n\t\t\t\t\tlines.push(indent + colorChalk.cyan(bullet) + firstLine);\n\t\t\t\t}\n\n\t\t\t\t// Rest of the lines\n\t\t\t\tfor (let j = 1; j < itemLines.length; j++) {\n\t\t\t\t\tconst line = itemLines[j];\n\t\t\t\t\tconst isNestedListLine = /^\\s+\\x1b\\[36m[-\\d]/.test(line); // starts with spaces + cyan + bullet char\n\n\t\t\t\t\tif (isNestedListLine) {\n\t\t\t\t\t\t// Nested list line - already has full indent\n\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular content - add parent indent + 2 spaces for continuation\n\t\t\t\t\t\tlines.push(indent + \" \" + line);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlines.push(indent + colorChalk.cyan(bullet));\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render list item tokens, handling nested lists\n\t * Returns lines WITHOUT the parent indent (renderList will add it)\n\t */\n\tprivate renderListItem(tokens: Token[], parentDepth: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tfor (const token of tokens) {\n\t\t\tif (token.type === \"list\") {\n\t\t\t\t// Nested list - render with one additional indent level\n\t\t\t\t// These lines will have their own indent, so we just add them as-is\n\t\t\t\tconst nestedLines = this.renderList(token as any, parentDepth + 1);\n\t\t\t\tlines.push(...nestedLines);\n\t\t\t} else if (token.type === \"text\") {\n\t\t\t\t// Text content (may have inline tokens)\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.tokens && token.tokens.length > 0 ? this.renderInlineTokens(token.tokens) : token.text || \"\";\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"paragraph\") {\n\t\t\t\t// Paragraph in list item\n\t\t\t\tconst text = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"code\") {\n\t\t\t\t// Code block in list item\n\t\t\t\tlines.push(colorChalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(colorChalk.dim(\" \") + colorChalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(colorChalk.gray(\"```\"));\n\t\t\t} else {\n\t\t\t\t// Other token types - try to render as inline\n\t\t\t\tconst text = this.renderInlineTokens([token]);\n\t\t\t\tif (text) {\n\t\t\t\t\tlines.push(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render a table\n\t */\n\tprivate renderTable(token: Token & { header: any[]; rows: any[][] }): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// Calculate column widths\n\t\tconst columnWidths: number[] = [];\n\n\t\t// Check header\n\t\tfor (let i = 0; i < token.header.length; i++) {\n\t\t\tconst headerText = this.renderInlineTokens(token.header[i].tokens || []);\n\t\t\tconst width = visibleWidth(headerText);\n\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t}\n\n\t\t// Check rows\n\t\tfor (const row of token.rows) {\n\t\t\tfor (let i = 0; i < row.length; i++) {\n\t\t\t\tconst cellText = this.renderInlineTokens(row[i].tokens || []);\n\t\t\t\tconst width = visibleWidth(cellText);\n\t\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t\t}\n\t\t}\n\n\t\t// Limit column widths to reasonable max\n\t\tconst maxColWidth = 40;\n\t\tfor (let i = 0; i < columnWidths.length; i++) {\n\t\t\tcolumnWidths[i] = Math.min(columnWidths[i], maxColWidth);\n\t\t}\n\n\t\t// Render header\n\t\tconst headerCells = token.header.map((cell, i) => {\n\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\treturn colorChalk.bold(text.padEnd(columnWidths[i]));\n\t\t});\n\t\tlines.push(\"│ \" + headerCells.join(\" │ \") + \" │\");\n\n\t\t// Render separator\n\t\tconst separatorCells = columnWidths.map((width) => \"─\".repeat(width));\n\t\tlines.push(\"├─\" + separatorCells.join(\"─┼─\") + \"─┤\");\n\n\t\t// Render rows\n\t\tfor (const row of token.rows) {\n\t\t\tconst rowCells = row.map((cell, i) => {\n\t\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\t\tconst visWidth = visibleWidth(text);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, columnWidths[i] - visWidth));\n\t\t\t\treturn text + padding;\n\t\t\t});\n\t\t\tlines.push(\"│ \" + rowCells.join(\" │ \") + \" │\");\n\t\t}\n\n\t\tlines.push(\"\"); // Add spacing after table\n\t\treturn lines;\n\t}\n}\n"]}
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Chalk } from "chalk";
|
|
2
2
|
import { marked } from "marked";
|
|
3
3
|
import { visibleWidth } from "../utils.js";
|
|
4
|
+
// Use a chalk instance with color level 3 for consistent ANSI output
|
|
5
|
+
const colorChalk = new Chalk({ level: 3 });
|
|
4
6
|
export class Markdown {
|
|
5
7
|
text;
|
|
6
|
-
bgColor;
|
|
7
|
-
fgColor;
|
|
8
|
-
customBgRgb;
|
|
9
8
|
paddingX; // Left/right padding
|
|
10
9
|
paddingY; // Top/bottom padding
|
|
10
|
+
defaultTextStyle;
|
|
11
11
|
// Cache for rendered output
|
|
12
12
|
cachedText;
|
|
13
13
|
cachedWidth;
|
|
14
14
|
cachedLines;
|
|
15
|
-
constructor(text = "",
|
|
15
|
+
constructor(text = "", paddingX = 1, paddingY = 1, defaultTextStyle) {
|
|
16
16
|
this.text = text;
|
|
17
|
-
this.bgColor = bgColor;
|
|
18
|
-
this.fgColor = fgColor;
|
|
19
|
-
this.customBgRgb = customBgRgb;
|
|
20
17
|
this.paddingX = paddingX;
|
|
21
18
|
this.paddingY = paddingY;
|
|
19
|
+
this.defaultTextStyle = defaultTextStyle;
|
|
22
20
|
}
|
|
23
21
|
setText(text) {
|
|
24
22
|
this.text = text;
|
|
@@ -27,27 +25,6 @@ export class Markdown {
|
|
|
27
25
|
this.cachedWidth = undefined;
|
|
28
26
|
this.cachedLines = undefined;
|
|
29
27
|
}
|
|
30
|
-
setBgColor(bgColor) {
|
|
31
|
-
this.bgColor = bgColor;
|
|
32
|
-
// Invalidate cache when color changes
|
|
33
|
-
this.cachedText = undefined;
|
|
34
|
-
this.cachedWidth = undefined;
|
|
35
|
-
this.cachedLines = undefined;
|
|
36
|
-
}
|
|
37
|
-
setFgColor(fgColor) {
|
|
38
|
-
this.fgColor = fgColor;
|
|
39
|
-
// Invalidate cache when color changes
|
|
40
|
-
this.cachedText = undefined;
|
|
41
|
-
this.cachedWidth = undefined;
|
|
42
|
-
this.cachedLines = undefined;
|
|
43
|
-
}
|
|
44
|
-
setCustomBgRgb(customBgRgb) {
|
|
45
|
-
this.customBgRgb = customBgRgb;
|
|
46
|
-
// Invalidate cache when color changes
|
|
47
|
-
this.cachedText = undefined;
|
|
48
|
-
this.cachedWidth = undefined;
|
|
49
|
-
this.cachedLines = undefined;
|
|
50
|
-
}
|
|
51
28
|
render(width) {
|
|
52
29
|
// Check cache
|
|
53
30
|
if (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {
|
|
@@ -81,7 +58,7 @@ export class Markdown {
|
|
|
81
58
|
for (const line of renderedLines) {
|
|
82
59
|
wrappedLines.push(...this.wrapLine(line, contentWidth));
|
|
83
60
|
}
|
|
84
|
-
// Add padding and apply
|
|
61
|
+
// Add padding and apply background color if specified
|
|
85
62
|
const leftPad = " ".repeat(this.paddingX);
|
|
86
63
|
const paddedLines = [];
|
|
87
64
|
for (const line of wrappedLines) {
|
|
@@ -92,16 +69,9 @@ export class Markdown {
|
|
|
92
69
|
const rightPad = " ".repeat(rightPadLength);
|
|
93
70
|
// Add left padding, content, and right padding
|
|
94
71
|
let paddedLine = leftPad + line + rightPad;
|
|
95
|
-
// Apply
|
|
96
|
-
if (this.
|
|
97
|
-
paddedLine =
|
|
98
|
-
}
|
|
99
|
-
// Apply background color if specified
|
|
100
|
-
if (this.customBgRgb) {
|
|
101
|
-
paddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(paddedLine);
|
|
102
|
-
}
|
|
103
|
-
else if (this.bgColor) {
|
|
104
|
-
paddedLine = chalk[this.bgColor](paddedLine);
|
|
72
|
+
// Apply background color to entire line if specified
|
|
73
|
+
if (this.defaultTextStyle?.bgColor) {
|
|
74
|
+
paddedLine = this.applyBgColor(paddedLine);
|
|
105
75
|
}
|
|
106
76
|
paddedLines.push(paddedLine);
|
|
107
77
|
}
|
|
@@ -109,26 +79,14 @@ export class Markdown {
|
|
|
109
79
|
const emptyLine = " ".repeat(width);
|
|
110
80
|
const topPadding = [];
|
|
111
81
|
for (let i = 0; i < this.paddingY; i++) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
emptyPaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);
|
|
115
|
-
}
|
|
116
|
-
else if (this.bgColor) {
|
|
117
|
-
emptyPaddedLine = chalk[this.bgColor](emptyPaddedLine);
|
|
118
|
-
}
|
|
119
|
-
topPadding.push(emptyPaddedLine);
|
|
82
|
+
const paddedEmptyLine = this.defaultTextStyle?.bgColor ? this.applyBgColor(emptyLine) : emptyLine;
|
|
83
|
+
topPadding.push(paddedEmptyLine);
|
|
120
84
|
}
|
|
121
85
|
// Add bottom padding (empty lines)
|
|
122
86
|
const bottomPadding = [];
|
|
123
87
|
for (let i = 0; i < this.paddingY; i++) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
emptyPaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);
|
|
127
|
-
}
|
|
128
|
-
else if (this.bgColor) {
|
|
129
|
-
emptyPaddedLine = chalk[this.bgColor](emptyPaddedLine);
|
|
130
|
-
}
|
|
131
|
-
bottomPadding.push(emptyPaddedLine);
|
|
88
|
+
const paddedEmptyLine = this.defaultTextStyle?.bgColor ? this.applyBgColor(emptyLine) : emptyLine;
|
|
89
|
+
bottomPadding.push(paddedEmptyLine);
|
|
132
90
|
}
|
|
133
91
|
// Combine top padding, content, and bottom padding
|
|
134
92
|
const result = [...topPadding, ...paddedLines, ...bottomPadding];
|
|
@@ -138,6 +96,79 @@ export class Markdown {
|
|
|
138
96
|
this.cachedLines = result;
|
|
139
97
|
return result.length > 0 ? result : [""];
|
|
140
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Apply only background color from default style.
|
|
101
|
+
* Used for padding lines that don't have text content.
|
|
102
|
+
*/
|
|
103
|
+
applyBgColor(text) {
|
|
104
|
+
if (!this.defaultTextStyle?.bgColor) {
|
|
105
|
+
return text;
|
|
106
|
+
}
|
|
107
|
+
if (this.defaultTextStyle.bgColor.startsWith("#")) {
|
|
108
|
+
// Hex color
|
|
109
|
+
const hex = this.defaultTextStyle.bgColor.substring(1);
|
|
110
|
+
const r = Number.parseInt(hex.substring(0, 2), 16);
|
|
111
|
+
const g = Number.parseInt(hex.substring(2, 4), 16);
|
|
112
|
+
const b = Number.parseInt(hex.substring(4, 6), 16);
|
|
113
|
+
return colorChalk.bgRgb(r, g, b)(text);
|
|
114
|
+
}
|
|
115
|
+
// Named background color (bgRed, bgBlue, etc.)
|
|
116
|
+
return colorChalk[this.defaultTextStyle.bgColor](text);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Apply default text style to a string.
|
|
120
|
+
* This is the base styling applied to all text content.
|
|
121
|
+
*/
|
|
122
|
+
applyDefaultStyle(text) {
|
|
123
|
+
if (!this.defaultTextStyle) {
|
|
124
|
+
return text;
|
|
125
|
+
}
|
|
126
|
+
let styled = text;
|
|
127
|
+
// Apply color
|
|
128
|
+
if (this.defaultTextStyle.color) {
|
|
129
|
+
if (this.defaultTextStyle.color.startsWith("#")) {
|
|
130
|
+
// Hex color
|
|
131
|
+
const hex = this.defaultTextStyle.color.substring(1);
|
|
132
|
+
const r = Number.parseInt(hex.substring(0, 2), 16);
|
|
133
|
+
const g = Number.parseInt(hex.substring(2, 4), 16);
|
|
134
|
+
const b = Number.parseInt(hex.substring(4, 6), 16);
|
|
135
|
+
styled = colorChalk.rgb(r, g, b)(styled);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Named color
|
|
139
|
+
styled = colorChalk[this.defaultTextStyle.color](styled);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Apply background color
|
|
143
|
+
if (this.defaultTextStyle.bgColor) {
|
|
144
|
+
if (this.defaultTextStyle.bgColor.startsWith("#")) {
|
|
145
|
+
// Hex color
|
|
146
|
+
const hex = this.defaultTextStyle.bgColor.substring(1);
|
|
147
|
+
const r = Number.parseInt(hex.substring(0, 2), 16);
|
|
148
|
+
const g = Number.parseInt(hex.substring(2, 4), 16);
|
|
149
|
+
const b = Number.parseInt(hex.substring(4, 6), 16);
|
|
150
|
+
styled = colorChalk.bgRgb(r, g, b)(styled);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// Named background color (bgRed, bgBlue, etc.)
|
|
154
|
+
styled = colorChalk[this.defaultTextStyle.bgColor](styled);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Apply text decorations
|
|
158
|
+
if (this.defaultTextStyle.bold) {
|
|
159
|
+
styled = colorChalk.bold(styled);
|
|
160
|
+
}
|
|
161
|
+
if (this.defaultTextStyle.italic) {
|
|
162
|
+
styled = colorChalk.italic(styled);
|
|
163
|
+
}
|
|
164
|
+
if (this.defaultTextStyle.strikethrough) {
|
|
165
|
+
styled = colorChalk.strikethrough(styled);
|
|
166
|
+
}
|
|
167
|
+
if (this.defaultTextStyle.underline) {
|
|
168
|
+
styled = colorChalk.underline(styled);
|
|
169
|
+
}
|
|
170
|
+
return styled;
|
|
171
|
+
}
|
|
141
172
|
renderToken(token, width, nextTokenType) {
|
|
142
173
|
const lines = [];
|
|
143
174
|
switch (token.type) {
|
|
@@ -146,13 +177,13 @@ export class Markdown {
|
|
|
146
177
|
const headingPrefix = "#".repeat(headingLevel) + " ";
|
|
147
178
|
const headingText = this.renderInlineTokens(token.tokens || []);
|
|
148
179
|
if (headingLevel === 1) {
|
|
149
|
-
lines.push(
|
|
180
|
+
lines.push(colorChalk.bold.underline.yellow(headingText));
|
|
150
181
|
}
|
|
151
182
|
else if (headingLevel === 2) {
|
|
152
|
-
lines.push(
|
|
183
|
+
lines.push(colorChalk.bold.yellow(headingText));
|
|
153
184
|
}
|
|
154
185
|
else {
|
|
155
|
-
lines.push(
|
|
186
|
+
lines.push(colorChalk.bold(headingPrefix + headingText));
|
|
156
187
|
}
|
|
157
188
|
lines.push(""); // Add spacing after headings
|
|
158
189
|
break;
|
|
@@ -167,13 +198,13 @@ export class Markdown {
|
|
|
167
198
|
break;
|
|
168
199
|
}
|
|
169
200
|
case "code": {
|
|
170
|
-
lines.push(
|
|
201
|
+
lines.push(colorChalk.gray("```" + (token.lang || "")));
|
|
171
202
|
// Split code by newlines and style each line
|
|
172
203
|
const codeLines = token.text.split("\n");
|
|
173
204
|
for (const codeLine of codeLines) {
|
|
174
|
-
lines.push(
|
|
205
|
+
lines.push(colorChalk.dim(" ") + colorChalk.green(codeLine));
|
|
175
206
|
}
|
|
176
|
-
lines.push(
|
|
207
|
+
lines.push(colorChalk.gray("```"));
|
|
177
208
|
lines.push(""); // Add spacing after code blocks
|
|
178
209
|
break;
|
|
179
210
|
}
|
|
@@ -193,13 +224,13 @@ export class Markdown {
|
|
|
193
224
|
const quoteText = this.renderInlineTokens(token.tokens || []);
|
|
194
225
|
const quoteLines = quoteText.split("\n");
|
|
195
226
|
for (const quoteLine of quoteLines) {
|
|
196
|
-
lines.push(
|
|
227
|
+
lines.push(colorChalk.gray("│ ") + colorChalk.italic(quoteLine));
|
|
197
228
|
}
|
|
198
229
|
lines.push(""); // Add spacing after blockquotes
|
|
199
230
|
break;
|
|
200
231
|
}
|
|
201
232
|
case "hr":
|
|
202
|
-
lines.push(
|
|
233
|
+
lines.push(colorChalk.gray("─".repeat(Math.min(width, 80))));
|
|
203
234
|
lines.push(""); // Add spacing after horizontal rules
|
|
204
235
|
break;
|
|
205
236
|
case "html":
|
|
@@ -227,39 +258,56 @@ export class Markdown {
|
|
|
227
258
|
result += this.renderInlineTokens(token.tokens);
|
|
228
259
|
}
|
|
229
260
|
else {
|
|
230
|
-
|
|
261
|
+
// Apply default style to plain text
|
|
262
|
+
result += this.applyDefaultStyle(token.text);
|
|
231
263
|
}
|
|
232
264
|
break;
|
|
233
|
-
case "strong":
|
|
234
|
-
|
|
265
|
+
case "strong": {
|
|
266
|
+
// Apply bold, then reapply default style after
|
|
267
|
+
const boldContent = this.renderInlineTokens(token.tokens || []);
|
|
268
|
+
result += colorChalk.bold(boldContent) + this.applyDefaultStyle("");
|
|
235
269
|
break;
|
|
236
|
-
|
|
237
|
-
|
|
270
|
+
}
|
|
271
|
+
case "em": {
|
|
272
|
+
// Apply italic, then reapply default style after
|
|
273
|
+
const italicContent = this.renderInlineTokens(token.tokens || []);
|
|
274
|
+
result += colorChalk.italic(italicContent) + this.applyDefaultStyle("");
|
|
238
275
|
break;
|
|
276
|
+
}
|
|
239
277
|
case "codespan":
|
|
240
|
-
|
|
278
|
+
// Apply code styling, then reapply default style after
|
|
279
|
+
result +=
|
|
280
|
+
colorChalk.gray("`") +
|
|
281
|
+
colorChalk.cyan(token.text) +
|
|
282
|
+
colorChalk.gray("`") +
|
|
283
|
+
this.applyDefaultStyle("");
|
|
241
284
|
break;
|
|
242
285
|
case "link": {
|
|
243
286
|
const linkText = this.renderInlineTokens(token.tokens || []);
|
|
244
287
|
// If link text matches href, only show the link once
|
|
245
288
|
if (linkText === token.href) {
|
|
246
|
-
result +=
|
|
289
|
+
result += colorChalk.underline.blue(linkText) + this.applyDefaultStyle("");
|
|
247
290
|
}
|
|
248
291
|
else {
|
|
249
|
-
result +=
|
|
292
|
+
result +=
|
|
293
|
+
colorChalk.underline.blue(linkText) +
|
|
294
|
+
colorChalk.gray(` (${token.href})`) +
|
|
295
|
+
this.applyDefaultStyle("");
|
|
250
296
|
}
|
|
251
297
|
break;
|
|
252
298
|
}
|
|
253
299
|
case "br":
|
|
254
300
|
result += "\n";
|
|
255
301
|
break;
|
|
256
|
-
case "del":
|
|
257
|
-
|
|
302
|
+
case "del": {
|
|
303
|
+
const delContent = this.renderInlineTokens(token.tokens || []);
|
|
304
|
+
result += colorChalk.strikethrough(delContent) + this.applyDefaultStyle("");
|
|
258
305
|
break;
|
|
306
|
+
}
|
|
259
307
|
default:
|
|
260
308
|
// Handle any other inline token types as plain text
|
|
261
309
|
if ("text" in token && typeof token.text === "string") {
|
|
262
|
-
result += token.text;
|
|
310
|
+
result += this.applyDefaultStyle(token.text);
|
|
263
311
|
}
|
|
264
312
|
}
|
|
265
313
|
}
|
|
@@ -384,7 +432,7 @@ export class Markdown {
|
|
|
384
432
|
}
|
|
385
433
|
else {
|
|
386
434
|
// Regular text content - add indent and bullet
|
|
387
|
-
lines.push(indent +
|
|
435
|
+
lines.push(indent + colorChalk.cyan(bullet) + firstLine);
|
|
388
436
|
}
|
|
389
437
|
// Rest of the lines
|
|
390
438
|
for (let j = 1; j < itemLines.length; j++) {
|
|
@@ -401,7 +449,7 @@ export class Markdown {
|
|
|
401
449
|
}
|
|
402
450
|
}
|
|
403
451
|
else {
|
|
404
|
-
lines.push(indent +
|
|
452
|
+
lines.push(indent + colorChalk.cyan(bullet));
|
|
405
453
|
}
|
|
406
454
|
}
|
|
407
455
|
return lines;
|
|
@@ -431,12 +479,12 @@ export class Markdown {
|
|
|
431
479
|
}
|
|
432
480
|
else if (token.type === "code") {
|
|
433
481
|
// Code block in list item
|
|
434
|
-
lines.push(
|
|
482
|
+
lines.push(colorChalk.gray("```" + (token.lang || "")));
|
|
435
483
|
const codeLines = token.text.split("\n");
|
|
436
484
|
for (const codeLine of codeLines) {
|
|
437
|
-
lines.push(
|
|
485
|
+
lines.push(colorChalk.dim(" ") + colorChalk.green(codeLine));
|
|
438
486
|
}
|
|
439
|
-
lines.push(
|
|
487
|
+
lines.push(colorChalk.gray("```"));
|
|
440
488
|
}
|
|
441
489
|
else {
|
|
442
490
|
// Other token types - try to render as inline
|
|
@@ -477,7 +525,7 @@ export class Markdown {
|
|
|
477
525
|
// Render header
|
|
478
526
|
const headerCells = token.header.map((cell, i) => {
|
|
479
527
|
const text = this.renderInlineTokens(cell.tokens || []);
|
|
480
|
-
return
|
|
528
|
+
return colorChalk.bold(text.padEnd(columnWidths[i]));
|
|
481
529
|
});
|
|
482
530
|
lines.push("│ " + headerCells.join(" │ ") + " │");
|
|
483
531
|
// Render separator
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from \"chalk\";\nimport { marked, type Token } from \"marked\";\nimport type { Component } from \"../tui.js\";\nimport { visibleWidth } from \"../utils.js\";\n\ntype Color =\n\t| \"black\"\n\t| \"red\"\n\t| \"green\"\n\t| \"yellow\"\n\t| \"blue\"\n\t| \"magenta\"\n\t| \"cyan\"\n\t| \"white\"\n\t| \"gray\"\n\t| \"bgBlack\"\n\t| \"bgRed\"\n\t| \"bgGreen\"\n\t| \"bgYellow\"\n\t| \"bgBlue\"\n\t| \"bgMagenta\"\n\t| \"bgCyan\"\n\t| \"bgWhite\"\n\t| \"bgGray\";\n\nexport class Markdown implements Component {\n\tprivate text: string;\n\tprivate bgColor?: Color;\n\tprivate fgColor?: Color;\n\tprivate customBgRgb?: { r: number; g: number; b: number };\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(\n\t\ttext: string = \"\",\n\t\tbgColor?: Color,\n\t\tfgColor?: Color,\n\t\tcustomBgRgb?: { r: number; g: number; b: number },\n\t\tpaddingX: number = 1,\n\t\tpaddingY: number = 1,\n\t) {\n\t\tthis.text = text;\n\t\tthis.bgColor = bgColor;\n\t\tthis.fgColor = fgColor;\n\t\tthis.customBgRgb = customBgRgb;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\t// Invalidate cache when text changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetBgColor(bgColor?: Color): void {\n\t\tthis.bgColor = bgColor;\n\t\t// Invalidate cache when color changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetFgColor(fgColor?: Color): void {\n\t\tthis.fgColor = fgColor;\n\t\t// Invalidate cache when color changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetCustomBgRgb(customBgRgb?: { r: number; g: number; b: number }): void {\n\t\tthis.customBgRgb = customBgRgb;\n\t\t// Invalidate cache when color changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Check cache\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\t// Calculate available width for content (subtract horizontal padding)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\t// Don't render anything if there's no actual text\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\t// Update cache\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\t// Replace tabs with 3 spaces for consistent rendering\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Parse markdown to HTML-like tokens\n\t\tconst tokens = marked.lexer(normalizedText);\n\n\t\t// Convert tokens to styled terminal output\n\t\tconst renderedLines: string[] = [];\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst nextToken = tokens[i + 1];\n\t\t\tconst tokenLines = this.renderToken(token, contentWidth, nextToken?.type);\n\t\t\trenderedLines.push(...tokenLines);\n\t\t}\n\n\t\t// Wrap lines to fit content width\n\t\tconst wrappedLines: string[] = [];\n\t\tfor (const line of renderedLines) {\n\t\t\twrappedLines.push(...this.wrapLine(line, contentWidth));\n\t\t}\n\n\t\t// Add padding and apply colors\n\t\tconst leftPad = \" \".repeat(this.paddingX);\n\t\tconst paddedLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\t// Calculate visible length\n\t\t\tconst visibleLength = visibleWidth(line);\n\t\t\t// Right padding to fill to width (accounting for left padding and content)\n\t\t\tconst rightPadLength = Math.max(0, width - this.paddingX - visibleLength);\n\t\t\tconst rightPad = \" \".repeat(rightPadLength);\n\n\t\t\t// Add left padding, content, and right padding\n\t\t\tlet paddedLine = leftPad + line + rightPad;\n\n\t\t\t// Apply foreground color if specified\n\t\t\tif (this.fgColor) {\n\t\t\t\tpaddedLine = (chalk as any)[this.fgColor](paddedLine);\n\t\t\t}\n\n\t\t\t// Apply background color if specified\n\t\t\tif (this.customBgRgb) {\n\t\t\t\tpaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(paddedLine);\n\t\t\t} else if (this.bgColor) {\n\t\t\t\tpaddedLine = (chalk as any)[this.bgColor](paddedLine);\n\t\t\t}\n\n\t\t\tpaddedLines.push(paddedLine);\n\t\t}\n\n\t\t// Add top padding (empty lines)\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst topPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tlet emptyPaddedLine = emptyLine;\n\t\t\tif (this.customBgRgb) {\n\t\t\t\temptyPaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);\n\t\t\t} else if (this.bgColor) {\n\t\t\t\temptyPaddedLine = (chalk as any)[this.bgColor](emptyPaddedLine);\n\t\t\t}\n\t\t\ttopPadding.push(emptyPaddedLine);\n\t\t}\n\n\t\t// Add bottom padding (empty lines)\n\t\tconst bottomPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tlet emptyPaddedLine = emptyLine;\n\t\t\tif (this.customBgRgb) {\n\t\t\t\temptyPaddedLine = chalk.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);\n\t\t\t} else if (this.bgColor) {\n\t\t\t\temptyPaddedLine = (chalk as any)[this.bgColor](emptyPaddedLine);\n\t\t\t}\n\t\t\tbottomPadding.push(emptyPaddedLine);\n\t\t}\n\n\t\t// Combine top padding, content, and bottom padding\n\t\tconst result = [...topPadding, ...paddedLines, ...bottomPadding];\n\n\t\t// Update cache\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n\n\tprivate renderToken(token: Token, width: number, nextTokenType?: string): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tswitch (token.type) {\n\t\t\tcase \"heading\": {\n\t\t\t\tconst headingLevel = token.depth;\n\t\t\t\tconst headingPrefix = \"#\".repeat(headingLevel) + \" \";\n\t\t\t\tconst headingText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tif (headingLevel === 1) {\n\t\t\t\t\tlines.push(chalk.bold.underline.yellow(headingText));\n\t\t\t\t} else if (headingLevel === 2) {\n\t\t\t\t\tlines.push(chalk.bold.yellow(headingText));\n\t\t\t\t} else {\n\t\t\t\t\tlines.push(chalk.bold(headingPrefix + headingText));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after headings\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"paragraph\": {\n\t\t\t\tconst paragraphText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(paragraphText);\n\t\t\t\t// Don't add spacing if next token is space or list\n\t\t\t\tif (nextTokenType && nextTokenType !== \"list\" && nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"code\": {\n\t\t\t\tlines.push(chalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\t// Split code by newlines and style each line\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(chalk.dim(\" \") + chalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(chalk.gray(\"```\"));\n\t\t\t\tlines.push(\"\"); // Add spacing after code blocks\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst listLines = this.renderList(token as any, 0);\n\t\t\t\tlines.push(...listLines);\n\t\t\t\t// Don't add spacing after lists if a space token follows\n\t\t\t\t// (the space token will handle it)\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"table\": {\n\t\t\t\tconst tableLines = this.renderTable(token as any);\n\t\t\t\tlines.push(...tableLines);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"blockquote\": {\n\t\t\t\tconst quoteText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tconst quoteLines = quoteText.split(\"\\n\");\n\t\t\t\tfor (const quoteLine of quoteLines) {\n\t\t\t\t\tlines.push(chalk.gray(\"│ \") + chalk.italic(quoteLine));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after blockquotes\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"hr\":\n\t\t\t\tlines.push(chalk.gray(\"─\".repeat(Math.min(width, 80))));\n\t\t\t\tlines.push(\"\"); // Add spacing after horizontal rules\n\t\t\t\tbreak;\n\n\t\t\tcase \"html\":\n\t\t\t\t// Skip HTML for terminal output\n\t\t\t\tbreak;\n\n\t\t\tcase \"space\":\n\t\t\t\t// Space tokens represent blank lines in markdown\n\t\t\t\tlines.push(\"\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// Handle any other token types as plain text\n\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\tlines.push(token.text);\n\t\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate renderInlineTokens(tokens: Token[]): string {\n\t\tlet result = \"\";\n\n\t\tfor (const token of tokens) {\n\t\t\tswitch (token.type) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// Text tokens in list items can have nested tokens for inline formatting\n\t\t\t\t\tif (token.tokens && token.tokens.length > 0) {\n\t\t\t\t\t\tresult += this.renderInlineTokens(token.tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += token.text;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"strong\":\n\t\t\t\t\tresult += chalk.bold(this.renderInlineTokens(token.tokens || []));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"em\":\n\t\t\t\t\tresult += chalk.italic(this.renderInlineTokens(token.tokens || []));\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"codespan\":\n\t\t\t\t\tresult += chalk.gray(\"`\") + chalk.cyan(token.text) + chalk.gray(\"`\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"link\": {\n\t\t\t\t\tconst linkText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\t// If link text matches href, only show the link once\n\t\t\t\t\tif (linkText === token.href) {\n\t\t\t\t\t\tresult += chalk.underline.blue(linkText);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += chalk.underline.blue(linkText) + chalk.gray(` (${token.href})`);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"br\":\n\t\t\t\t\tresult += \"\\n\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"del\":\n\t\t\t\t\tresult += chalk.strikethrough(this.renderInlineTokens(token.tokens || []));\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t// Handle any other inline token types as plain text\n\t\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\t\tresult += token.text;\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate wrapLine(line: string, width: number): string[] {\n\t\t// Handle ANSI escape codes properly when wrapping\n\t\tconst wrapped: string[] = [];\n\n\t\t// Handle undefined or null lines\n\t\tif (!line) {\n\t\t\treturn [\"\"];\n\t\t}\n\n\t\t// Split by newlines first - wrap each line individually\n\t\tconst splitLines = line.split(\"\\n\");\n\t\tfor (const splitLine of splitLines) {\n\t\t\tconst visibleLength = visibleWidth(splitLine);\n\n\t\t\tif (visibleLength <= width) {\n\t\t\t\twrapped.push(splitLine);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// This line needs wrapping\n\t\t\twrapped.push(...this.wrapSingleLine(splitLine, width));\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\tprivate wrapSingleLine(line: string, width: number): string[] {\n\t\tconst wrapped: string[] = [];\n\n\t\t// Track active ANSI codes to preserve them across wrapped lines\n\t\tconst activeAnsiCodes: string[] = [];\n\t\tlet currentLine = \"\";\n\t\tlet currentLength = 0;\n\t\tlet i = 0;\n\n\t\twhile (i < line.length) {\n\t\t\tif (line[i] === \"\\x1b\" && line[i + 1] === \"[\") {\n\t\t\t\t// ANSI escape sequence - parse and track it\n\t\t\t\tlet j = i + 2;\n\t\t\t\twhile (j < line.length && line[j] && !/[mGKHJ]/.test(line[j]!)) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < line.length) {\n\t\t\t\t\tconst ansiCode = line.substring(i, j + 1);\n\t\t\t\t\tcurrentLine += ansiCode;\n\n\t\t\t\t\t// Track styling codes (ending with 'm')\n\t\t\t\t\tif (line[j] === \"m\") {\n\t\t\t\t\t\t// Reset code\n\t\t\t\t\t\tif (ansiCode === \"\\x1b[0m\" || ansiCode === \"\\x1b[m\") {\n\t\t\t\t\t\t\tactiveAnsiCodes.length = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Add to active codes (replacing similar ones)\n\t\t\t\t\t\t\tactiveAnsiCodes.push(ansiCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ti = j + 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Incomplete ANSI sequence at end - don't include it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Regular character - extract full grapheme cluster\n\t\t\t\t// Handle multi-byte characters (emoji, surrogate pairs, etc.)\n\t\t\t\tlet char: string;\n\t\t\t\tlet charByteLength: number;\n\n\t\t\t\t// Check for surrogate pair (emoji and other multi-byte chars)\n\t\t\t\tconst codePoint = line.charCodeAt(i);\n\t\t\t\tif (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < line.length) {\n\t\t\t\t\t// High surrogate - get the pair\n\t\t\t\t\tchar = line.substring(i, i + 2);\n\t\t\t\t\tcharByteLength = 2;\n\t\t\t\t} else {\n\t\t\t\t\t// Regular character\n\t\t\t\t\tchar = line[i];\n\t\t\t\t\tcharByteLength = 1;\n\t\t\t\t}\n\n\t\t\t\tconst charWidth = visibleWidth(char);\n\n\t\t\t\t// Check if adding this character would exceed width\n\t\t\t\tif (currentLength + charWidth > width) {\n\t\t\t\t\t// Need to wrap - close current line with reset if needed\n\t\t\t\t\tif (activeAnsiCodes.length > 0) {\n\t\t\t\t\t\twrapped.push(currentLine + \"\\x1b[0m\");\n\t\t\t\t\t\t// Start new line with active codes\n\t\t\t\t\t\tcurrentLine = activeAnsiCodes.join(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\twrapped.push(currentLine);\n\t\t\t\t\t\tcurrentLine = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tcurrentLength = 0;\n\t\t\t\t}\n\n\t\t\t\tcurrentLine += char;\n\t\t\t\tcurrentLength += charWidth;\n\t\t\t\ti += charByteLength;\n\t\t\t}\n\t\t}\n\n\t\tif (currentLine) {\n\t\t\twrapped.push(currentLine);\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\t/**\n\t * Render a list with proper nesting support\n\t */\n\tprivate renderList(token: Token & { items: any[]; ordered: boolean }, depth: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst indent = \" \".repeat(depth);\n\n\t\tfor (let i = 0; i < token.items.length; i++) {\n\t\t\tconst item = token.items[i];\n\t\t\tconst bullet = token.ordered ? `${i + 1}. ` : \"- \";\n\n\t\t\t// Process item tokens to handle nested lists\n\t\t\tconst itemLines = this.renderListItem(item.tokens || [], depth);\n\n\t\t\tif (itemLines.length > 0) {\n\t\t\t\t// First line - check if it's a nested list\n\t\t\t\t// A nested list will start with indent (spaces) followed by cyan bullet\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = /^\\s+\\x1b\\[36m[-\\d]/.test(firstLine); // starts with spaces + cyan + bullet char\n\n\t\t\t\tif (isNestedList) {\n\t\t\t\t\t// This is a nested list, just add it as-is (already has full indent)\n\t\t\t\t\tlines.push(firstLine);\n\t\t\t\t} else {\n\t\t\t\t\t// Regular text content - add indent and bullet\n\t\t\t\t\tlines.push(indent + chalk.cyan(bullet) + firstLine);\n\t\t\t\t}\n\n\t\t\t\t// Rest of the lines\n\t\t\t\tfor (let j = 1; j < itemLines.length; j++) {\n\t\t\t\t\tconst line = itemLines[j];\n\t\t\t\t\tconst isNestedListLine = /^\\s+\\x1b\\[36m[-\\d]/.test(line); // starts with spaces + cyan + bullet char\n\n\t\t\t\t\tif (isNestedListLine) {\n\t\t\t\t\t\t// Nested list line - already has full indent\n\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular content - add parent indent + 2 spaces for continuation\n\t\t\t\t\t\tlines.push(indent + \" \" + line);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlines.push(indent + chalk.cyan(bullet));\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render list item tokens, handling nested lists\n\t * Returns lines WITHOUT the parent indent (renderList will add it)\n\t */\n\tprivate renderListItem(tokens: Token[], parentDepth: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tfor (const token of tokens) {\n\t\t\tif (token.type === \"list\") {\n\t\t\t\t// Nested list - render with one additional indent level\n\t\t\t\t// These lines will have their own indent, so we just add them as-is\n\t\t\t\tconst nestedLines = this.renderList(token as any, parentDepth + 1);\n\t\t\t\tlines.push(...nestedLines);\n\t\t\t} else if (token.type === \"text\") {\n\t\t\t\t// Text content (may have inline tokens)\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.tokens && token.tokens.length > 0 ? this.renderInlineTokens(token.tokens) : token.text || \"\";\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"paragraph\") {\n\t\t\t\t// Paragraph in list item\n\t\t\t\tconst text = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"code\") {\n\t\t\t\t// Code block in list item\n\t\t\t\tlines.push(chalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(chalk.dim(\" \") + chalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(chalk.gray(\"```\"));\n\t\t\t} else {\n\t\t\t\t// Other token types - try to render as inline\n\t\t\t\tconst text = this.renderInlineTokens([token]);\n\t\t\t\tif (text) {\n\t\t\t\t\tlines.push(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render a table\n\t */\n\tprivate renderTable(token: Token & { header: any[]; rows: any[][] }): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// Calculate column widths\n\t\tconst columnWidths: number[] = [];\n\n\t\t// Check header\n\t\tfor (let i = 0; i < token.header.length; i++) {\n\t\t\tconst headerText = this.renderInlineTokens(token.header[i].tokens || []);\n\t\t\tconst width = visibleWidth(headerText);\n\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t}\n\n\t\t// Check rows\n\t\tfor (const row of token.rows) {\n\t\t\tfor (let i = 0; i < row.length; i++) {\n\t\t\t\tconst cellText = this.renderInlineTokens(row[i].tokens || []);\n\t\t\t\tconst width = visibleWidth(cellText);\n\t\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t\t}\n\t\t}\n\n\t\t// Limit column widths to reasonable max\n\t\tconst maxColWidth = 40;\n\t\tfor (let i = 0; i < columnWidths.length; i++) {\n\t\t\tcolumnWidths[i] = Math.min(columnWidths[i], maxColWidth);\n\t\t}\n\n\t\t// Render header\n\t\tconst headerCells = token.header.map((cell, i) => {\n\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\treturn chalk.bold(text.padEnd(columnWidths[i]));\n\t\t});\n\t\tlines.push(\"│ \" + headerCells.join(\" │ \") + \" │\");\n\n\t\t// Render separator\n\t\tconst separatorCells = columnWidths.map((width) => \"─\".repeat(width));\n\t\tlines.push(\"├─\" + separatorCells.join(\"─┼─\") + \"─┤\");\n\n\t\t// Render rows\n\t\tfor (const row of token.rows) {\n\t\t\tconst rowCells = row.map((cell, i) => {\n\t\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\t\tconst visWidth = visibleWidth(text);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, columnWidths[i] - visWidth));\n\t\t\t\treturn text + padding;\n\t\t\t});\n\t\t\tlines.push(\"│ \" + rowCells.join(\" │ \") + \" │\");\n\t\t}\n\n\t\tlines.push(\"\"); // Add spacing after table\n\t\treturn lines;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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","sourcesContent":["import { Chalk } from \"chalk\";\nimport { marked, type Token } from \"marked\";\nimport type { Component } from \"../tui.js\";\nimport { visibleWidth } from \"../utils.js\";\n\n// Use a chalk instance with color level 3 for consistent ANSI output\nconst colorChalk = new Chalk({ level: 3 });\n\n/**\n * Default text styling for markdown content.\n * Applied to all text unless overridden by markdown formatting.\n */\nexport interface DefaultTextStyle {\n\t/** Foreground color - named color or hex string like \"#ff0000\" */\n\tcolor?: string;\n\t/** Background color - named color or hex string like \"#ff0000\" */\n\tbgColor?: string;\n\t/** Bold text */\n\tbold?: boolean;\n\t/** Italic text */\n\titalic?: boolean;\n\t/** Strikethrough text */\n\tstrikethrough?: boolean;\n\t/** Underline text */\n\tunderline?: boolean;\n}\n\nexport class Markdown implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate defaultTextStyle?: DefaultTextStyle;\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(text: string = \"\", paddingX: number = 1, paddingY: number = 1, defaultTextStyle?: DefaultTextStyle) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.defaultTextStyle = defaultTextStyle;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\t// Invalidate cache when text changes\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Check cache\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\t// Calculate available width for content (subtract horizontal padding)\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\t// Don't render anything if there's no actual text\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\t// Update cache\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\t// Replace tabs with 3 spaces for consistent rendering\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Parse markdown to HTML-like tokens\n\t\tconst tokens = marked.lexer(normalizedText);\n\n\t\t// Convert tokens to styled terminal output\n\t\tconst renderedLines: string[] = [];\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tconst nextToken = tokens[i + 1];\n\t\t\tconst tokenLines = this.renderToken(token, contentWidth, nextToken?.type);\n\t\t\trenderedLines.push(...tokenLines);\n\t\t}\n\n\t\t// Wrap lines to fit content width\n\t\tconst wrappedLines: string[] = [];\n\t\tfor (const line of renderedLines) {\n\t\t\twrappedLines.push(...this.wrapLine(line, contentWidth));\n\t\t}\n\n\t\t// Add padding and apply background color if specified\n\t\tconst leftPad = \" \".repeat(this.paddingX);\n\t\tconst paddedLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\t// Calculate visible length\n\t\t\tconst visibleLength = visibleWidth(line);\n\t\t\t// Right padding to fill to width (accounting for left padding and content)\n\t\t\tconst rightPadLength = Math.max(0, width - this.paddingX - visibleLength);\n\t\t\tconst rightPad = \" \".repeat(rightPadLength);\n\n\t\t\t// Add left padding, content, and right padding\n\t\t\tlet paddedLine = leftPad + line + rightPad;\n\n\t\t\t// Apply background color to entire line if specified\n\t\t\tif (this.defaultTextStyle?.bgColor) {\n\t\t\t\tpaddedLine = this.applyBgColor(paddedLine);\n\t\t\t}\n\n\t\t\tpaddedLines.push(paddedLine);\n\t\t}\n\n\t\t// Add top padding (empty lines)\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst topPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst paddedEmptyLine = this.defaultTextStyle?.bgColor ? this.applyBgColor(emptyLine) : emptyLine;\n\t\t\ttopPadding.push(paddedEmptyLine);\n\t\t}\n\n\t\t// Add bottom padding (empty lines)\n\t\tconst bottomPadding: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst paddedEmptyLine = this.defaultTextStyle?.bgColor ? this.applyBgColor(emptyLine) : emptyLine;\n\t\t\tbottomPadding.push(paddedEmptyLine);\n\t\t}\n\n\t\t// Combine top padding, content, and bottom padding\n\t\tconst result = [...topPadding, ...paddedLines, ...bottomPadding];\n\n\t\t// Update cache\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n\n\t/**\n\t * Apply only background color from default style.\n\t * Used for padding lines that don't have text content.\n\t */\n\tprivate applyBgColor(text: string): string {\n\t\tif (!this.defaultTextStyle?.bgColor) {\n\t\t\treturn text;\n\t\t}\n\n\t\tif (this.defaultTextStyle.bgColor.startsWith(\"#\")) {\n\t\t\t// Hex color\n\t\t\tconst hex = this.defaultTextStyle.bgColor.substring(1);\n\t\t\tconst r = Number.parseInt(hex.substring(0, 2), 16);\n\t\t\tconst g = Number.parseInt(hex.substring(2, 4), 16);\n\t\t\tconst b = Number.parseInt(hex.substring(4, 6), 16);\n\t\t\treturn colorChalk.bgRgb(r, g, b)(text);\n\t\t}\n\t\t// Named background color (bgRed, bgBlue, etc.)\n\t\treturn (colorChalk as any)[this.defaultTextStyle.bgColor](text);\n\t}\n\n\t/**\n\t * Apply default text style to a string.\n\t * This is the base styling applied to all text content.\n\t */\n\tprivate applyDefaultStyle(text: string): string {\n\t\tif (!this.defaultTextStyle) {\n\t\t\treturn text;\n\t\t}\n\n\t\tlet styled = text;\n\n\t\t// Apply color\n\t\tif (this.defaultTextStyle.color) {\n\t\t\tif (this.defaultTextStyle.color.startsWith(\"#\")) {\n\t\t\t\t// Hex color\n\t\t\t\tconst hex = this.defaultTextStyle.color.substring(1);\n\t\t\t\tconst r = Number.parseInt(hex.substring(0, 2), 16);\n\t\t\t\tconst g = Number.parseInt(hex.substring(2, 4), 16);\n\t\t\t\tconst b = Number.parseInt(hex.substring(4, 6), 16);\n\t\t\t\tstyled = colorChalk.rgb(r, g, b)(styled);\n\t\t\t} else {\n\t\t\t\t// Named color\n\t\t\t\tstyled = (colorChalk as any)[this.defaultTextStyle.color](styled);\n\t\t\t}\n\t\t}\n\n\t\t// Apply background color\n\t\tif (this.defaultTextStyle.bgColor) {\n\t\t\tif (this.defaultTextStyle.bgColor.startsWith(\"#\")) {\n\t\t\t\t// Hex color\n\t\t\t\tconst hex = this.defaultTextStyle.bgColor.substring(1);\n\t\t\t\tconst r = Number.parseInt(hex.substring(0, 2), 16);\n\t\t\t\tconst g = Number.parseInt(hex.substring(2, 4), 16);\n\t\t\t\tconst b = Number.parseInt(hex.substring(4, 6), 16);\n\t\t\t\tstyled = colorChalk.bgRgb(r, g, b)(styled);\n\t\t\t} else {\n\t\t\t\t// Named background color (bgRed, bgBlue, etc.)\n\t\t\t\tstyled = (colorChalk as any)[this.defaultTextStyle.bgColor](styled);\n\t\t\t}\n\t\t}\n\n\t\t// Apply text decorations\n\t\tif (this.defaultTextStyle.bold) {\n\t\t\tstyled = colorChalk.bold(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.italic) {\n\t\t\tstyled = colorChalk.italic(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.strikethrough) {\n\t\t\tstyled = colorChalk.strikethrough(styled);\n\t\t}\n\t\tif (this.defaultTextStyle.underline) {\n\t\t\tstyled = colorChalk.underline(styled);\n\t\t}\n\n\t\treturn styled;\n\t}\n\n\tprivate renderToken(token: Token, width: number, nextTokenType?: string): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tswitch (token.type) {\n\t\t\tcase \"heading\": {\n\t\t\t\tconst headingLevel = token.depth;\n\t\t\t\tconst headingPrefix = \"#\".repeat(headingLevel) + \" \";\n\t\t\t\tconst headingText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tif (headingLevel === 1) {\n\t\t\t\t\tlines.push(colorChalk.bold.underline.yellow(headingText));\n\t\t\t\t} else if (headingLevel === 2) {\n\t\t\t\t\tlines.push(colorChalk.bold.yellow(headingText));\n\t\t\t\t} else {\n\t\t\t\t\tlines.push(colorChalk.bold(headingPrefix + headingText));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after headings\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"paragraph\": {\n\t\t\t\tconst paragraphText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(paragraphText);\n\t\t\t\t// Don't add spacing if next token is space or list\n\t\t\t\tif (nextTokenType && nextTokenType !== \"list\" && nextTokenType !== \"space\") {\n\t\t\t\t\tlines.push(\"\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"code\": {\n\t\t\t\tlines.push(colorChalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\t// Split code by newlines and style each line\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(colorChalk.dim(\" \") + colorChalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(colorChalk.gray(\"```\"));\n\t\t\t\tlines.push(\"\"); // Add spacing after code blocks\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst listLines = this.renderList(token as any, 0);\n\t\t\t\tlines.push(...listLines);\n\t\t\t\t// Don't add spacing after lists if a space token follows\n\t\t\t\t// (the space token will handle it)\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"table\": {\n\t\t\t\tconst tableLines = this.renderTable(token as any);\n\t\t\t\tlines.push(...tableLines);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"blockquote\": {\n\t\t\t\tconst quoteText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tconst quoteLines = quoteText.split(\"\\n\");\n\t\t\t\tfor (const quoteLine of quoteLines) {\n\t\t\t\t\tlines.push(colorChalk.gray(\"│ \") + colorChalk.italic(quoteLine));\n\t\t\t\t}\n\t\t\t\tlines.push(\"\"); // Add spacing after blockquotes\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"hr\":\n\t\t\t\tlines.push(colorChalk.gray(\"─\".repeat(Math.min(width, 80))));\n\t\t\t\tlines.push(\"\"); // Add spacing after horizontal rules\n\t\t\t\tbreak;\n\n\t\t\tcase \"html\":\n\t\t\t\t// Skip HTML for terminal output\n\t\t\t\tbreak;\n\n\t\t\tcase \"space\":\n\t\t\t\t// Space tokens represent blank lines in markdown\n\t\t\t\tlines.push(\"\");\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t// Handle any other token types as plain text\n\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\tlines.push(token.text);\n\t\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\tprivate renderInlineTokens(tokens: Token[]): string {\n\t\tlet result = \"\";\n\n\t\tfor (const token of tokens) {\n\t\t\tswitch (token.type) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\t// Text tokens in list items can have nested tokens for inline formatting\n\t\t\t\t\tif (token.tokens && token.tokens.length > 0) {\n\t\t\t\t\t\tresult += this.renderInlineTokens(token.tokens);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Apply default style to plain text\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"strong\": {\n\t\t\t\t\t// Apply bold, then reapply default style after\n\t\t\t\t\tconst boldContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += colorChalk.bold(boldContent) + this.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"em\": {\n\t\t\t\t\t// Apply italic, then reapply default style after\n\t\t\t\t\tconst italicContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += colorChalk.italic(italicContent) + this.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"codespan\":\n\t\t\t\t\t// Apply code styling, then reapply default style after\n\t\t\t\t\tresult +=\n\t\t\t\t\t\tcolorChalk.gray(\"`\") +\n\t\t\t\t\t\tcolorChalk.cyan(token.text) +\n\t\t\t\t\t\tcolorChalk.gray(\"`\") +\n\t\t\t\t\t\tthis.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"link\": {\n\t\t\t\t\tconst linkText = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\t// If link text matches href, only show the link once\n\t\t\t\t\tif (linkText === token.href) {\n\t\t\t\t\t\tresult += colorChalk.underline.blue(linkText) + this.applyDefaultStyle(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult +=\n\t\t\t\t\t\t\tcolorChalk.underline.blue(linkText) +\n\t\t\t\t\t\t\tcolorChalk.gray(` (${token.href})`) +\n\t\t\t\t\t\t\tthis.applyDefaultStyle(\"\");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"br\":\n\t\t\t\t\tresult += \"\\n\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"del\": {\n\t\t\t\t\tconst delContent = this.renderInlineTokens(token.tokens || []);\n\t\t\t\t\tresult += colorChalk.strikethrough(delContent) + this.applyDefaultStyle(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\t// Handle any other inline token types as plain text\n\t\t\t\t\tif (\"text\" in token && typeof token.text === \"string\") {\n\t\t\t\t\t\tresult += this.applyDefaultStyle(token.text);\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate wrapLine(line: string, width: number): string[] {\n\t\t// Handle ANSI escape codes properly when wrapping\n\t\tconst wrapped: string[] = [];\n\n\t\t// Handle undefined or null lines\n\t\tif (!line) {\n\t\t\treturn [\"\"];\n\t\t}\n\n\t\t// Split by newlines first - wrap each line individually\n\t\tconst splitLines = line.split(\"\\n\");\n\t\tfor (const splitLine of splitLines) {\n\t\t\tconst visibleLength = visibleWidth(splitLine);\n\n\t\t\tif (visibleLength <= width) {\n\t\t\t\twrapped.push(splitLine);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// This line needs wrapping\n\t\t\twrapped.push(...this.wrapSingleLine(splitLine, width));\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\tprivate wrapSingleLine(line: string, width: number): string[] {\n\t\tconst wrapped: string[] = [];\n\n\t\t// Track active ANSI codes to preserve them across wrapped lines\n\t\tconst activeAnsiCodes: string[] = [];\n\t\tlet currentLine = \"\";\n\t\tlet currentLength = 0;\n\t\tlet i = 0;\n\n\t\twhile (i < line.length) {\n\t\t\tif (line[i] === \"\\x1b\" && line[i + 1] === \"[\") {\n\t\t\t\t// ANSI escape sequence - parse and track it\n\t\t\t\tlet j = i + 2;\n\t\t\t\twhile (j < line.length && line[j] && !/[mGKHJ]/.test(line[j]!)) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\tif (j < line.length) {\n\t\t\t\t\tconst ansiCode = line.substring(i, j + 1);\n\t\t\t\t\tcurrentLine += ansiCode;\n\n\t\t\t\t\t// Track styling codes (ending with 'm')\n\t\t\t\t\tif (line[j] === \"m\") {\n\t\t\t\t\t\t// Reset code\n\t\t\t\t\t\tif (ansiCode === \"\\x1b[0m\" || ansiCode === \"\\x1b[m\") {\n\t\t\t\t\t\t\tactiveAnsiCodes.length = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Add to active codes (replacing similar ones)\n\t\t\t\t\t\t\tactiveAnsiCodes.push(ansiCode);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ti = j + 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Incomplete ANSI sequence at end - don't include it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Regular character - extract full grapheme cluster\n\t\t\t\t// Handle multi-byte characters (emoji, surrogate pairs, etc.)\n\t\t\t\tlet char: string;\n\t\t\t\tlet charByteLength: number;\n\n\t\t\t\t// Check for surrogate pair (emoji and other multi-byte chars)\n\t\t\t\tconst codePoint = line.charCodeAt(i);\n\t\t\t\tif (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < line.length) {\n\t\t\t\t\t// High surrogate - get the pair\n\t\t\t\t\tchar = line.substring(i, i + 2);\n\t\t\t\t\tcharByteLength = 2;\n\t\t\t\t} else {\n\t\t\t\t\t// Regular character\n\t\t\t\t\tchar = line[i];\n\t\t\t\t\tcharByteLength = 1;\n\t\t\t\t}\n\n\t\t\t\tconst charWidth = visibleWidth(char);\n\n\t\t\t\t// Check if adding this character would exceed width\n\t\t\t\tif (currentLength + charWidth > width) {\n\t\t\t\t\t// Need to wrap - close current line with reset if needed\n\t\t\t\t\tif (activeAnsiCodes.length > 0) {\n\t\t\t\t\t\twrapped.push(currentLine + \"\\x1b[0m\");\n\t\t\t\t\t\t// Start new line with active codes\n\t\t\t\t\t\tcurrentLine = activeAnsiCodes.join(\"\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\twrapped.push(currentLine);\n\t\t\t\t\t\tcurrentLine = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tcurrentLength = 0;\n\t\t\t\t}\n\n\t\t\t\tcurrentLine += char;\n\t\t\t\tcurrentLength += charWidth;\n\t\t\t\ti += charByteLength;\n\t\t\t}\n\t\t}\n\n\t\tif (currentLine) {\n\t\t\twrapped.push(currentLine);\n\t\t}\n\n\t\treturn wrapped.length > 0 ? wrapped : [\"\"];\n\t}\n\n\t/**\n\t * Render a list with proper nesting support\n\t */\n\tprivate renderList(token: Token & { items: any[]; ordered: boolean }, depth: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tconst indent = \" \".repeat(depth);\n\n\t\tfor (let i = 0; i < token.items.length; i++) {\n\t\t\tconst item = token.items[i];\n\t\t\tconst bullet = token.ordered ? `${i + 1}. ` : \"- \";\n\n\t\t\t// Process item tokens to handle nested lists\n\t\t\tconst itemLines = this.renderListItem(item.tokens || [], depth);\n\n\t\t\tif (itemLines.length > 0) {\n\t\t\t\t// First line - check if it's a nested list\n\t\t\t\t// A nested list will start with indent (spaces) followed by cyan bullet\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = /^\\s+\\x1b\\[36m[-\\d]/.test(firstLine); // starts with spaces + cyan + bullet char\n\n\t\t\t\tif (isNestedList) {\n\t\t\t\t\t// This is a nested list, just add it as-is (already has full indent)\n\t\t\t\t\tlines.push(firstLine);\n\t\t\t\t} else {\n\t\t\t\t\t// Regular text content - add indent and bullet\n\t\t\t\t\tlines.push(indent + colorChalk.cyan(bullet) + firstLine);\n\t\t\t\t}\n\n\t\t\t\t// Rest of the lines\n\t\t\t\tfor (let j = 1; j < itemLines.length; j++) {\n\t\t\t\t\tconst line = itemLines[j];\n\t\t\t\t\tconst isNestedListLine = /^\\s+\\x1b\\[36m[-\\d]/.test(line); // starts with spaces + cyan + bullet char\n\n\t\t\t\t\tif (isNestedListLine) {\n\t\t\t\t\t\t// Nested list line - already has full indent\n\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Regular content - add parent indent + 2 spaces for continuation\n\t\t\t\t\t\tlines.push(indent + \" \" + line);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlines.push(indent + colorChalk.cyan(bullet));\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render list item tokens, handling nested lists\n\t * Returns lines WITHOUT the parent indent (renderList will add it)\n\t */\n\tprivate renderListItem(tokens: Token[], parentDepth: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tfor (const token of tokens) {\n\t\t\tif (token.type === \"list\") {\n\t\t\t\t// Nested list - render with one additional indent level\n\t\t\t\t// These lines will have their own indent, so we just add them as-is\n\t\t\t\tconst nestedLines = this.renderList(token as any, parentDepth + 1);\n\t\t\t\tlines.push(...nestedLines);\n\t\t\t} else if (token.type === \"text\") {\n\t\t\t\t// Text content (may have inline tokens)\n\t\t\t\tconst text =\n\t\t\t\t\ttoken.tokens && token.tokens.length > 0 ? this.renderInlineTokens(token.tokens) : token.text || \"\";\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"paragraph\") {\n\t\t\t\t// Paragraph in list item\n\t\t\t\tconst text = this.renderInlineTokens(token.tokens || []);\n\t\t\t\tlines.push(text);\n\t\t\t} else if (token.type === \"code\") {\n\t\t\t\t// Code block in list item\n\t\t\t\tlines.push(colorChalk.gray(\"```\" + (token.lang || \"\")));\n\t\t\t\tconst codeLines = token.text.split(\"\\n\");\n\t\t\t\tfor (const codeLine of codeLines) {\n\t\t\t\t\tlines.push(colorChalk.dim(\" \") + colorChalk.green(codeLine));\n\t\t\t\t}\n\t\t\t\tlines.push(colorChalk.gray(\"```\"));\n\t\t\t} else {\n\t\t\t\t// Other token types - try to render as inline\n\t\t\t\tconst text = this.renderInlineTokens([token]);\n\t\t\t\tif (text) {\n\t\t\t\t\tlines.push(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn lines;\n\t}\n\n\t/**\n\t * Render a table\n\t */\n\tprivate renderTable(token: Token & { header: any[]; rows: any[][] }): string[] {\n\t\tconst lines: string[] = [];\n\n\t\t// Calculate column widths\n\t\tconst columnWidths: number[] = [];\n\n\t\t// Check header\n\t\tfor (let i = 0; i < token.header.length; i++) {\n\t\t\tconst headerText = this.renderInlineTokens(token.header[i].tokens || []);\n\t\t\tconst width = visibleWidth(headerText);\n\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t}\n\n\t\t// Check rows\n\t\tfor (const row of token.rows) {\n\t\t\tfor (let i = 0; i < row.length; i++) {\n\t\t\t\tconst cellText = this.renderInlineTokens(row[i].tokens || []);\n\t\t\t\tconst width = visibleWidth(cellText);\n\t\t\t\tcolumnWidths[i] = Math.max(columnWidths[i] || 0, width);\n\t\t\t}\n\t\t}\n\n\t\t// Limit column widths to reasonable max\n\t\tconst maxColWidth = 40;\n\t\tfor (let i = 0; i < columnWidths.length; i++) {\n\t\t\tcolumnWidths[i] = Math.min(columnWidths[i], maxColWidth);\n\t\t}\n\n\t\t// Render header\n\t\tconst headerCells = token.header.map((cell, i) => {\n\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\treturn colorChalk.bold(text.padEnd(columnWidths[i]));\n\t\t});\n\t\tlines.push(\"│ \" + headerCells.join(\" │ \") + \" │\");\n\n\t\t// Render separator\n\t\tconst separatorCells = columnWidths.map((width) => \"─\".repeat(width));\n\t\tlines.push(\"├─\" + separatorCells.join(\"─┼─\") + \"─┤\");\n\n\t\t// Render rows\n\t\tfor (const row of token.rows) {\n\t\t\tconst rowCells = row.map((cell, i) => {\n\t\t\t\tconst text = this.renderInlineTokens(cell.tokens || []);\n\t\t\t\tconst visWidth = visibleWidth(text);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, columnWidths[i] - visWidth));\n\t\t\t\treturn text + padding;\n\t\t\t});\n\t\t\tlines.push(\"│ \" + rowCells.join(\" │ \") + \" │\");\n\t\t}\n\n\t\tlines.push(\"\"); // Add spacing after table\n\t\treturn lines;\n\t}\n}\n"]}
|
package/package.json
CHANGED