@elizaos/tui 2.0.0-alpha.10

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.
Files changed (140) hide show
  1. package/README.md +761 -0
  2. package/dist/autocomplete.d.ts +48 -0
  3. package/dist/autocomplete.d.ts.map +1 -0
  4. package/dist/autocomplete.js +555 -0
  5. package/dist/components/box.d.ts +22 -0
  6. package/dist/components/box.d.ts.map +1 -0
  7. package/dist/components/box.js +103 -0
  8. package/dist/components/cancellable-loader.d.ts +22 -0
  9. package/dist/components/cancellable-loader.d.ts.map +1 -0
  10. package/dist/components/cancellable-loader.js +34 -0
  11. package/dist/components/editor/history.d.ts +38 -0
  12. package/dist/components/editor/history.d.ts.map +1 -0
  13. package/dist/components/editor/history.js +76 -0
  14. package/dist/components/editor/index.d.ts +18 -0
  15. package/dist/components/editor/index.d.ts.map +1 -0
  16. package/dist/components/editor/index.js +21 -0
  17. package/dist/components/editor/kill-ring.d.ts +41 -0
  18. package/dist/components/editor/kill-ring.d.ts.map +1 -0
  19. package/dist/components/editor/kill-ring.js +81 -0
  20. package/dist/components/editor/layout.d.ts +40 -0
  21. package/dist/components/editor/layout.d.ts.map +1 -0
  22. package/dist/components/editor/layout.js +205 -0
  23. package/dist/components/editor/types.d.ts +68 -0
  24. package/dist/components/editor/types.d.ts.map +1 -0
  25. package/dist/components/editor/types.js +4 -0
  26. package/dist/components/editor/undo.d.ts +46 -0
  27. package/dist/components/editor/undo.d.ts.map +1 -0
  28. package/dist/components/editor/undo.js +58 -0
  29. package/dist/components/editor.d.ts +196 -0
  30. package/dist/components/editor.d.ts.map +1 -0
  31. package/dist/components/editor.js +1707 -0
  32. package/dist/components/image.d.ts +28 -0
  33. package/dist/components/image.d.ts.map +1 -0
  34. package/dist/components/image.js +68 -0
  35. package/dist/components/input.d.ts +19 -0
  36. package/dist/components/input.d.ts.map +1 -0
  37. package/dist/components/input.js +195 -0
  38. package/dist/components/loader.d.ts +21 -0
  39. package/dist/components/loader.d.ts.map +1 -0
  40. package/dist/components/loader.js +49 -0
  41. package/dist/components/markdown/index.d.ts +13 -0
  42. package/dist/components/markdown/index.d.ts.map +1 -0
  43. package/dist/components/markdown/index.js +9 -0
  44. package/dist/components/markdown/inline-renderer.d.ts +22 -0
  45. package/dist/components/markdown/inline-renderer.d.ts.map +1 -0
  46. package/dist/components/markdown/inline-renderer.js +88 -0
  47. package/dist/components/markdown/list-renderer.d.ts +33 -0
  48. package/dist/components/markdown/list-renderer.d.ts.map +1 -0
  49. package/dist/components/markdown/list-renderer.js +110 -0
  50. package/dist/components/markdown/table-renderer.d.ts +43 -0
  51. package/dist/components/markdown/table-renderer.d.ts.map +1 -0
  52. package/dist/components/markdown/table-renderer.js +184 -0
  53. package/dist/components/markdown/types.d.ts +57 -0
  54. package/dist/components/markdown/types.d.ts.map +1 -0
  55. package/dist/components/markdown/types.js +13 -0
  56. package/dist/components/markdown.d.ts +44 -0
  57. package/dist/components/markdown.d.ts.map +1 -0
  58. package/dist/components/markdown.js +319 -0
  59. package/dist/components/progress-bar.d.ts +67 -0
  60. package/dist/components/progress-bar.d.ts.map +1 -0
  61. package/dist/components/progress-bar.js +124 -0
  62. package/dist/components/select-list.d.ts +32 -0
  63. package/dist/components/select-list.d.ts.map +1 -0
  64. package/dist/components/select-list.js +151 -0
  65. package/dist/components/settings-list.d.ts +50 -0
  66. package/dist/components/settings-list.d.ts.map +1 -0
  67. package/dist/components/settings-list.js +184 -0
  68. package/dist/components/spacer.d.ts +12 -0
  69. package/dist/components/spacer.d.ts.map +1 -0
  70. package/dist/components/spacer.js +22 -0
  71. package/dist/components/text.d.ts +19 -0
  72. package/dist/components/text.d.ts.map +1 -0
  73. package/dist/components/text.js +88 -0
  74. package/dist/components/toast.d.ts +73 -0
  75. package/dist/components/toast.d.ts.map +1 -0
  76. package/dist/components/toast.js +119 -0
  77. package/dist/components/truncated-text.d.ts +13 -0
  78. package/dist/components/truncated-text.d.ts.map +1 -0
  79. package/dist/components/truncated-text.js +50 -0
  80. package/dist/constants.d.ts +97 -0
  81. package/dist/constants.d.ts.map +1 -0
  82. package/dist/constants.js +126 -0
  83. package/dist/core/container.d.ts +32 -0
  84. package/dist/core/container.d.ts.map +1 -0
  85. package/dist/core/container.js +49 -0
  86. package/dist/core/index.d.ts +9 -0
  87. package/dist/core/index.d.ts.map +1 -0
  88. package/dist/core/index.js +10 -0
  89. package/dist/core/overlay.d.ts +44 -0
  90. package/dist/core/overlay.d.ts.map +1 -0
  91. package/dist/core/overlay.js +171 -0
  92. package/dist/core/types.d.ts +116 -0
  93. package/dist/core/types.d.ts.map +1 -0
  94. package/dist/core/types.js +14 -0
  95. package/dist/editor-component.d.ts +37 -0
  96. package/dist/editor-component.d.ts.map +1 -0
  97. package/dist/editor-component.js +1 -0
  98. package/dist/fuzzy.d.ts +16 -0
  99. package/dist/fuzzy.d.ts.map +1 -0
  100. package/dist/fuzzy.js +108 -0
  101. package/dist/index.d.ts +29 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +59 -0
  104. package/dist/keybindings.d.ts +39 -0
  105. package/dist/keybindings.d.ts.map +1 -0
  106. package/dist/keybindings.js +113 -0
  107. package/dist/keys.d.ts +153 -0
  108. package/dist/keys.d.ts.map +1 -0
  109. package/dist/keys.js +951 -0
  110. package/dist/stdin-buffer.d.ts +48 -0
  111. package/dist/stdin-buffer.d.ts.map +1 -0
  112. package/dist/stdin-buffer.js +316 -0
  113. package/dist/terminal-image.d.ts +68 -0
  114. package/dist/terminal-image.d.ts.map +1 -0
  115. package/dist/terminal-image.js +287 -0
  116. package/dist/terminal.d.ts +71 -0
  117. package/dist/terminal.d.ts.map +1 -0
  118. package/dist/terminal.js +216 -0
  119. package/dist/themes/index.d.ts +103 -0
  120. package/dist/themes/index.d.ts.map +1 -0
  121. package/dist/themes/index.js +161 -0
  122. package/dist/tui.d.ts +90 -0
  123. package/dist/tui.d.ts.map +1 -0
  124. package/dist/tui.js +745 -0
  125. package/dist/types/marked-tokens.d.ts +57 -0
  126. package/dist/types/marked-tokens.d.ts.map +1 -0
  127. package/dist/types/marked-tokens.js +17 -0
  128. package/dist/utils/cursor-movement.d.ts +127 -0
  129. package/dist/utils/cursor-movement.d.ts.map +1 -0
  130. package/dist/utils/cursor-movement.js +251 -0
  131. package/dist/utils/index.d.ts +6 -0
  132. package/dist/utils/index.d.ts.map +1 -0
  133. package/dist/utils/index.js +7 -0
  134. package/dist/utils/paste-handler.d.ts +86 -0
  135. package/dist/utils/paste-handler.d.ts.map +1 -0
  136. package/dist/utils/paste-handler.js +121 -0
  137. package/dist/utils.d.ts +75 -0
  138. package/dist/utils.d.ts.map +1 -0
  139. package/dist/utils.js +796 -0
  140. package/package.json +53 -0
