Skip to content

[Bug]: Rich text composer consumes typed underscores in snake_case text, including inside inline code #19169

Closed

Description

@lastobelus

Area

apps/web (message composer, rich text mode)

Summary

In the rich text composer, typing a second _ on a line consumes both underscores and italicizes everything between them. It happens mid-word in snake_case text such as node_modules, and it reaches back into an already completed inline code span. The underscores do not come back.

Steps to reproduce

Rich text composer enabled. Type every character; do not paste.

Case 1: plain text

  1. Start with an empty composer.
  2. Type:
    clean _build and node
    
  3. Type _
  4. Press Right, then type modules

Case 2: inline code

  1. Start with an empty composer.
  2. Type the line below. The first backtick pair becomes a code span showing _build; the last backtick stays open.
    clean `_build` and `node
    
  3. Type _
  4. Type, with no leading space:
    modules`
    

Expected behavior

The composer keeps exactly what was typed, with no italics.

Case 1:

clean _build and node_modules

Case 2, shown as two inline code spans:

clean `_build` and `node_modules`

An intraword _ does not close emphasis in CommonMark, and inline code content is literal.

Actual behavior

Case 1

  • After step 3, both underscores are consumed and replaced with italic formatting on build and node.
  • After step 4, the composer shows clean, italic build and node, then plain modules. The underscores are still gone.

T3 Code composer after case 1

Case 2

  • After step 3, the underscore inside the completed code span is consumed along with the one just typed. The span shows build, and italics run from inside it through node.
  • After step 4, the composer shows an italic code span build, italic and, a code span holding italic node plus a literal backtick, and a separate non-italic code span holding modules plus a literal backtick. No underscore is left.

T3 Code composer after case 2

Impact

Prompts for coding agents are full of leading-underscore names, snake_case identifiers, and paths. The composer changes them during typing, and the change is easy to miss. Wrapping the name in inline code, the usual way to protect a literal, does not prevent it.

Version or commit

0.0.46-nightly.20261013.3066 (tag v0.0.46-nightly.20261013.3066, commit 98a6246d07624432a6e6d0ab4fb87bede90a49a6)

Environment

macOS desktop app. No provider or model involved; nothing needs to be sent.

Source notes

Unconfirmed reading of the source at that commit:

  • Italic rule: rich mode leaves StarterKit's stock italic enabled (ComposerPromptEditorTiptap.tsx#L1063). Its Tiptap 3.31.3 underscore input rule fires on the closing _ and deletes both delimiters.
  • Code guard: Tiptap's markInputRule skips matches overlapping a mark that excludes italic, and excludes: "code" in ComposerCodeExtension removes that guard (composer-rich-text-doc.ts#L62-L67). This is why the rule reaches into inline code.
  • Serializer: RICH_TEXT_DELIMITERS.italic is * (composer-rich-text.ts#L20-L25), so the italic run is written back with asterisks.

Activity

  1. juliusmarminge commented on Oct 13, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Confirmed on main: this comes from our editor config, not intended behavior.

    • StarterKit.configure in ComposerPromptEditorTiptap.tsx keeps Tiptap's stock Italic, which has _text_ input and paste rules alongside *text*. The stock underscore rule only needs whitespace before the opening _, so _build and node_ matches even though CommonMark wouldn't close emphasis on an intraword _.
    • ComposerCodeExtension (composer-rich-text-doc.ts) sets excludes: "code" so code can sit inside emphasis. That also means italic is still allowed inside code, so the rule can reach into a finished code span.
    • RICH_TEXT_DELIMITERS writes italic as *, so the composer never needs _ as an emphasis trigger.

    Likely fix: extend Italic so it keeps only the * rules (or skip matches touching a code mark), and add tests for snake_case and code spans. #17435 (backticks) and #16105 (tildes) touch nearby code but don't fix this.

    Workaround for now: switch off the rich text composer setting, which makes the composer keep typed markers as literal characters.

  2. added
    acceptedfeature request accepted
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 13, 2026
  3. lastobelus commented on Oct 14, 2026

    @lastobelus
    ContributorAuthor

    This is a good case where Obsidian is both useful and appropriate, lol.
    The way Obsidian works in live preview with automatic Markdown pairing enabled is very good & has worked well for me for years.

    The above case would leave the sentence after _build in italics, BUT navigating to the correct spot and putting backticks around _build is easy and intuitive with either cursor keys or mouse.

  4. juliusmarminge commented on Oct 20, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Fixed by #19186, which just landed on main: the rich text composer now keeps typed underscores literal (including inside earlier inline code) and only uses `*` for italics. It will ship in the next nightly. If you still see underscores getting eaten on a build that includes #19186, comment here and we will reopen.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions