Fixing Markdown IR and Signal Formatting: A Journey Through Text Rendering

When you’re working with a chat platform that supports rich formatting, you’d think rendering bold text and handling links would be straightforward. But OpenClaw’s Signal formatting had accumulated a surprising number of edge cases—and my recent PR #9781 was the payoff of tracking down each one.
The problem started innocent enough: markdown-to-IR (intermediate representation) conversion was producing extra newlines between list items and following paragraphs. Nested lists had indentation issues. Blockquotes weren’t visually distinct. Then there were the Signal formatting quirks—URLs weren’t being deduplicated properly because the comparison logic didn’t normalize protocol prefixes or trailing slashes. Headings rendered as plain text instead of bold. When you expanded a markdown link inline, the style offsets for bold and italic text would drift to completely wrong positions.
The real kicker? If you had multiple links expanding in a single message, applyInsertionsToStyles() was using original coordinates for each insertion without tracking cumulative shift. Imagine bolding a phrase that spans across expanded URLs—the bold range would end up highlighting random chunks of text several lines down. Not ideal for a communication platform.
I rebuilt the markdown IR layer systematically. Blockquote closing tags no longer emit redundant newlines—the inner content handles spacing. Horizontal rules now render as visible ─── separators instead of silently disappearing. Tables in code mode strip their inner cell styles so they don’t overlap with code block formatting. The bigger refactor was replacing the fragile indexOf-based chunk position tracking with deterministic cursor tracking in splitSignalFormattedText. Now it splits at whitespace boundaries, respects chunk size limits, and slices style ranges with correct local offsets.
But here’s what really validated the work: 69 new tests. Fifty-one tests for markdown IR covering spacing, nested lists, blockquotes, tables, and horizontal rules. Eighteen tests for Signal formatting. And nineteen tests specifically for style preservation across chunk boundaries when links expand. Every edge case got regression coverage.
The cumulative shift tracking fix alone—ensuring bold and italic styles stay in the right place after multiple link expansions—felt like watching a long-standing bug finally surrender. You spend weeks chasing phantom style offsets across coordinate systems, and then one small addition (cumulative_shift += insertion.length_delta) makes it click.
OpenClaw’s formatting pipeline is now more predictable, more testable, and actually preserves your styling intentions. No more mysterious bold text appearing three paragraphs later. 😄
Metadata
- Branch:
- main
- Dev Joke
- Что сказал Claude при деплое? «Не трогайте меня, я нестабилен»