@dungle-scrubs/tallow 0.9.4 → 0.9.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.
Files changed (212) hide show
  1. package/dist/cli.js +8 -5
  2. package/dist/cli.js.map +1 -1
  3. package/dist/config.d.ts +1 -1
  4. package/dist/config.js +1 -1
  5. package/dist/interactive-mode-patch.d.ts +24 -12
  6. package/dist/interactive-mode-patch.d.ts.map +1 -1
  7. package/dist/interactive-mode-patch.js +229 -146
  8. package/dist/interactive-mode-patch.js.map +1 -1
  9. package/dist/interactive-reset.d.ts +49 -0
  10. package/dist/interactive-reset.d.ts.map +1 -0
  11. package/dist/interactive-reset.js +40 -0
  12. package/dist/interactive-reset.js.map +1 -0
  13. package/dist/pi-tui-editor-patch.d.ts +10 -0
  14. package/dist/pi-tui-editor-patch.d.ts.map +1 -0
  15. package/dist/pi-tui-editor-patch.js +159 -0
  16. package/dist/pi-tui-editor-patch.js.map +1 -0
  17. package/dist/pi-tui-patch.d.ts +2 -0
  18. package/dist/pi-tui-patch.d.ts.map +1 -0
  19. package/dist/pi-tui-patch.js +563 -0
  20. package/dist/pi-tui-patch.js.map +1 -0
  21. package/dist/pi-tui-settings-list-patch.d.ts +11 -0
  22. package/dist/pi-tui-settings-list-patch.d.ts.map +1 -0
  23. package/dist/pi-tui-settings-list-patch.js +38 -0
  24. package/dist/pi-tui-settings-list-patch.js.map +1 -0
  25. package/dist/process-cleanup.js +1 -1
  26. package/dist/process-cleanup.js.map +1 -1
  27. package/dist/reset-diagnostics.d.ts +69 -0
  28. package/dist/reset-diagnostics.d.ts.map +1 -0
  29. package/dist/reset-diagnostics.js +41 -0
  30. package/dist/reset-diagnostics.js.map +1 -0
  31. package/dist/sdk.d.ts +7 -23
  32. package/dist/sdk.d.ts.map +1 -1
  33. package/dist/sdk.js +211 -174
  34. package/dist/sdk.js.map +1 -1
  35. package/dist/workspace-transition-interactive.d.ts +1 -0
  36. package/dist/workspace-transition-interactive.d.ts.map +1 -1
  37. package/dist/workspace-transition-interactive.js +8 -18
  38. package/dist/workspace-transition-interactive.js.map +1 -1
  39. package/extensions/__integration__/audit-findings.test.ts +4 -5
  40. package/extensions/_icons/index.ts +2 -4
  41. package/extensions/_shared/__tests__/image-metadata.test.ts +33 -0
  42. package/extensions/_shared/__tests__/shell-policy.test.ts +19 -0
  43. package/extensions/_shared/__tests__/terminal-links.test.ts +18 -0
  44. package/extensions/_shared/image-metadata.ts +99 -0
  45. package/extensions/_shared/inline-preview.ts +1 -1
  46. package/extensions/_shared/shell-policy.ts +121 -1
  47. package/extensions/_shared/terminal-links.ts +22 -0
  48. package/extensions/ask-user-question-tool/index.ts +0 -3
  49. package/extensions/clear/__tests__/clear.test.ts +269 -2
  50. package/extensions/command-expansion/index.ts +9 -3
  51. package/extensions/context-files/index.ts +5 -1
  52. package/extensions/context-fork/__tests__/context-fork.test.ts +94 -1
  53. package/extensions/context-fork/extension.json +1 -1
  54. package/extensions/context-fork/frontmatter-index.ts +6 -1
  55. package/extensions/context-fork/index.ts +32 -0
  56. package/extensions/edit-tool-enhanced/index.ts +2 -1
  57. package/extensions/git-status/__tests__/git-status.test.ts +65 -2
  58. package/extensions/git-status/index.ts +268 -98
  59. package/extensions/hooks/index.ts +33 -11
  60. package/extensions/loop/index.ts +14 -1
  61. package/extensions/lsp/index.ts +64 -13
  62. package/extensions/lsp/package.json +2 -2
  63. package/extensions/minimal-skill-display/index.ts +7 -1
  64. package/extensions/random-spinner/index.ts +7 -642
  65. package/extensions/read-tool-enhanced/index.ts +13 -10
  66. package/extensions/render-stabilizer/__tests__/render-stabilizer.test.ts +2 -3
  67. package/extensions/render-stabilizer/index.ts +6 -6
  68. package/extensions/rewind/__tests__/session-files.test.ts +115 -0
  69. package/extensions/rewind/__tests__/snapshots.test.ts +23 -0
  70. package/extensions/rewind/index.ts +5 -0
  71. package/extensions/rewind/session-files.ts +138 -0
  72. package/extensions/rewind/snapshots.ts +104 -5
  73. package/extensions/skill-commands/index.ts +6 -1
  74. package/extensions/slash-command-bridge/__tests__/slash-command-bridge.test.ts +26 -0
  75. package/extensions/slash-command-bridge/index.ts +14 -2
  76. package/extensions/subagent-tool/model-resolver.ts +274 -7
  77. package/extensions/subagent-tool/schema.ts +1 -2
  78. package/extensions/tasks/commands/register-tasks-extension.ts +9 -9
  79. package/extensions/teams-tool/tools/register-extension.ts +1 -3
  80. package/extensions/teams-tool/tools/teammate-tools.ts +1 -2
  81. package/extensions/web-search-tool/index.ts +2 -1
  82. package/extensions/wezterm-pane-control/index.ts +1 -2
  83. package/extensions/write-tool-enhanced/index.ts +2 -1
  84. package/node_modules/@mariozechner/pi-tui/README.md +56 -34
  85. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts +18 -13
  86. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts.map +1 -1
  87. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js +182 -113
  88. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js.map +1 -1
  89. package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js +3 -3
  90. package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js.map +1 -1
  91. package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts +45 -36
  92. package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts.map +1 -1
  93. package/node_modules/@mariozechner/pi-tui/dist/components/editor.js +489 -325
  94. package/node_modules/@mariozechner/pi-tui/dist/components/editor.js.map +1 -1
  95. package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts +1 -99
  96. package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts.map +1 -1
  97. package/node_modules/@mariozechner/pi-tui/dist/components/image.js +17 -192
  98. package/node_modules/@mariozechner/pi-tui/dist/components/image.js.map +1 -1
  99. package/node_modules/@mariozechner/pi-tui/dist/components/input.d.ts.map +1 -1
  100. package/node_modules/@mariozechner/pi-tui/dist/components/input.js +57 -60
  101. package/node_modules/@mariozechner/pi-tui/dist/components/input.js.map +1 -1
  102. package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts +2 -69
  103. package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts.map +1 -1
  104. package/node_modules/@mariozechner/pi-tui/dist/components/loader.js +5 -102
  105. package/node_modules/@mariozechner/pi-tui/dist/components/loader.js.map +1 -1
  106. package/node_modules/@mariozechner/pi-tui/dist/components/markdown.d.ts.map +1 -1
  107. package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js +111 -53
  108. package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js.map +1 -1
  109. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts +19 -1
  110. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts.map +1 -1
  111. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js +78 -67
  112. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js.map +1 -1
  113. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts +1 -25
  114. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts.map +1 -1
  115. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js +13 -50
  116. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js.map +1 -1
  117. package/node_modules/@mariozechner/pi-tui/dist/index.d.ts +8 -10
  118. package/node_modules/@mariozechner/pi-tui/dist/index.d.ts.map +1 -1
  119. package/node_modules/@mariozechner/pi-tui/dist/index.js +6 -9
  120. package/node_modules/@mariozechner/pi-tui/dist/index.js.map +1 -1
  121. package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts +108 -238
  122. package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts.map +1 -1
  123. package/node_modules/@mariozechner/pi-tui/dist/keybindings.js +108 -365
  124. package/node_modules/@mariozechner/pi-tui/dist/keybindings.js.map +1 -1
  125. package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts +33 -48
  126. package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts.map +1 -1
  127. package/node_modules/@mariozechner/pi-tui/dist/keys.js +239 -155
  128. package/node_modules/@mariozechner/pi-tui/dist/keys.js.map +1 -1
  129. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts +14 -94
  130. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts.map +1 -1
  131. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js +44 -186
  132. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js.map +1 -1
  133. package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts +13 -58
  134. package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts.map +1 -1
  135. package/node_modules/@mariozechner/pi-tui/dist/terminal.js +78 -111
  136. package/node_modules/@mariozechner/pi-tui/dist/terminal.js.map +1 -1
  137. package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts +24 -110
  138. package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts.map +1 -1
  139. package/node_modules/@mariozechner/pi-tui/dist/tui.js +188 -435
  140. package/node_modules/@mariozechner/pi-tui/dist/tui.js.map +1 -1
  141. package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts +0 -18
  142. package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts.map +1 -1
  143. package/node_modules/@mariozechner/pi-tui/dist/utils.js +251 -119
  144. package/node_modules/@mariozechner/pi-tui/dist/utils.js.map +1 -1
  145. package/node_modules/@mariozechner/pi-tui/package.json +6 -6
  146. package/node_modules/@mariozechner/pi-tui/src/__tests__/__snapshots__/render.test.ts.snap +3 -40
  147. package/node_modules/@mariozechner/pi-tui/src/__tests__/image-component.test.ts +71 -81
  148. package/node_modules/@mariozechner/pi-tui/src/__tests__/render.test.ts +0 -33
  149. package/node_modules/@mariozechner/pi-tui/src/__tests__/terminal-image.test.ts +93 -334
  150. package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-render-scheduling.test.ts +1 -1
  151. package/node_modules/@mariozechner/pi-tui/src/__tests__/utils.test.ts +11 -196
  152. package/node_modules/@mariozechner/pi-tui/src/autocomplete.ts +228 -142
  153. package/node_modules/@mariozechner/pi-tui/src/components/cancellable-loader.ts +3 -3
  154. package/node_modules/@mariozechner/pi-tui/src/components/editor.ts +624 -390
  155. package/node_modules/@mariozechner/pi-tui/src/components/image.ts +17 -227
  156. package/node_modules/@mariozechner/pi-tui/src/components/input.ts +71 -63
  157. package/node_modules/@mariozechner/pi-tui/src/components/loader.ts +5 -137
  158. package/node_modules/@mariozechner/pi-tui/src/components/markdown.ts +143 -52
  159. package/node_modules/@mariozechner/pi-tui/src/components/select-list.ts +136 -70
  160. package/node_modules/@mariozechner/pi-tui/src/components/settings-list.ts +12 -51
  161. package/node_modules/@mariozechner/pi-tui/src/index.ts +17 -36
  162. package/node_modules/@mariozechner/pi-tui/src/keybindings.ts +148 -421
  163. package/node_modules/@mariozechner/pi-tui/src/keys.ts +253 -181
  164. package/node_modules/@mariozechner/pi-tui/src/terminal-image.ts +51 -252
  165. package/node_modules/@mariozechner/pi-tui/src/terminal.ts +78 -133
  166. package/node_modules/@mariozechner/pi-tui/src/tui.ts +202 -478
  167. package/node_modules/@mariozechner/pi-tui/src/utils.ts +289 -125
  168. package/node_modules/@mariozechner/pi-tui/tsconfig.build.json +1 -0
  169. package/package.json +13 -13
  170. package/packages/tallow-tui/node_modules/@types/mime-types/README.md +8 -2
  171. package/packages/tallow-tui/node_modules/@types/mime-types/index.d.ts +6 -0
  172. package/packages/tallow-tui/node_modules/@types/mime-types/package.json +9 -3
  173. package/packages/tallow-tui/node_modules/get-east-asian-width/lookup-data.js +18 -0
  174. package/packages/tallow-tui/node_modules/get-east-asian-width/lookup.js +116 -384
  175. package/packages/tallow-tui/node_modules/get-east-asian-width/package.json +5 -4
  176. package/packages/tallow-tui/node_modules/get-east-asian-width/utilities.js +24 -0
  177. package/packages/tallow-tui/node_modules/marked/README.md +5 -4
  178. package/packages/tallow-tui/node_modules/marked/bin/main.js +10 -8
  179. package/packages/tallow-tui/node_modules/marked/bin/marked.js +2 -1
  180. package/packages/tallow-tui/node_modules/marked/lib/marked.d.ts +156 -125
  181. package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js +67 -2179
  182. package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js.map +3 -3
  183. package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js +67 -2201
  184. package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js.map +3 -3
  185. package/packages/tallow-tui/node_modules/marked/man/marked.1 +4 -2
  186. package/packages/tallow-tui/node_modules/marked/man/marked.1.md +2 -1
  187. package/packages/tallow-tui/node_modules/marked/package.json +26 -34
  188. package/skills/tallow-expert/SKILL.md +3 -5
  189. package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts +0 -32
  190. package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts.map +0 -1
  191. package/node_modules/@mariozechner/pi-tui/dist/border-styles.js +0 -46
  192. package/node_modules/@mariozechner/pi-tui/dist/border-styles.js.map +0 -1
  193. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts +0 -52
  194. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts.map +0 -1
  195. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js +0 -89
  196. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js.map +0 -1
  197. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts +0 -14
  198. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts.map +0 -1
  199. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js +0 -55
  200. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js.map +0 -1
  201. package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-change-listener.test.ts +0 -121
  202. package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-ghost-text.test.ts +0 -112
  203. package/node_modules/@mariozechner/pi-tui/src/__tests__/mouse-events.test.ts +0 -134
  204. package/node_modules/@mariozechner/pi-tui/src/__tests__/settings-list.test.ts +0 -81
  205. package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-diff-regression.test.ts +0 -555
  206. package/node_modules/@mariozechner/pi-tui/src/border-styles.ts +0 -60
  207. package/node_modules/@mariozechner/pi-tui/src/components/bordered-box.ts +0 -113
  208. package/node_modules/@mariozechner/pi-tui/src/test-utils/capability-env.ts +0 -56
  209. package/packages/tallow-tui/node_modules/marked/lib/marked.cjs +0 -2211
  210. package/packages/tallow-tui/node_modules/marked/lib/marked.cjs.map +0 -7
  211. package/packages/tallow-tui/node_modules/marked/lib/marked.d.cts +0 -728
  212. package/packages/tallow-tui/node_modules/marked/marked.min.js +0 -69
@@ -1,87 +1,20 @@
1
1
  import type { TUI } from "../tui.js";
2
2
  import { Text } from "./text.js";
3
- /** Optional configuration for the Loader's spinner appearance and timing. */
4
- export interface LoaderOptions {
5
- /** Spinner animation frames (defaults to braille dots). */
6
- frames?: string[];
7
- /** Animation interval in ms (default: 80). */
8
- intervalMs?: number;
9
- }
10
- /** Context passed to the message transform callback each tick. */
11
- export interface MessageTransformContext {
12
- /** The current message set on this Loader (from constructor or setMessage). */
13
- message: string;
14
- /** Monotonic tick counter — increments each animation frame for this instance. */
15
- tick: number;
16
- /** True if the message has not been changed via setMessage() since construction. */
17
- isInitialMessage: boolean;
18
- }
19
3
  /**
20
- * Loader component that updates with a spinning animation.
21
- *
22
- * @param ui - TUI instance for rendering
23
- * @param spinnerColorFn - Color function applied to the spinner frame
24
- * @param messageColorFn - Color function applied to the message text
25
- * @param message - Text shown next to the spinner (default: "Loading...")
26
- * @param options - Optional frames and interval override
4
+ * Loader component that updates every 80ms with spinning animation
27
5
  */
28
6
  export declare class Loader extends Text {
29
7
  private spinnerColorFn;
30
8
  private messageColorFn;
31
9
  private message;
32
10
  private frames;
33
- private intervalMs;
34
11
  private currentFrame;
35
12
  private intervalId;
36
- private _transformIntervalId;
37
13
  private ui;
38
- /** Per-instance tick counter for message transform animations. */
39
- private _transformTick;
40
- /** Tracks whether setMessage() has been called since construction. */
41
- private _messageChanged;
42
- constructor(ui: TUI, spinnerColorFn: (str: string) => string, messageColorFn: (str: string) => string, message?: string, options?: LoaderOptions);
43
- /**
44
- * Global default spinner frames — set once, applies to all new Loader instances.
45
- * Extensions can set this at session_start to override the braille default.
46
- */
47
- static defaultFrames: string[] | undefined;
48
- /**
49
- * Global default interval — set once, applies to all new Loader instances.
50
- */
51
- static defaultIntervalMs: number | undefined;
52
- /**
53
- * Global message transform — called each tick to modify the displayed message.
54
- * Extensions use this to animate or replace the loader text.
55
- * Return the string to display. The transform is applied before messageColorFn.
56
- */
57
- static defaultMessageTransform?: (ctx: MessageTransformContext) => string;
58
- /**
59
- * Interval (ms) for the message transform tick — independent of the spinner frame rate.
60
- * When set to a value faster than the spinner interval, a separate timer drives
61
- * the transform tick and re-renders, giving animations higher
62
- * frame rates without affecting the spinner animation speed.
63
- */
64
- static defaultTransformIntervalMs: number | undefined;
65
- /** Whether the loader is hidden (renders as empty space). */
66
- private hidden;
67
- /**
68
- * Hide the loader — renders nothing but keeps the interval alive.
69
- * Call show() to restore.
70
- */
71
- hide(): void;
72
- /**
73
- * Show the loader after a hide() call.
74
- */
75
- show(): void;
14
+ constructor(ui: TUI, spinnerColorFn: (str: string) => string, messageColorFn: (str: string) => string, message?: string);
76
15
  render(width: number): string[];
77
16
  start(): void;
78
17
  stop(): void;
79
- /** Sentinel value — pass to setWorkingMessage() to hide the loader. */
80
- static readonly HIDE = "\u200B";
81
- /**
82
- * Set the loader message. Pass Loader.HIDE to hide, any other string to show.
83
- * @param message - Message text or Loader.HIDE sentinel
84
- */
85
18
  setMessage(message: string): void;
86
19
  private updateDisplay;
87
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/components/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC7B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,kEAAkE;AAClE,MAAM,WAAW,uBAAuB;IACvC,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,oFAAoF;IACpF,gBAAgB,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,MAAO,SAAQ,IAAI;IAgB9B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,OAAO;IAjBhB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,oBAAoB,CAA+B;IAC3D,OAAO,CAAC,EAAE,CAAoB;IAE9B,kEAAkE;IAClE,OAAO,CAAC,cAAc,CAAK;IAE3B,sEAAsE;IACtE,OAAO,CAAC,eAAe,CAAS;gBAG/B,EAAE,EAAE,GAAG,EACC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EACvC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EACvC,OAAO,GAAE,MAAqB,EACtC,OAAO,CAAC,EAAE,aAAa;IASxB;;;OAGG;IACH,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAE3C;;OAEG;IACH,MAAM,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7C;;;;OAIG;IACH,MAAM,CAAC,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,uBAAuB,KAAK,MAAM,CAAC;IAE1E;;;;;OAKG;IACH,MAAM,CAAC,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IAEtD,6DAA6D;IAC7D,OAAO,CAAC,MAAM,CAAS;IAEvB;;;OAGG;IACH,IAAI;IAMJ;;OAEG;IACH,IAAI;IAKJ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAK/B,KAAK;IAwBL,IAAI;IAWJ,uEAAuE;IACvE,MAAM,CAAC,QAAQ,CAAC,IAAI,YAAY;IAEhC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM;IAW1B,OAAO,CAAC,aAAa;CAiBrB"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/components/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;GAEG;AACH,qBAAa,MAAO,SAAQ,IAAI;IAQ9B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,OAAO;IAThB,OAAO,CAAC,MAAM,CAAsD;IACpE,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,EAAE,CAAoB;gBAG7B,EAAE,EAAE,GAAG,EACC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EACvC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EACvC,OAAO,GAAE,MAAqB;IAOvC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAI/B,KAAK;IAQL,IAAI;IAOJ,UAAU,CAAC,OAAO,EAAE,MAAM;IAK1B,OAAO,CAAC,aAAa;CAOrB"}
@@ -1,143 +1,46 @@
1
1
  import { Text } from "./text.js";