@@ -0,0 +1,110 @@
1
+ /**
2
+ * List rendering utilities for Markdown component.
3
+ */
4
+ /**
5
+ * Render a list with proper nesting support.
6
+ *
7
+ * @param token - The list token to render
8
+ * @param depth - Current nesting depth (0 for top-level)
9
+ * @param context - Rendering context with theme and inline renderer
10
+ * @returns Array of rendered lines
11
+ */
12
+ export function renderList(token, depth, context) {
13
+ const lines = [];
14
+ const indent = " ".repeat(depth);
15
+ // Use the list's start property (defaults to 1 for ordered lists)
16
+ const startNumber = typeof token.start === "number" ? token.start : 1;
17
+ for (let i = 0; i < token.items.length; i++) {
18
+ const item = token.items[i];
19
+ const bullet = token.ordered ? `${startNumber + i}. ` : "- ";
20
+ // Process item tokens to handle nested lists
21
+ const itemLines = renderListItem(item.tokens || [], depth, context);
22
+ if (itemLines.length > 0) {
23
+ // First line - check if it's a nested list
24
+ // A nested list will start with indent (spaces) followed by cyan bullet
25
+ const firstLine = itemLines[0];
26
+ const isNestedList = /^\s+\x1b\[36m[-\d]/.test(firstLine); // starts with spaces + cyan + bullet char
27
+ if (isNestedList) {
28
+ // This is a nested list, just add it as-is (already has full indent)
29
+ lines.push(firstLine);
30
+ }
31
+ else {
32
+ // Regular text content - add indent and bullet
33
+ lines.push(indent + context.theme.listBullet(bullet) + firstLine);
34
+ }
35
+ // Rest of the lines
36
+ for (let j = 1; j < itemLines.length; j++) {
37
+ const line = itemLines[j];
38
+ const isNestedListLine = /^\s+\x1b\[36m[-\d]/.test(line); // starts with spaces + cyan + bullet char
39
+ if (isNestedListLine) {
40
+ // Nested list line - already has full indent
41
+ lines.push(line);
42
+ }
43
+ else {
44
+ // Regular content - add parent indent + 2 spaces for continuation
45
+ lines.push(`${indent} ${line}`);
46
+ }
47
+ }
48
+ }
49
+ else {
50
+ lines.push(indent + context.theme.listBullet(bullet));
51
+ }
52
+ }
53
+ return lines;
54
+ }
55
+ /**
56
+ * Render list item tokens, handling nested lists.
57
+ * Returns lines WITHOUT the parent indent (renderList will add it).
58
+ *
59
+ * @param tokens - Tokens from the list item
60
+ * @param parentDepth - Depth of the parent list
61
+ * @param context - Rendering context with theme and inline renderer
62
+ * @returns Array of rendered lines
63
+ */
64
+ export function renderListItem(tokens, parentDepth, context) {
65
+ const lines = [];
66
+ for (const token of tokens) {
67
+ if (token.type === "list") {
68
+ // Nested list - render with one additional indent level
69
+ // These lines will have their own indent, so we just add them as-is
70
+ const nestedLines = renderList(token, parentDepth + 1, context);
71
+ lines.push(...nestedLines);
72
+ }
73
+ else if (token.type === "text") {
74
+ // Text content (may have inline tokens)
75
+ const text = token.tokens && token.tokens.length > 0 ? context.renderInlineTokens(token.tokens) : token.text || "";
76
+ lines.push(text);
77
+ }
78
+ else if (token.type === "paragraph") {
79
+ // Paragraph in list item
80
+ const text = context.renderInlineTokens(token.tokens || []);
81
+ lines.push(text);
82
+ }
83
+ else if (token.type === "code") {
84
+ // Code block in list item
85
+ const indent = context.theme.codeBlockIndent ?? " ";
86
+ lines.push(context.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
87
+ if (context.theme.highlightCode) {
88
+ const highlightedLines = context.theme.highlightCode(token.text, token.lang);
89
+ for (const hlLine of highlightedLines) {
90
+ lines.push(`${indent}${hlLine}`);
91
+ }
92
+ }
93
+ else {
94
+ const codeLines = token.text.split("\n");
95
+ for (const codeLine of codeLines) {
96
+ lines.push(`${indent}${context.theme.codeBlock(codeLine)}`);
97
+ }
98
+ }
99
+ lines.push(context.theme.codeBlockBorder("```"));
100
+ }
101
+ else {
102
+ // Other token types - try to render as inline
103
+ const text = context.renderInlineTokens([token]);
104
+ if (text) {
105
+ lines.push(text);
106
+ }
107
+ }
108
+ }
109
+ return lines;
110
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Table rendering utilities for Markdown component.
3
+ */
4
+ import type { Token } from "marked";
5
+ import type { TableToken } from "../../types/marked-tokens.js";
6
+ import type { InlineStyleContext, MarkdownTheme } from "./types.js";
7
+ /**
8
+ * Context for table rendering operations.
9
+ */
10
+ export interface TableRenderContext {
11
+ theme: MarkdownTheme;
12
+ renderInlineTokens: (tokens: Token[], styleContext?: InlineStyleContext) => string;
13
+ }
14
+ /**
15
+ * Get the visible width of the longest word in a string.
16
+ *
17
+ * @param text - Text to analyze
18
+ * @param maxWidth - Optional maximum width to cap the result
19
+ * @returns Width of the longest word (or maxWidth if exceeded)
20
+ */
21
+ export declare function getLongestWordWidth(text: string, maxWidth?: number): number;
22
+ /**
23
+ * Wrap a table cell to fit into a column.
24
+ *
25
+ * Delegates to wrapTextWithAnsi() so ANSI codes + long tokens are handled
26
+ * consistently with the rest of the renderer.
27
+ *
28
+ * @param text - Cell text to wrap
29
+ * @param maxWidth - Maximum width for wrapping
30
+ * @returns Array of wrapped lines
31
+ */
32
+ export declare function wrapCellText(text: string, maxWidth: number): string[];
33
+ /**
34
+ * Render a table with width-aware cell wrapping.
35
+ * Cells that don't fit are wrapped to multiple lines.
36
+ *
37
+ * @param token - The table token to render
38
+ * @param availableWidth - Available width for the table
39
+ * @param context - Rendering context with theme and inline renderer
40
+ * @returns Array of rendered lines
41
+ */
42
+ export declare function renderTable(token: TableToken, availableWidth: number, context: TableRenderContext): string[];
43
+ //# sourceMappingURL=table-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-renderer.d.ts","sourceRoot":"","sources":["../../../src/components/markdown/table-renderer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,kBAAkB,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,YAAY,CAAC,EAAE,kBAAkB,KAAK,MAAM,CAAC;CACnF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAU3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAErE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAgK5G"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Table rendering utilities for Markdown component.
3
+ */
4
+ import { visibleWidth, wrapTextWithAnsi } from "../../utils.js";
5
+ /**
6
+ * Get the visible width of the longest word in a string.
7
+ *
8
+ * @param text - Text to analyze
9
+ * @param maxWidth - Optional maximum width to cap the result
10
+ * @returns Width of the longest word (or maxWidth if exceeded)
11
+ */
12
+ export function getLongestWordWidth(text, maxWidth) {
13
+ const words = text.split(/\s+/).filter((word) => word.length > 0);
14
+ let longest = 0;
15
+ for (const word of words) {
16
+ longest = Math.max(longest, visibleWidth(word));
17
+ }
18
+ if (maxWidth === undefined) {
19
+ return longest;
20
+ }
21
+ return Math.min(longest, maxWidth);
22
+ }
23
+ /**
24
+ * Wrap a table cell to fit into a column.
25
+ *
26
+ * Delegates to wrapTextWithAnsi() so ANSI codes + long tokens are handled
27
+ * consistently with the rest of the renderer.
28
+ *
29
+ * @param text - Cell text to wrap
30
+ * @param maxWidth - Maximum width for wrapping
31
+ * @returns Array of wrapped lines
32
+ */
33
+ export function wrapCellText(text, maxWidth) {
34
+ return wrapTextWithAnsi(text, Math.max(1, maxWidth));
35
+ }
36
+ /**
37
+ * Render a table with width-aware cell wrapping.
38
+ * Cells that don't fit are wrapped to multiple lines.
39
+ *
40
+ * @param token - The table token to render
41
+ * @param availableWidth - Available width for the table
42
+ * @param context - Rendering context with theme and inline renderer
43
+ * @returns Array of rendered lines
44
+ */
45
+ export function renderTable(token, availableWidth, context) {
46
+ const lines = [];
47
+ const numCols = token.header.length;
48
+ if (numCols === 0) {
49
+ return lines;
50
+ }
51
+ // Calculate border overhead: "│ " + (n-1) * " │ " + " │"
52
+ // = 2 + (n-1) * 3 + 2 = 3n + 1
53
+ const borderOverhead = 3 * numCols + 1;
54
+ const availableForCells = availableWidth - borderOverhead;
55
+ if (availableForCells < numCols) {
56
+ // Too narrow to render a stable table. Fall back to raw markdown.
57
+ const fallbackLines = token.raw ? wrapTextWithAnsi(token.raw, availableWidth) : [];
58
+ fallbackLines.push("");
59
+ return fallbackLines;
60
+ }
61
+ const maxUnbrokenWordWidth = 30;
62
+ // Calculate natural column widths (what each column needs without constraints)
63
+ const naturalWidths = [];
64
+ const minWordWidths = [];
65
+ for (let i = 0; i < numCols; i++) {
66
+ const headerText = context.renderInlineTokens(token.header[i].tokens || []);
67
+ naturalWidths[i] = visibleWidth(headerText);
68
+ minWordWidths[i] = Math.max(1, getLongestWordWidth(headerText, maxUnbrokenWordWidth));
69
+ }
70
+ for (const row of token.rows) {
71
+ for (let i = 0; i < row.length; i++) {
72
+ const cellText = context.renderInlineTokens(row[i].tokens || []);
73
+ naturalWidths[i] = Math.max(naturalWidths[i] || 0, visibleWidth(cellText));
74
+ minWordWidths[i] = Math.max(minWordWidths[i] || 1, getLongestWordWidth(cellText, maxUnbrokenWordWidth));
75
+ }
76
+ }
77
+ let minColumnWidths = minWordWidths;
78
+ let minCellsWidth = minColumnWidths.reduce((a, b) => a + b, 0);
79
+ if (minCellsWidth > availableForCells) {
80
+ minColumnWidths = new Array(numCols).fill(1);
81
+ const remaining = availableForCells - numCols;
82
+ if (remaining > 0) {
83
+ const totalWeight = minWordWidths.reduce((total, width) => total + Math.max(0, width - 1), 0);
84
+ const growth = minWordWidths.map((width) => {
85
+ const weight = Math.max(0, width - 1);
86
+ return totalWeight > 0 ? Math.floor((weight / totalWeight) * remaining) : 0;
87
+ });
88
+ for (let i = 0; i < numCols; i++) {
89
+ minColumnWidths[i] += growth[i];
90
+ }
91
+ const allocated = growth.reduce((total, width) => total + width, 0);
92
+ let leftover = remaining - allocated;
93
+ for (let i = 0; leftover > 0 && i < numCols; i++) {
94
+ minColumnWidths[i]++;
95
+ leftover--;
96
+ }
97
+ }
98
+ minCellsWidth = minColumnWidths.reduce((a, b) => a + b, 0);
99
+ }
100
+ // Calculate column widths that fit within available width
101
+ const totalNaturalWidth = naturalWidths.reduce((a, b) => a + b, 0) + borderOverhead;
102
+ let columnWidths;
103
+ if (totalNaturalWidth <= availableWidth) {
104
+ // Everything fits naturally
105
+ columnWidths = naturalWidths.map((width, index) => Math.max(width, minColumnWidths[index]));
106
+ }
107
+ else {
108
+ // Need to shrink columns to fit
109
+ const totalGrowPotential = naturalWidths.reduce((total, width, index) => {
110
+ return total + Math.max(0, width - minColumnWidths[index]);
111
+ }, 0);
112
+ const extraWidth = Math.max(0, availableForCells - minCellsWidth);
113
+ columnWidths = minColumnWidths.map((minWidth, index) => {
114
+ const naturalWidth = naturalWidths[index];
115
+ const minWidthDelta = Math.max(0, naturalWidth - minWidth);
116
+ let grow = 0;
117
+ if (totalGrowPotential > 0) {
118
+ grow = Math.floor((minWidthDelta / totalGrowPotential) * extraWidth);
119
+ }
120
+ return minWidth + grow;
121
+ });
122
+ // Adjust for rounding errors - distribute remaining space
123
+ const allocated = columnWidths.reduce((a, b) => a + b, 0);
124
+ let remaining = availableForCells - allocated;
125
+ while (remaining > 0) {
126
+ let grew = false;
127
+ for (let i = 0; i < numCols && remaining > 0; i++) {
128
+ if (columnWidths[i] < naturalWidths[i]) {
129
+ columnWidths[i]++;
130
+ remaining--;
131
+ grew = true;
132
+ }
133
+ }
134
+ if (!grew) {
135
+ break;
136
+ }
137
+ }
138
+ }
139
+ // Render top border
140
+ const topBorderCells = columnWidths.map((w) => "─".repeat(w));
141
+ lines.push(`┌─${topBorderCells.join("─┬─")}─┐`);
142
+ // Render header with wrapping
143
+ const headerCellLines = token.header.map((cell, i) => {
144
+ const text = context.renderInlineTokens(cell.tokens || []);
145
+ return wrapCellText(text, columnWidths[i]);
146
+ });
147
+ const headerLineCount = Math.max(...headerCellLines.map((c) => c.length));
148
+ for (let lineIdx = 0; lineIdx < headerLineCount; lineIdx++) {
149
+ const rowParts = headerCellLines.map((cellLines, colIdx) => {
150
+ const text = cellLines[lineIdx] || "";
151
+ const padded = text + " ".repeat(Math.max(0, columnWidths[colIdx] - visibleWidth(text)));
152
+ return context.theme.bold(padded);
153
+ });
154
+ lines.push(`│ ${rowParts.join(" │ ")} │`);
155
+ }
156
+ // Render separator
157
+ const separatorCells = columnWidths.map((w) => "─".repeat(w));
158
+ const separatorLine = `├─${separatorCells.join("─┼─")}─┤`;
159
+ lines.push(separatorLine);
160
+ // Render rows with wrapping
161
+ for (let rowIndex = 0; rowIndex < token.rows.length; rowIndex++) {
162
+ const row = token.rows[rowIndex];
163
+ const rowCellLines = row.map((cell, i) => {
164
+ const text = context.renderInlineTokens(cell.tokens || []);
165
+ return wrapCellText(text, columnWidths[i]);
166
+ });
167
+ const rowLineCount = Math.max(...rowCellLines.map((c) => c.length));
168
+ for (let lineIdx = 0; lineIdx < rowLineCount; lineIdx++) {
169
+ const rowParts = rowCellLines.map((cellLines, colIdx) => {
170
+ const text = cellLines[lineIdx] || "";
171
+ return text + " ".repeat(Math.max(0, columnWidths[colIdx] - visibleWidth(text)));
172
+ });
173
+ lines.push(`│ ${rowParts.join(" │ ")} │`);
174
+ }
175
+ if (rowIndex < token.rows.length - 1) {
176
+ lines.push(separatorLine);
177
+ }
178
+ }
179
+ // Render bottom border
180
+ const bottomBorderCells = columnWidths.map((w) => "─".repeat(w));
181
+ lines.push(`└─${bottomBorderCells.join("─┴─")}─┘`);
182
+ lines.push(""); // Add spacing after table
183
+ return lines;
184
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Type definitions for the Markdown component.
3
+ */
4
+ /**
5
+ * Default text styling for markdown content.
6
+ * Applied to all text unless overridden by markdown formatting.
7
+ */
8
+ export interface DefaultTextStyle {
9
+ /** Foreground color function */
10
+ color?: (text: string) => string;
11
+ /** Background color function */
12
+ bgColor?: (text: string) => string;
13
+ /** Bold text */
14
+ bold?: boolean;
15
+ /** Italic text */
16
+ italic?: boolean;
17
+ /** Strikethrough text */
18
+ strikethrough?: boolean;
19
+ /** Underline text */
20
+ underline?: boolean;
21
+ }
22
+ /**
23
+ * Theme functions for markdown elements.
24
+ * Each function takes text and returns styled text with ANSI codes.
25
+ */
26
+ export interface MarkdownTheme {
27
+ heading: (text: string) => string;
28
+ link: (text: string) => string;
29
+ linkUrl: (text: string) => string;
30
+ code: (text: string) => string;
31
+ codeBlock: (text: string) => string;
32
+ codeBlockBorder: (text: string) => string;
33
+ quote: (text: string) => string;
34
+ quoteBorder: (text: string) => string;
35
+ hr: (text: string) => string;
36
+ listBullet: (text: string) => string;
37
+ bold: (text: string) => string;
38
+ italic: (text: string) => string;
39
+ strikethrough: (text: string) => string;
40
+ underline: (text: string) => string;
41
+ highlightCode?: (code: string, lang?: string) => string[];
42
+ /** Prefix applied to each rendered code block line (default: " ") */
43
+ codeBlockIndent?: string;
44
+ }
45
+ /**
46
+ * Context for inline token rendering, carrying style functions and prefixes.
47
+ */
48
+ export interface InlineStyleContext {
49
+ applyText: (text: string) => string;
50
+ stylePrefix: string;
51
+ }
52
+ /**
53
+ * Get the style prefix from a styling function.
54
+ * Uses a sentinel character to extract the ANSI prefix codes.
55
+ */
56
+ export declare function getStylePrefix(styleFn: (text: string) => string): string;
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/markdown/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,gCAAgC;IAChC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,gCAAgC;IAChC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,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;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IAC1D,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAKxE"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Type definitions for the Markdown component.
3
+ */
4
+ /**
5
+ * Get the style prefix from a styling function.
6
+ * Uses a sentinel character to extract the ANSI prefix codes.
7
+ */
8
+ export function getStylePrefix(styleFn) {
9
+ const sentinel = "\u0000";
10
+ const styled = styleFn(sentinel);
11
+ const sentinelIndex = styled.indexOf(sentinel);
12
+ return sentinelIndex >= 0 ? styled.slice(0, sentinelIndex) : "";
13
+ }
@@ -0,0 +1,44 @@
1
+ import type { Component } from "../tui.js";
2
+ export type { DefaultTextStyle, InlineStyleContext, MarkdownTheme } from "./markdown/types.js";
3
+ import type { DefaultTextStyle, MarkdownTheme } from "./markdown/types.js";
4
+ export declare class Markdown implements Component {
5
+ private text;
6
+ private paddingX;
7
+ private paddingY;
8
+ private defaultTextStyle?;
9
+ private theme;
10
+ private defaultStylePrefix?;
11
+ private cachedText?;
12
+ private cachedWidth?;
13
+ private cachedLines?;
14
+ constructor(text: string, paddingX: number, paddingY: number, theme: MarkdownTheme, defaultTextStyle?: DefaultTextStyle);
15
+ setText(text: string): void;
16
+ invalidate(): void;
17
+ render(width: number): string[];
18
+ /**
19
+ * Apply default text style to a string.
20
+ * This is the base styling applied to all text content.
21
+ * NOTE: Background color is NOT applied here - it's applied at the padding stage
22
+ * to ensure it extends to the full line width.
23
+ */
24
+ private applyDefaultStyle;
25
+ private getDefaultStylePrefix;
26
+ private getDefaultInlineStyleContext;
27
+ private renderToken;
28
+ /**
29
+ * Render inline tokens to styled text.
30
+ * Delegates to the extracted inline-renderer utility.
31
+ */
32
+ private renderInlineTokens;
33
+ /**
34
+ * Render a list with proper nesting support.
35
+ * Delegates to the extracted list-renderer utility.
36
+ */
37
+ private renderList;
38
+ /**
39
+ * Render a table with width-aware cell wrapping.
40
+ * Delegates to the extracted table-renderer utility.
41
+ */
42
+ private renderTable;
43
+ }
44
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +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;AAe3C,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE3E,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;IAC5C,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,kBAAkB,CAAC,CAAS;IAGpC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;gBAG9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,EACpB,gBAAgB,CAAC,EAAE,gBAAgB;IASpC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK3B,UAAU,IAAI,IAAI;IAMlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAwF/B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,WAAW;IA2HnB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;OAGG;IACH,OAAO,CAAC,UAAU;IAQlB;;;OAGG;IACH,OAAO,CAAC,WAAW;CAOnB"}