Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion addons/html_editor/static/src/core/clipboard_plugin.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { isTextNode, isParagraphRelatedElement } from "../utils/dom_info";
import { Plugin } from "../plugin";
import { closestBlock, isBlock } from "../utils/blocks";
import { unwrapContents, wrapInlinesInBlocks } from "../utils/dom";
import { unwrapContents, wrapInlinesInBlocks, splitTextNode } from "../utils/dom";
import { ancestors, childNodes, closestElement } from "../utils/dom_traversal";
import { parseHTML } from "../utils/html";
import { getTableCells } from "../utils/table";
import {
baseContainerGlobalSelector,
getBaseContainerSelector,
} from "@html_editor/utils/base_container";
import { DIRECTIONS } from "../utils/position";

/**
* @typedef { import("./selection_plugin").EditorSelection } EditorSelection
Expand Down Expand Up @@ -622,6 +623,21 @@ export class ClipboardPlugin extends Plugin {
if (!isHtmlContentSupported(ev.target)) {
return;
}
const selection = this.dependencies.selection.getEditableSelection();
const nodeToSplit =
selection.direction === DIRECTIONS.RIGHT ? selection.focusNode : selection.anchorNode;
const offsetToSplit =
selection.direction === DIRECTIONS.RIGHT
? selection.focusOffset
: selection.anchorOffset;
if (nodeToSplit.nodeType === Node.TEXT_NODE && !selection.isCollapsed) {
const selectionToRestore = this.dependencies.selection.preserveSelection();
// Split the text node beforehand to ensure the insertion offset
// remains correct after deleting the selection.
splitTextNode(nodeToSplit, offsetToSplit, DIRECTIONS.LEFT);
selectionToRestore.restore();
}

const dataTransfer = (ev.originalEvent || ev).dataTransfer;
const imageNodeHTML = ev.dataTransfer.getData("application/vnd.odoo.odoo-editor-node");
const image =
Expand All @@ -635,12 +651,14 @@ export class ClipboardPlugin extends Plugin {
if (image || fileTransferItems.length || htmlTransferItem) {
if (this.document.caretPositionFromPoint) {
const range = this.document.caretPositionFromPoint(ev.clientX, ev.clientY);
this.dependencies.delete.deleteSelection();
this.dependencies.selection.setSelection({
anchorNode: range.offsetNode,
anchorOffset: range.offset,
});
} else if (this.document.caretRangeFromPoint) {
const range = this.document.caretRangeFromPoint(ev.clientX, ev.clientY);
this.dependencies.delete.deleteSelection();
this.dependencies.selection.setSelection({
anchorNode: range.startContainer,
anchorOffset: range.startOffset,
Expand Down
8 changes: 4 additions & 4 deletions addons/html_editor/static/tests/paste.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3725,21 +3725,21 @@ ${" "}
});

describe("onDrop", () => {
test("should add text from htmlTransferItem", async () => {
test("should drop text from htmlTransferItem", async () => {
const { el } = await setupEditor("<p>a[b]cd</p>");
const pElement = el.firstChild;
const textNode = pElement.firstChild;

patchWithCleanup(document, {
caretPositionFromPoint: () => ({ offsetNode: textNode, offset: 3 }),
caretPositionFromPoint: () => ({ offsetNode: textNode, offset: 0 }),
});

const dropData = new DataTransfer();
dropData.setData("text/html", "b");
await dispatch(pElement, "drop", { dataTransfer: dropData });
await tick();

expect(getContent(el)).toBe("<p>abcb[]d</p>");
expect(getContent(el)).toBe("<p>b[]acd</p>");
});
test("should not be able to paste inside some branded node", async () => {
const { el } = await setupEditor(`<p data-oe-model="foo" data-oe-type="text">a[b]cd</p>`);
Expand All @@ -3759,7 +3759,7 @@ describe("onDrop", () => {
expect(getContent(el)).toBe(`<p data-oe-model="foo" data-oe-type="text">a[b]cd</p>`);
});
test("should add new images form fileTransferItems", async () => {
const { el } = await setupEditor(`<p>a[b]cd</p>`);
const { el } = await setupEditor(`<p>ab[]cd</p>`);
const pElement = el.firstChild;
const textNode = pElement.firstChild;

Expand Down