Skip to content

[COMMS-572] Pasting rich text into CKEditor crashes it#124

Draft
op-chomper wants to merge 1 commit into
opf:masterfrom
op-chomper:task/COMMS-572-pasting-rich-text-into-ckeditor-crashes-
Draft

[COMMS-572] Pasting rich text into CKEditor crashes it#124
op-chomper wants to merge 1 commit into
opf:masterfrom
op-chomper:task/COMMS-572-pasting-rich-text-into-ckeditor-crashes-

Conversation

@op-chomper

Copy link
Copy Markdown

🤖 AI-generated PR! Please review it for accuracy and then remove this line.

What does this PR change?

Fixes a crash where pasting formatted rich text into CKEditor (e.g. an AppSignal error page with a syntax-highlighted code block) threw CKEditorError: can't access property "replace", e6.data is undefined, which the watchdog answered by restarting the editor — wiping everything the user had typed.

The crash came from the code-block upcast converter assuming <code>'s first child was a text node (child.data.replace(...)). When the pasted code is wrapped in highlight <span>s, that child is an element and .data is undefined. It now extracts text via a recursive textContentOf() helper that only reads .data off real text nodes.

It also adds a defensive paste boundary so this class of failure can never crash the editor again.

What approach did you choose and why?

Two layers: (1) the targeted converter fix, which resolves the reported repro; and (2) a new OPPasteGuard plugin that runs the clipboard→model conversion in a try/catch before the pipeline's default insertion. On any converter error it aborts the rich paste, inserts the plain-text fallback, and emits op:clipboard-paste-error — so the editor stays alive and existing content is preserved even for a future, unknown converter bug. The companion OpenProject frontend change turns that event (and watchdog errors) into a user-facing flash instead of failing silently.

Screenshots

No visual changes (error-handling/flash messaging only).

Tests

Added unit tests for textContentOf covering plain text, single-text <code>, the regression case (element-wrapped <code>, asserts no throw), deep nesting, and empty elements. Manual verification: paste the AppSignal incident content into a meeting agenda editor — content pastes, no console error, previously typed text retained; Ctrl+Shift+V still works.

Merge checklist

  • Rebuild the bundle (npm run build) and bump @openproject/commonmark-ckeditor-build in the OpenProject frontend — the fix isn't live until the generated build/ + src/ckeditor.js are regenerated.
  • Companion OpenProject PR (component event handling + js.editor.error_paste_failed locale key) merged together.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant