Skip to content

Fix Telegram MarkdownV2 parsing errors with custom pulldown-cmark renderer#71

Merged
bug-ops merged 1 commit intomainfrom
feat/telegram-escape
Feb 8, 2026
Merged

Fix Telegram MarkdownV2 parsing errors with custom pulldown-cmark renderer#71
bug-ops merged 1 commit intomainfrom
feat/telegram-escape

Conversation

@bug-ops
Copy link
Copy Markdown
Owner

@bug-ops bug-ops commented Feb 8, 2026

Summary

Fixes Telegram API parsing errors (Bad Request: can't parse entities) by implementing a custom MarkdownV2 escape function using pulldown-cmark event-driven rendering.

Implementation

Core changes:

  • Custom TelegramRenderer with state machine for context-aware escaping
  • Event-driven parsing via pulldown-cmark 0.13.0
  • 19 special chars escaped in text, only \ and ` in code blocks
  • UTF-8 safe chunking with char boundary detection

Architecture:

  • markdown.rs - Complete rewrite with TelegramRenderer
  • telegram.rs - UTF-8 safe chunking integration, removed has_unclosed_code_block()
  • markdown_performance.rs - Comprehensive criterion benchmarks
  • memory_profile.rs - Allocation overhead profiling

Performance

  • Latency: 2.83µs (500 chars), 25.73µs (5KB) - 3,534x below 10ms target
  • Throughput: 121-970 MiB/s depending on content type
  • Memory: Single allocation strategy, no excessive copying

Quality

  • Tests: 37/37 pass (30 markdown + 5 telegram + 2 memory)
  • Coverage: 99.32% line coverage for markdown.rs
  • Security: 0 vulnerabilities, no unsafe code
  • Linting: 0 clippy warnings

Dependencies

  • pulldown-cmark 0.13.0 (MIT)
  • criterion 0.8.0 (Apache-2.0/MIT)

Review Process

Phase 2 completed with full rust-lifecycle workflow:

  • Architecture design by rust-architect
  • Implementation by rust-developer
  • Parallel validation: performance, security, testing
  • Code review identified 4 issues (1 critical, 3 important)
  • All issues fixed and re-reviewed
  • Final approval for merge

See .local/handoff/ for detailed reports from each phase.

Fixes #69

Replace manual markdown parsing with AST-based event-driven rendering
using pulldown-cmark for robust Telegram MarkdownV2 formatting.

Core implementation:
- TelegramRenderer with state machine for context-aware escaping
- 19 special chars escaped in text, only \ and ` in code blocks
- Bold/italic/strikethrough/header/link/list/blockquote formatting
- UTF-8 safe chunking with char boundary detection and newline preference
- Dedicated escape_url() for link URLs (only ) and \ per spec)

Performance:
- Latency: 2.83µs for 500 chars, 25.73µs for 5KB (3,534x below 10ms target)
- Throughput: 121-970 MiB/s depending on content type
- Single allocation strategy, no excessive copying

Quality:
- 37 tests pass (30 markdown + 5 telegram + 2 memory profiling)
- 99.32% line coverage for markdown.rs
- 0 clippy warnings
- 0 vulnerabilities (cargo deny pass)
- No unsafe code

Dependencies:
- Added pulldown-cmark 0.13.0 (MIT license)
- Added criterion 0.8.0 for benchmarking

Files modified:
- crates/zeph-channels/src/markdown.rs - Complete rewrite with TelegramRenderer
- crates/zeph-channels/src/telegram.rs - UTF-8 safe chunking, removed has_unclosed_code_block()
- crates/zeph-channels/src/lib.rs - Made markdown module public
- crates/zeph-channels/benches/markdown_performance.rs - Comprehensive benchmark suite
- crates/zeph-channels/tests/memory_profile.rs - Memory allocation profiling

Fixes #69
@github-actions github-actions bot added channels zeph-channels crate (Telegram) rust Rust code changes dependencies Dependency updates size/XL Extra large PR (500+ lines) labels Feb 8, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.97297% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/zeph-channels/src/markdown.rs 98.97% 3 Missing ⚠️
crates/zeph-channels/src/telegram.rs 0.00% 3 Missing ⚠️

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #71      +/-   ##
==========================================
+ Coverage   75.60%   77.23%   +1.62%     
==========================================
  Files          20       20              
  Lines        3489     3654     +165     
==========================================
+ Hits         2638     2822     +184     
+ Misses        851      832      -19     
Files with missing lines Coverage Δ
crates/zeph-channels/src/markdown.rs 98.74% <98.97%> (+1.70%) ⬆️
crates/zeph-channels/src/telegram.rs 32.73% <0.00%> (+2.57%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bug-ops bug-ops merged commit f5ffab9 into main Feb 8, 2026
17 checks passed
@bug-ops bug-ops deleted the feat/telegram-escape branch February 8, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channels zeph-channels crate (Telegram) dependencies Dependency updates rust Rust code changes size/XL Extra large PR (500+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix Telegram MarkdownV2 parsing errors with telegram-escape

2 participants