Skip to content

fix(transcription): strip ***bold italic*** markdown emphasis - #6549

Open
darrenori wants to merge 2 commits into
livekit:mainfrom
darrenori:fix/markdown-filter-bold-italic
Open

fix(transcription): strip ***bold italic*** markdown emphasis#6549
darrenori wants to merge 2 commits into
livekit:mainfrom
darrenori:fix/markdown-filter-bold-italic

Conversation

@darrenori

Copy link
Copy Markdown

Problem

filter_markdown strips markdown before text reaches TTS, but it only covers *italic* and **bold**. The combined ***text*** / ___text___ form is left untouched, so the delimiters leak through and get spoken.

"This is ***very important*** text."  ->  "This is ***very important*** text."
"___Totally___ critical."             ->  "___Totally___ critical."
"Use ***both*** and **bold**"         ->  "Use ***both*** and bold"

Neither existing pattern can match it:

  • bold — the body is [^*\n]+?, which stops at the third asterisk
  • italic — the (?!\s|\*) guard rejects a * immediately after the opening delimiter

Same for the underscore variants. LLMs emit ***…*** fairly often for emphasis, so this shows up in practice.

Fix

Add a triple-delimiter pattern ahead of each existing pair. The word/asterisk boundary assertions ((?<![\w*]) / (?![\w*])) are carried over unchanged from the existing patterns.

Tests

Added test_bold_italic, covering the four cases above across chunk sizes 1, 2, 3, 7, 50 so the streaming path is exercised too. All fail before the change, pass after.

Existing coverage is unaffected — the full MARKDOWN_INPUT document test, the punctuation-boundary cases, and the no-false-positive cases (2 * 3 = 6, Use *.py files, x**2 + y**2 = z**2, __dunder_method__) all still pass.

ruff check and ruff format are clean.

The markdown filter handled `*text*` and `**text**` but not the combined
`***text***` / `___text___` form, so those delimiters leaked through to
TTS and were read aloud.

Neither existing pattern can match it: the bold pattern's body is
`[^*\n]+?`, which stops at the third asterisk, and the italic pattern
has a `(?!\s|\*)` guard right after the opening delimiter. The same
applies to the underscore variants.

Add a triple-delimiter pattern ahead of each existing pair. The
word/asterisk boundary assertions are unchanged, so arithmetic (`x**2`),
globs (`*.py`) and dunder names are still preserved.
Exercise `***text***` and `___text___` across several chunk sizes, so the
streaming path is checked as well as the single-shot one.
@darrenori
darrenori requested a review from a team as a code owner July 26, 2026 15:23
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@longcw longcw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the pr! could you sign the CLA before we merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants