Skip to content

The cursor will jump when typing text before the end of colored text using an input method #7621

@snovey

Description

@snovey

Affected Packages

extension-text-style

Version(s)

3.20.3

Bug Description

  1. Select any piece of text in the editor and apply color to it (make sure the text at the end of the paragraph is colored).
  2. Insert the cursor before the last character in the paragraph.
  3. Insert a character using the input method.
  4. The cursor ends up at the end of the paragraph.
2026-03-17.21.54.39.mov

Move the cursor to the end of the paragraph.

Browser Used

Chrome

Code Example URL

https://tiptap.dev/docs/ui-components/components/color-text-button

Expected Behavior

The cursor is expected to remain before the last character, not after it.

Additional Context (Optional)

In fact, this issue does not occur in Firefox or Safari. Even on Tiptap’s official website, the problem exists on some pages but not others.

Affected pages (with the issue):

Unaffected pages (no issue):

Based on my debugging, the code execution flow when inputting characters via an input method is as follows:

  1. In prosemirror-view/domchange.ts (lines 108–122): parseBetween and findDiff compare the current ProseMirror state with the DOM-parsed result.
  2. In prosemirror-model/diff.ts (line 37): findDiffEnd calls sameMarkup and returns early when marks do not match.
  3. Since injectExtensionAttributesToParseRule in @tiptap/core skips null/undefined values but retains empty strings (""), it causes an inconsistency between the ProseMirror state (null) and the DOM parse result ("").
  4. In prosemirror-view/domchange.ts (lines 233–237): When findDiff returns {start:1, endA:3, endB:3} (where 3 represents the positional coordinate of the cursor at the end of the line), the condition sel.head == tr.mapping.map(chTo) - 1 evaluates to true. This prevents parse.sel from being applied, leaving the cursor stuck at the incorrect position.

Based on point 3 above, I believe the logic of injectExtensionAttributesToParseRule is correct. Instead, I suggest modifying the default values of the parseHTML method in the following files under the packages/extension-text-style directory to either null or undefined:

  • src/background-color/background-color.ts
  • src/color/color.ts
  • src/font-family/font-family.ts
  • src/font-size/font-size.ts
  • src/line-height/line-height.ts

Additionally, this issue also occurs if the version of prosemirror-model in demos/package.json is upgraded to v1.25.2.

ProseMirror introduced a change in version 1.25.2 (commit e73b74c, July 2, 2025):

  • v1.24.1: dom.setAttribute("style", "color: #F98181")getAttribute('style') returns "color: #F98181"parseHTML receives the original hex value → consistent with the ProseMirror state.
  • v1.25.2: dom.style.cssText = "color: #F98181" → Chrome normalizes the value → getAttribute('style') returns "color: rgb(249, 129, 129);"parseHTML receives the RGB value → inconsistent with the hex value in the ProseMirror state.

This change was implemented to bypass CSP (Content Security Policy) restrictions (Issue #1522), but it introduced an unintended side effect of color value normalization. I hope this issue can also be addressed and fixed.

Dependency Updates

  • Yes, I've updated all my dependencies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Open SourceThe issue or pull reuqest is related to the open source packages of Tiptap.

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions