Fix(view): Resolve Safari IME style pollution and table truncation #188

Closed
ghost wants to merge 1 commit from master into master
ghost commented 2025-12-24 07:25:19 +01:00 (Migrated from github.com)

This PR addresses critical compatibility issues with Safari IME (Input Method Editor), specifically resolving "style pollution" (unwanted styles/tags) and "content truncation" in complex nodes like tables.

1. Style Pollution Fix (Garbage Cleanup)

  • Issue: Safari IME frequently injects unwanted <font> tags or adds inline style attributes (e.g., color: ..., font-size: ...) to elements during composition. This often persists after composition ends, corrupting the document model.
  • Fix: Implemented a "Record & Cleanup" strategy.
    • Record: DOMObserver now detects and records specific "pollution" mutations (FONT tag insertions, style attribute changes) into a safariDirtyNodes list during composition (while still effectively ignoring them for general parsing transactions).
    • Cleanup: At compositionend, InputState consumes this list to surgically remove the recorded styles/tags and triggers markDirty on the affected nodes.
    • Benefit: This maintains high performance (O(1) vs O(N) scan) and ensures only proven garbage is removed.

2. Table Content Truncation Fix (Structural Guard)

  • Issue: In table cells, Safari IME occasionally inserts block-level elements (<br>, <div>, <p>) during composition updates. ProseMirror often interprets this as a structural split (e.g., ending the cell), causing subsequent text to be moved outside the table, appearing as data loss.
  • Fix: Added a guard in DOMChange to detect and abort these invalid structural insertions (DIV/P/BR) specifically during Safari composition. This prevents the parser from breaking the table structure.

3. Composition Start Safety

  • Improvement: Enhanced compositionstart logic to prioritize the physical DOM caret position over abstract ProseMirror selections (like CellSelection).
  • Why: When a CellSelection is active, ProseMirror considers the whole cell selected. If composition starts, standard logic might overwrite (delete) the cell. Using the DOM caret ensures text is inserted inside the cell as intended.

Videos

before:

https://github.com/user-attachments/assets/66c72429-3ce8-4d89-b373-ac83af2225f2

https://github.com/user-attachments/assets/6ea5f0c6-de6c-4211-9271-c30e2255d096

after:

https://github.com/user-attachments/assets/ad1d0959-1107-4a1a-9658-483627c362ff

https://github.com/user-attachments/assets/fd53ab3c-050f-4c16-9ab0-20cbe3358d37

This PR addresses critical compatibility issues with Safari IME (Input Method Editor), specifically resolving "style pollution" (unwanted styles/tags) and "content truncation" in complex nodes like tables. ## 1. Style Pollution Fix (Garbage Cleanup) * **Issue**: Safari IME frequently injects unwanted `<font>` tags or adds inline `style` attributes (e.g., `color: ...`, `font-size: ...`) to elements during composition. This often persists after composition ends, corrupting the document model. * **Fix**: Implemented a **"Record & Cleanup"** strategy. * **Record**: `DOMObserver` now detects and records specific "pollution" mutations (`FONT` tag insertions, `style` attribute changes) into a `safariDirtyNodes` list during composition (while still effectively ignoring them for general parsing transactions). * **Cleanup**: At `compositionend`, `InputState` consumes this list to surgically remove the recorded styles/tags and triggers `markDirty` on the affected nodes. * **Benefit**: This maintains high performance (O(1) vs O(N) scan) and ensures only proven garbage is removed. ## 2. Table Content Truncation Fix (Structural Guard) * **Issue**: In table cells, Safari IME occasionally inserts block-level elements (`<br>`, `<div>`, `<p>`) during composition updates. ProseMirror often interprets this as a structural split (e.g., ending the cell), causing subsequent text to be moved *outside* the table, appearing as data loss. * **Fix**: Added a guard in `DOMChange` to detect and abort these invalid structural insertions (`DIV`/`P`/`BR`) specifically during Safari composition. This prevents the parser from breaking the table structure. ## 3. Composition Start Safety * **Improvement**: Enhanced `compositionstart` logic to prioritize the physical DOM caret position over abstract ProseMirror selections (like `CellSelection`). * **Why**: When a `CellSelection` is active, ProseMirror considers the *whole cell* selected. If composition starts, standard logic might overwrite (delete) the cell. Using the DOM caret ensures text is inserted *inside* the cell as intended. ## Videos before: https://github.com/user-attachments/assets/66c72429-3ce8-4d89-b373-ac83af2225f2 https://github.com/user-attachments/assets/6ea5f0c6-de6c-4211-9271-c30e2255d096 after: https://github.com/user-attachments/assets/ad1d0959-1107-4a1a-9658-483627c362ff https://github.com/user-attachments/assets/fd53ab3c-050f-4c16-9ab0-20cbe3358d37
marijnh commented 2025-12-29 19:10:28 +01:00 (Migrated from github.com)

I was able to reproduce this issue in table cells. However, I was not able to ever see <font> tags being created. Can you provide detailed reproduction instructions for a situation where that happens?

Similarly, I haven't been able to reproduce the issue in headings, as described in the TipTap bug report. Can you reproduce that in plain ProseMirror?

Lastly, was any of this code generated with the help of a language model (AI)?

I was able to reproduce this issue in table cells. However, I was not able to ever see `<font>` tags being created. Can you provide detailed reproduction instructions for a situation where that happens? Similarly, I haven't been able to reproduce the issue in headings, as described in the TipTap bug report. Can you reproduce that in plain ProseMirror? Lastly, was any of this code generated with the help of a language model (AI)?
marijnh commented 2026-01-14 12:56:04 +01:00 (Migrated from github.com)

I'm going to guess that yes, this PR was generated with a language model. That kind of 'contribution' is not welcome to this project.

If you can provide me information about the header problem (assuming the connection with the table issue wasn't a hallucination), I'd be interested in looking at that. For now, I've pushed a patch 1773eac that tries to work around the table problem.

I'm going to guess that yes, this PR was generated with a language model. That kind of 'contribution' is not welcome to this project. If you can provide me information about the header problem (assuming the connection with the table issue wasn't a hallucination), I'd be interested in looking at that. For now, I've pushed a patch 1773eac that tries to work around the table problem.

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
prosemirror/prosemirror-view!188
No description provided.