@mariozechner/pi-tui 0.7.2 → 0.7.7
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 +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;IA6ClB;;;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 (contains cyan ANSI code for bullets)\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = firstLine.includes(\"\\x1b[36m\"); // cyan color code\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 = line.includes(\"\\x1b[36m\"); // cyan bullet color\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;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"]}
|
|
@@ -374,9 +374,10 @@ export class Markdown {
|
|
|
374
374
|
// Process item tokens to handle nested lists
|
|
375
375
|
const itemLines = this.renderListItem(item.tokens || [], depth);
|
|
376
376
|
if (itemLines.length > 0) {
|
|
377
|
-
// First line - check if it's a nested list
|
|
377
|
+
// First line - check if it's a nested list
|
|
378
|
+
// A nested list will start with indent (spaces) followed by cyan bullet
|
|
378
379
|
const firstLine = itemLines[0];
|
|
379
|
-
const isNestedList =
|
|
380
|
+
const isNestedList = /^\s+\x1b\[36m[-\d]/.test(firstLine); // starts with spaces + cyan + bullet char
|
|
380
381
|
if (isNestedList) {
|
|
381
382
|
// This is a nested list, just add it as-is (already has full indent)
|
|
382
383
|
lines.push(firstLine);
|
|
@@ -388,7 +389,7 @@ export class Markdown {
|
|
|
388
389
|
// Rest of the lines
|
|
389
390
|
for (let j = 1; j < itemLines.length; j++) {
|
|
390
391
|
const line = itemLines[j];
|
|
391
|
-
const isNestedListLine =
|
|
392
|
+
const isNestedListLine = /^\s+\x1b\[36m[-\d]/.test(line); // starts with spaces + cyan + bullet char
|
|
392
393
|
if (isNestedListLine) {
|
|
393
394
|
// Nested list line - already has full indent
|
|
394
395
|
lines.push(line);
|
|
@@ -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 (contains cyan ANSI code for bullets)\n\t\t\t\tconst firstLine = itemLines[0];\n\t\t\t\tconst isNestedList = firstLine.includes(\"\\x1b[36m\"); // cyan color code\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 = line.includes(\"\\x1b[36m\"); // cyan bullet color\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\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"]}
|
package/package.json
CHANGED