2
- /** Default braille spinner frames used when no custom frames are provided. */
3
- const DEFAULT_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
4
- /** Default animation interval in milliseconds. */
5
- const DEFAULT_INTERVAL_MS = 80;
6
2
  /**
7
- * Loader component that updates with a spinning animation.
8
- *
9
- * @param ui - TUI instance for rendering
10
- * @param spinnerColorFn - Color function applied to the spinner frame
11
- * @param messageColorFn - Color function applied to the message text
12
- * @param message - Text shown next to the spinner (default: "Loading...")
13
- * @param options - Optional frames and interval override
3
+ * Loader component that updates every 80ms with spinning animation
14
4
  */
15
5
  export class Loader extends Text {
16
6
  spinnerColorFn;
17
7
  messageColorFn;
18
8
  message;
19
- frames;
20
- intervalMs;
9
+ frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
21
10
  currentFrame = 0;
22
11
  intervalId = null;
23
- _transformIntervalId = null;
24
12
  ui = null;
25
- /** Per-instance tick counter for message transform animations. */
26
- _transformTick = 0;
27
- /** Tracks whether setMessage() has been called since construction. */
28
- _messageChanged = false;
29
- constructor(ui, spinnerColorFn, messageColorFn, message = "Loading...", options) {
13
+ constructor(ui, spinnerColorFn, messageColorFn, message = "Loading...") {
30
14
  super("", 1, 0);
31
15
  this.spinnerColorFn = spinnerColorFn;
32
16
  this.messageColorFn = messageColorFn;
33
17
  this.message = message;
34
- this.frames = options?.frames ?? Loader.defaultFrames ?? DEFAULT_FRAMES;
35
- this.intervalMs = options?.intervalMs ?? Loader.defaultIntervalMs ?? DEFAULT_INTERVAL_MS;
36
18
  this.ui = ui;
37
19
  this.start();
38
20
  }
39
- /**
40
- * Global default spinner frames — set once, applies to all new Loader instances.
41
- * Extensions can set this at session_start to override the braille default.
42
- */
43
- static defaultFrames;
44
- /**
45
- * Global default interval — set once, applies to all new Loader instances.
46
- */
47
- static defaultIntervalMs;
48
- /**
49
- * Global message transform — called each tick to modify the displayed message.
50
- * Extensions use this to animate or replace the loader text.
51
- * Return the string to display. The transform is applied before messageColorFn.
52
- */
53
- static defaultMessageTransform;
54
- /**
55
- * Interval (ms) for the message transform tick — independent of the spinner frame rate.
56
- * When set to a value faster than the spinner interval, a separate timer drives
57
- * the transform tick and re-renders, giving animations higher
58
- * frame rates without affecting the spinner animation speed.
59
- */
60
- static defaultTransformIntervalMs;
61
- /** Whether the loader is hidden (renders as empty space). */
62
- hidden = false;
63
- /**
64
- * Hide the loader — renders nothing but keeps the interval alive.
65
- * Call show() to restore.
66
- */
67
- hide() {
68
- this.hidden = true;
69
- this.setText("");
70
- this.ui?.requestRender();
71
- }
72
- /**
73
- * Show the loader after a hide() call.
74
- */
75
- show() {
76
- this.hidden = false;
77
- this.updateDisplay();
78
- }
79
21
  render(width) {
80
- if (this.hidden)
81
- return [];
82
22
  return ["", ...super.render(width)];
83
23
  }
84
24
  start() {
85
25
  this.updateDisplay();
86
- const transformMs = Loader.defaultTransformIntervalMs;
87
- const hasFastTransform = Loader.defaultMessageTransform != null &&
88
- transformMs != null &&
89
- transformMs < this.intervalMs;
90
26
  this.intervalId = setInterval(() => {
91
27
  this.currentFrame = (this.currentFrame + 1) % this.frames.length;
92
- this._transformTick++;
93
28
  this.updateDisplay();
94
- }, this.intervalMs);
95
- // Separate faster interval for message transform re-renders only.
96
- // Does NOT advance _transformTick — just re-rolls random visuals.
97
- if (hasFastTransform) {
98
- this._transformIntervalId = setInterval(() => {
99
- this.updateDisplay();
100
- }, transformMs);
101
- }
29
+ }, 80);
102
30
  }
103
31
  stop() {
104
32
  if (this.intervalId) {
105
33
  clearInterval(this.intervalId);
106
34
  this.intervalId = null;
107
35
  }
108
- if (this._transformIntervalId) {
109
- clearInterval(this._transformIntervalId);
110
- this._transformIntervalId = null;
111
- }
112
36
  }
113
- /** Sentinel value — pass to setWorkingMessage() to hide the loader. */
114
- static HIDE = "\u200B";
115
- /**
116
- * Set the loader message. Pass Loader.HIDE to hide, any other string to show.
117
- * @param message - Message text or Loader.HIDE sentinel
118
- */
119
37
  setMessage(message) {
120
- if (message === Loader.HIDE) {
121
- this.hide();
122
- return;
123
- }
124
- if (this.hidden)
125
- this.show();
126
- this._messageChanged = true;
127
38
  this.message = message;
128
39
  this.updateDisplay();
129
40
  }
130
41
  updateDisplay() {
131
42
  const frame = this.frames[this.currentFrame];
132
- let displayMessage = this.message;
133
- if (Loader.defaultMessageTransform) {
134
- displayMessage = Loader.defaultMessageTransform({
135
- message: this.message,
136
- tick: this._transformTick,
137
- isInitialMessage: !this._messageChanged,
138
- });
139
- }
140
- this.setText(`${this.spinnerColorFn(frame)} ${this.messageColorFn(displayMessage)}`);
43
+ this.setText(`${this.spinnerColorFn(frame)} ${this.messageColorFn(this.message)}`);
141
44
  if (this.ui) {
142
45
  this.ui.requestRender();
143
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/components/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/components/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;GAEG;AACH,MAAM,OAAO,MAAO,SAAQ,IAAI;IAQtB;IACA;IACA;IATD,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5D,YAAY,GAAG,CAAC,CAAC;IACjB,UAAU,GAA0B,IAAI,CAAC;IACzC,EAAE,GAAe,IAAI,CAAC;IAE9B,YACC,EAAO,EACC,cAAuC,EACvC,cAAuC,EACvC,UAAkB,YAAY;QAEtC,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAJR,mBAAc,GAAd,cAAc,CAAyB;QACvC,mBAAc,GAAd,cAAc,CAAyB;QACvC,YAAO,GAAP,OAAO,CAAuB;QAGtC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,EAAE,CAAC;IACd,CAAC;IAED,MAAM,CAAC,KAAa;QACnB,OAAO,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YAClC,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACjE,IAAI,CAAC,aAAa,EAAE,CAAC;QACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IACR,CAAC;IAED,IAAI;QACH,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;IACF,CAAC;IAED,UAAU,CAAC,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,aAAa,EAAE,CAAC;IACtB,CAAC;IAEO,aAAa;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACnF,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;QACzB,CAAC;IACF,CAAC;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,26 @@
1
- import { marked } from "marked";
2
- import { isImageLine } from "../terminal-image.js";
1
+ import { Marked, Tokenizer } from "marked";
2
+ import { getCapabilities, hyperlink, isImageLine } from "../terminal-image.js";
3
3
  import { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from "../utils.js";
4
+ const STRICT_STRIKETHROUGH_REGEX = /^(~~)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/;
5
+ class StrictStrikethroughTokenizer extends Tokenizer {
6
+ del(src) {
7
+ const match = STRICT_STRIKETHROUGH_REGEX.exec(src);
8
+ if (!match) {
9
+ return undefined;
10
+ }
11
+ const text = match[2];
12
+ return {
13
+ type: "del",
14
+ raw: match[0],
15
+ text,
16
+ tokens: this.lexer.inlineTokens(text),
17
+ };
18
+ }
19
+ }
20
+ const markdownParser = new Marked();
21
+ markdownParser.setOptions({
22
+ tokenizer: new StrictStrikethroughTokenizer(),
23
+ });
4
24
  export class Markdown {
5
25
  text;
6
26
  paddingX; // Left/right padding
@@ -47,7 +67,7 @@ export class Markdown {
47
67
  // Replace tabs with 3 spaces for consistent rendering
48
68
  const normalizedText = this.text.replace(/\t/g, " ");
49
69
  // Parse markdown to HTML-like tokens
50
- const tokens = marked.lexer(normalizedText);
70
+ const tokens = markdownParser.lexer(normalizedText);
51
71
  // Convert tokens to styled terminal output
52
72
  const renderedLines = [];
53
73
  for (let i = 0; i < tokens.length; i++) {
@@ -172,31 +192,36 @@ export class Markdown {
172
192
  stylePrefix: this.getDefaultStylePrefix(),
173
193
  };
174
194
  }
175
- renderToken(token, width, nextTokenType) {
195
+ renderToken(token, width, nextTokenType, styleContext) {
176
196
  const lines = [];
177
197
  switch (token.type) {
178
198
  case "heading": {
179
199
  const headingLevel = token.depth;
180
200
  const headingPrefix = `${"#".repeat(headingLevel)} `;
181
- const headingText = this.renderInlineTokens(token.tokens || []);
182
- let styledHeading;
201
+ // Build a heading-specific style context so inline tokens (codespan, bold, etc.)
202
+ // restore heading styling after their own ANSI resets instead of falling back to
203
+ // the default text style.
204
+ let headingStyleFn;
183
205
  if (headingLevel === 1) {
184
- styledHeading = this.theme.heading(this.theme.bold(this.theme.underline(headingText)));
185
- }
186
- else if (headingLevel === 2) {
187
- styledHeading = this.theme.heading(this.theme.bold(headingText));
206
+ headingStyleFn = (text) => this.theme.heading(this.theme.bold(this.theme.underline(text)));
188
207
  }
189
208
  else {
190
- styledHeading = this.theme.heading(this.theme.bold(headingPrefix + headingText));
209
+ headingStyleFn = (text) => this.theme.heading(this.theme.bold(text));
191
210
  }
211
+ const headingStyleContext = {
212
+ applyText: headingStyleFn,
213
+ stylePrefix: this.getStylePrefix(headingStyleFn),
214
+ };
215
+ const headingText = this.renderInlineTokens(token.tokens || [], headingStyleContext);
216
+ const styledHeading = headingLevel >= 3 ? headingStyleFn(headingPrefix) + headingText : headingText;
192
217
  lines.push(styledHeading);
193
- if (nextTokenType !== "space") {
218
+ if (nextTokenType && nextTokenType !== "space") {
194
219
  lines.push(""); // Add spacing after headings (unless space token follows)
195
220
  }
196
221
  break;
197
222
  }
198
223
  case "paragraph": {
199
- const paragraphText = this.renderInlineTokens(token.tokens || []);
224
+ const paragraphText = this.renderInlineTokens(token.tokens || [], styleContext);
200
225
  lines.push(paragraphText);
201
226
  // Don't add spacing if next token is space or list
202
227
  if (nextTokenType && nextTokenType !== "list" && nextTokenType !== "space") {
@@ -221,48 +246,69 @@ export class Markdown {
221
246
  }
222
247
  }
223
248
  lines.push(this.theme.codeBlockBorder("```"));
224
- if (nextTokenType !== "space") {
249
+ if (nextTokenType && nextTokenType !== "space") {
225
250
  lines.push(""); // Add spacing after code blocks (unless space token follows)
226
251
  }
227
252
  break;
228
253
  }
229
254
  case "list": {
230
- const listLines = this.renderList(token, 0);
255
+ const listLines = this.renderList(token, 0, styleContext);
231
256
  lines.push(...listLines);
232
257
  // Don't add spacing after lists if a space token follows
233
258
  // (the space token will handle it)
234
259
  break;
235
260
  }
236
261
  case "table": {
237
- const tableLines = this.renderTable(token, width);
262
+ const tableLines = this.renderTable(token, width, nextTokenType, styleContext);
238
263
  lines.push(...tableLines);
239
264
  break;
240
265
  }
241
266
  case "blockquote": {
242
267
  const quoteStyle = (text) => this.theme.quote(this.theme.italic(text));
243
- const quoteStyleContext = {
244
- applyText: quoteStyle,
245
- stylePrefix: this.getStylePrefix(quoteStyle),
268
+ const quoteStylePrefix = this.getStylePrefix(quoteStyle);
269
+ const applyQuoteStyle = (line) => {
270
+ if (!quoteStylePrefix) {
271
+ return quoteStyle(line);
272
+ }
273
+ const lineWithReappliedStyle = line.replace(/\x1b\[0m/g, `\x1b[0m${quoteStylePrefix}`);
274
+ return quoteStyle(lineWithReappliedStyle);
246
275
  };
247
- const quoteText = this.renderInlineTokens(token.tokens || [], quoteStyleContext);
248
- const quoteLines = quoteText.split("\n");
249
276
  // Calculate available width for quote content (subtract border "│ " = 2 chars)
250
277
  const quoteContentWidth = Math.max(1, width - 2);
251
- for (const quoteLine of quoteLines) {
252
- // Wrap the styled line, then add border to each wrapped line
253
- const wrappedLines = wrapTextWithAnsi(quoteLine, quoteContentWidth);
278
+ // Blockquotes contain block-level tokens (paragraph, list, code, etc.), so render
279
+ // children with renderToken() instead of renderInlineTokens().
280
+ // Default message style should not apply inside blockquotes.
281
+ const quoteInlineStyleContext = {
282
+ applyText: (text) => text,
283
+ stylePrefix: quoteStylePrefix,
284
+ };
285
+ const quoteTokens = token.tokens || [];
286
+ const renderedQuoteLines = [];
287
+ for (let i = 0; i < quoteTokens.length; i++) {
288
+ const quoteToken = quoteTokens[i];
289
+ const nextQuoteToken = quoteTokens[i + 1];
290
+ renderedQuoteLines.push(...this.renderToken(quoteToken, quoteContentWidth, nextQuoteToken?.type, quoteInlineStyleContext));
291
+ }
292
+ // Avoid rendering an extra empty quote line before the outer blockquote spacing.
293
+ while (renderedQuoteLines.length > 0 &&
294
+ renderedQuoteLines[renderedQuoteLines.length - 1] === "") {
295
+ renderedQuoteLines.pop();
296
+ }
297
+ for (const quoteLine of renderedQuoteLines) {
298
+ const styledLine = applyQuoteStyle(quoteLine);
299
+ const wrappedLines = wrapTextWithAnsi(styledLine, quoteContentWidth);
254
300
  for (const wrappedLine of wrappedLines) {
255
301
  lines.push(this.theme.quoteBorder("│ ") + wrappedLine);
256
302
  }
257
303
  }
258
- if (nextTokenType !== "space") {
304
+ if (nextTokenType && nextTokenType !== "space") {
259
305
  lines.push(""); // Add spacing after blockquotes (unless space token follows)
260
306
  }
261
307
  break;
262
308
  }
263
309
  case "hr":
264
310
  lines.push(this.theme.hr("─".repeat(Math.min(width, 80))));
265
- if (nextTokenType !== "space") {
311
+ if (nextTokenType && nextTokenType !== "space") {
266
312
  lines.push(""); // Add spacing after horizontal rules (unless space token follows)
267
313
  }
268
314
  break;
@@ -322,21 +368,26 @@ export class Markdown {
322
368
  break;
323
369
  case "link": {
324
370
  const linkText = this.renderInlineTokens(token.tokens || [], resolvedStyleContext);
325
- // If link text matches href, only show the link once
326
- // Compare raw text (token.text) not styled text (linkText) since linkText has ANSI codes
327
- // For mailto: links, strip the prefix before comparing (autolinked emails have
328
- // text="foo@bar.com" but href="mailto:foo@bar.com")
329
- const hrefForComparison = token.href.startsWith("mailto:")
330
- ? token.href.slice(7)
331
- : token.href;
332
- if (token.text === token.href || token.text === hrefForComparison) {
333
- result += this.theme.link(this.theme.underline(linkText)) + stylePrefix;
371
+ const styledLink = this.theme.link(this.theme.underline(linkText));
372
+ if (getCapabilities().hyperlinks) {
373
+ // OSC 8: render as a clickable hyperlink. The URL is not printed inline,
374
+ // so we always show only the link text regardless of whether it matches href.
375
+ result += hyperlink(styledLink, token.href) + stylePrefix;
334
376
  }
335
377
  else {
336
- result +=
337
- this.theme.link(this.theme.underline(linkText)) +
338
- this.theme.linkUrl(` (${token.href})`) +
339
- stylePrefix;
378
+ // Fallback: print URL in parentheses when text differs from href.
379
+ // Compare raw token.text (not styled) against href for the equality check.
380
+ // For mailto: links strip the prefix (autolinked emails use text="foo@bar.com"
381
+ // but href="mailto:foo@bar.com").
382
+ const hrefForComparison = token.href.startsWith("mailto:")
383
+ ? token.href.slice(7)
384
+ : token.href;
385
+ if (token.text === token.href || token.text === hrefForComparison) {
386
+ result += styledLink + stylePrefix;
387
+ }
388
+ else {
389
+ result += styledLink + this.theme.linkUrl(` (${token.href})`) + stylePrefix;
390
+ }
340
391
  }
341
392
  break;
342
393
  }
@@ -361,12 +412,15 @@ export class Markdown {
361
412
  }
362
413
  }
363
414
  }
415
+ while (stylePrefix && result.endsWith(stylePrefix)) {
416
+ result = result.slice(0, -stylePrefix.length);
417
+ }
364
418
  return result;
365
419
  }
366
420
  /**
367
421
  * Render a list with proper nesting support
368
422
  */
369
- renderList(token, depth) {
423
+ renderList(token, depth, styleContext) {
370
424
  const lines = [];
371
425
  const indent = " ".repeat(depth);
372
426
  // Use the list's start property (defaults to 1 for ordered lists)
@@ -375,7 +429,7 @@ export class Markdown {
375
429
  const item = token.items[i];
376
430
  const bullet = token.ordered ? `${startNumber + i}. ` : "- ";
377
431
  // Process item tokens to handle nested lists
378
- const itemLines = this.renderListItem(item.tokens || [], depth);
432
+ const itemLines = this.renderListItem(item.tokens || [], depth, styleContext);
379
433
  if (itemLines.length > 0) {
380
434
  // First line - check if it's a nested list
381
435
  // A nested list will start with indent (spaces) followed by cyan bullet
@@ -413,25 +467,25 @@ export class Markdown {
413
467
  * Render list item tokens, handling nested lists
414
468
  * Returns lines WITHOUT the parent indent (renderList will add it)
415
469
  */
416
- renderListItem(tokens, parentDepth) {
470
+ renderListItem(tokens, parentDepth, styleContext) {
417
471
  const lines = [];
418
472
  for (const token of tokens) {
419
473
  if (token.type === "list") {
420
474
  // Nested list - render with one additional indent level
421
475
  // These lines will have their own indent, so we just add them as-is
422
- const nestedLines = this.renderList(token, parentDepth + 1);
476
+ const nestedLines = this.renderList(token, parentDepth + 1, styleContext);
423
477
  lines.push(...nestedLines);
424
478
  }
425
479
  else if (token.type === "text") {
426
480
  // Text content (may have inline tokens)
427
481
  const text = token.tokens && token.tokens.length > 0
428
- ? this.renderInlineTokens(token.tokens)
482
+ ? this.renderInlineTokens(token.tokens, styleContext)
429
483
  : token.text || "";
430
484
  lines.push(text);
431
485
  }
432
486
  else if (token.type === "paragraph") {
433
487
  // Paragraph in list item
434
- const text = this.renderInlineTokens(token.tokens || []);
488
+ const text = this.renderInlineTokens(token.tokens || [], styleContext);
435
489
  lines.push(text);
436
490
  }
437
491
  else if (token.type === "code") {
@@ -454,7 +508,7 @@ export class Markdown {
454
508
  }
455
509
  else {
456
510
  // Other token types - try to render as inline
457
- const text = this.renderInlineTokens([token]);
511
+ const text = this.renderInlineTokens([token], styleContext);
458
512
  if (text) {
459
513
  lines.push(text);
460
514
  }
@@ -489,7 +543,7 @@ export class Markdown {
489
543
  * Render a table with width-aware cell wrapping.
490
544
  * Cells that don't fit are wrapped to multiple lines.
491
545
  */
492
- renderTable(token, availableWidth) {
546
+ renderTable(token, availableWidth, nextTokenType, styleContext) {
493
547
  const lines = [];
494
548
  const numCols = token.header.length;
495
549
  if (numCols === 0) {
@@ -502,7 +556,9 @@ export class Markdown {
502
556
  if (availableForCells < numCols) {
503
557
  // Too narrow to render a stable table. Fall back to raw markdown.
504
558
  const fallbackLines = token.raw ? wrapTextWithAnsi(token.raw, availableWidth) : [];
505
- fallbackLines.push("");
559
+ if (nextTokenType && nextTokenType !== "space") {
560
+ fallbackLines.push("");
561
+ }
506
562
  return fallbackLines;
507
563
  }
508
564
  const maxUnbrokenWordWidth = 30;
@@ -510,13 +566,13 @@ export class Markdown {
510
566
  const naturalWidths = [];
511
567
  const minWordWidths = [];
512
568
  for (let i = 0; i < numCols; i++) {
513
- const headerText = this.renderInlineTokens(token.header[i].tokens || []);
569
+ const headerText = this.renderInlineTokens(token.header[i].tokens || [], styleContext);
514
570
  naturalWidths[i] = visibleWidth(headerText);
515
571
  minWordWidths[i] = Math.max(1, this.getLongestWordWidth(headerText, maxUnbrokenWordWidth));
516
572
  }
517
573
  for (const row of token.rows) {
518
574
  for (let i = 0; i < row.length; i++) {
519
- const cellText = this.renderInlineTokens(row[i].tokens || []);
575
+ const cellText = this.renderInlineTokens(row[i].tokens || [], styleContext);
520
576
  naturalWidths[i] = Math.max(naturalWidths[i] || 0, visibleWidth(cellText));
521
577
  minWordWidths[i] = Math.max(minWordWidths[i] || 1, this.getLongestWordWidth(cellText, maxUnbrokenWordWidth));
522
578
  }
@@ -588,7 +644,7 @@ export class Markdown {
588
644
  lines.push(`┌─${topBorderCells.join("─┬─")}─┐`);
589
645
  // Render header with wrapping
590
646
  const headerCellLines = token.header.map((cell, i) => {
591
- const text = this.renderInlineTokens(cell.tokens || []);
647
+ const text = this.renderInlineTokens(cell.tokens || [], styleContext);
592
648
  return this.wrapCellText(text, columnWidths[i]);
593
649
  });
594
650
  const headerLineCount = Math.max(...headerCellLines.map((c) => c.length));
@@ -608,7 +664,7 @@ export class Markdown {
608
664
  for (let rowIndex = 0; rowIndex < token.rows.length; rowIndex++) {
609
665
  const row = token.rows[rowIndex];
610
666
  const rowCellLines = row.map((cell, i) => {
611
- const text = this.renderInlineTokens(cell.tokens || []);
667
+ const text = this.renderInlineTokens(cell.tokens || [], styleContext);
612
668
  return this.wrapCellText(text, columnWidths[i]);
613
669
  });
614
670
  const rowLineCount = Math.max(...rowCellLines.map((c) => c.length));
@@ -626,7 +682,9 @@ export class Markdown {
626
682
  // Render bottom border
627
683
  const bottomBorderCells = columnWidths.map((w) => "─".repeat(w));
628
684
  lines.push(`└─${bottomBorderCells.join("─┴─")}─┘`);
629
- lines.push(""); // Add spacing after table
685
+ if (nextTokenType && nextTokenType !== "space") {
686
+ lines.push(""); // Add spacing after table
687
+ }
630
688
  return lines;
631
689
  }
632
690
  }