ultraworkers / ultraworkers/claw-code

Fix markdown formatting issues in TUI streaming: block-level element newline omission and consecutive empty line accumulation

Open Beginner friendly
#3,259 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
195k
Forks
108k
PR merge metrics
No merged PRs in 30d

Description

Describe the bug

When rendering Markdown text in TUI streaming mode (specifically in non-compact mode):

  1. Newline omission / output stickiness: When a text description is immediately followed by a block-level element (e.g., a fenced code block), pulldown-cmark does 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.
  2. 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) or ensure_newlines(output, 1) (for items, blockquotes), which prevents consecutive newlines from accumulating beyond 1 empty line.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

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.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.