Fix markdown formatting issues in TUI streaming: block-level element newline omission and consecutive empty line accumulation
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
Research direction
Start in render.rs, focusing on the Markdown event handlers used by TUI streaming in non-compact mode and the block-level start and end events described in the issue. Verify the result with descriptions followed by fenced code blocks and nested list content: borders should not stick to preceding text, and block endings should leave no more than one empty line.
Written by the indexing model from the issue text.
Description
Describe the bug
When rendering Markdown text in TUI streaming mode (specifically in non-compact mode):
- Newline omission / output stickiness: When a text description is immediately followed by a block-level element (e.g., a fenced code block),
pulldown-cmarkdoes not emit any line-break or soft-break events between them. This results in the code block top border rendering immediately after the text (e.g.,2. Enter directory:╭─ code), causing layout stickiness. - Consecutive empty line accumulation: Multiple block closing events (such as code block end + list item end + list end) consecutively append newlines unconditionally. This leads to redundant empty lines stacking up in the terminal (e.g., 3-4 consecutive empty lines), which wastes screen space.
Solution / Implementation
We solved this by introducing an idempotent, smart newline-ensuring helper:
fn ensure_newlines(output: &mut String, count: usize) {
if output.is_empty() {
return;
}
let current = output.chars().rev().take_while(|&c| c == '\n').count();
if current < count {
output.push_str(&"\n".repeat(count - current));
}
}
And applied it defensively to block-level start/end event handlers in render.rs:
- Code Block Start / Item Start / Blockquote Start: Call
ensure_newlines(output, 1)to prevent inline stickiness. - Heading Start: Call
ensure_newlines(output, 2)to ensure space before headers. - Block End Events: Replace unconditional newline pushing with
ensure_newlines(output, 2)(for paragraphs, headings, lists, table closings) orensure_newlines(output, 1)(for items, blockquotes), which prevents consecutive newlines from accumulating beyond 1 empty line.
- Dominant language
- Rust
- Stars
- 195k
- Forks
- 108k
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ultraworkers/claw-code
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
ultraworkers/claw-code#3258 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ultraworkers/claw-code#3257 · 2 comments ·
-
[CRITICAL][SECURITY] Untrusted project hooks bypass read-only mode for arbitrary command execution Open
Difficulty 4/5 3-5 days Newbie friendliness 68/100
ultraworkers/claw-code#3301 · 4 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 20/100
ultraworkers/claw-code#3300 · 2 comments ·
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
ultraworkers/claw-code#3287 · 6 comments · 1 reaction ·
All issues in ultraworkers/claw-code
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gitbutlerapp/gitbutler#15998 · 1 comment ·
-
bug triage:deciding
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-telemetry/otel-arrow#4132 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100