Skip to content

DocumentEditor: pasting HTML from browser into a list paragraph inserts raw SFDT JSON as literal text #214

@coco-ethix

Description

@coco-ethix

Description

When a user copies text from a browser (or any external source) and pastes it into a list paragraph inside the DocumentEditor, the raw SFDT JSON string is inserted into the document as literal text instead of the actual content. Pasting into a regular (non-list) paragraph works correctly.

Version

@syncfusion/ej2-documenteditor 33.1.49 (React)

Steps to Reproduce

  1. Open a document that contains a bulleted or numbered list.
  2. Place the cursor inside a list item.
  3. Copy any text from a browser tab (e.g., a sentence from a webpage).
  4. Press Ctrl+V inside the list item.

Expected: The copied text is pasted into the list item.
Actual: A raw JSON string (SFDT format) is inserted as literal text, e.g.:

{"sections":[{"blocks":[{"inlines":[{"text":"Hello world"}],"paragraphFormat":{...}}],...}]}

Root Cause (traced in source)

The bug is in Editor.prototype.beforePasteEvent (editor.js). The try/catch block is too broad — it wraps both JSON.parse and pasteContents together:

// editor.js — beforePasteEvent
try {
    var parsedData = JSON.parse(data);
    this.pasteContents(HelperMethods.getSfdtDocument(parsedData)); // ← throws for list context
} catch (_a) {
    // fallback: pastes raw `data` string as-is
    this.pasteContents(isNullOrUndefined(data) ? this.copiedTextContent : data);
}

Flow for HTML paste into a list:

  1. External HTML is sent to the SystemClipboard service endpoint.
  2. Service returns SFDT JSON → data = JSON.stringify(result.data).
  3. beforePasteEvent(data, '.html') is called.
  4. JSON.parse(data) succeeds.
  5. pasteContents(getSfdtDocument(parsedData)) throws (list-context-specific error).
  6. The catch block runs pasteContents(data) where data is the raw SFDT JSON string.
  7. The JSON string is inserted into the document as literal text.

The same paste into a non-list paragraph does not throw in step 5, so it works correctly.

Suggested Fix

Narrow the try/catch so it only guards JSON.parse, not pasteContents:

var parsedData;
try {
    parsedData = JSON.parse(data);
} catch (_a) {
    // not JSON — paste as plain text
    this.pasteContents(isNullOrUndefined(data) ? this.copiedTextContent : data);
    return;
}
this.pasteContents(HelperMethods.getSfdtDocument(parsedData));

This way, a failure inside pasteContents is not silently swallowed and does not cause the SFDT JSON to land in the document as text.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions