Skip to content

Commit

Permalink
[FIX] web_editor: fix issues caused by textContent
Browse files Browse the repository at this point in the history
Issue #1: reading textContent

When reading the textContent property of an element, its does not take into
account line breaks introduced by <br> and block elements, whilst innerHtml
does.

This commit solves the issue of updating a link's href to a non-sense url
upon label change. Before this commit, "www.abc.com <br> www.xyz.com" was
being incorrectely parsed as "www.abc.comwww.xyz.com".

Issue #2: setting textContent

When setting the textContent property of an element, all of its child nodes are
removed and replaced by a single text node. While this is fine when the
element contains a single text node, it might not be the desired result when
the element contains other children.

This commit solves the issue obtained when pasting html such as
"link.com<br>link.be" inside an empty inline element such as STRONG or A,
in which cleanForSave was changing its content (removing the line-break) due
to misuse of textContent, when the intended effected was simply removing
ZeroWidthSpace characters. A safer alternative for removing ZeroWidthSpace is
thus provided.

task-3081254

closes odoo#108521

Signed-off-by: David Monjoie (dmo) <[email protected]>
  • Loading branch information
cammarosano committed Feb 9, 2023
1 parent 862d3bd commit 249de26
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 14 deletions.
14 changes: 7 additions & 7 deletions addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ import {
rightLeafOnlyNotBlockPath,
isBlock,
isMacOS,
childNodeIndex,
getSelectedNodes,
isVoidElement
isVoidElement,
cleanZWS,
isZWS,
} from './utils/utils.js';
import { editorCommands } from './commands/commands.js';
import { Powerbox } from './powerbox/Powerbox.js';
Expand Down Expand Up @@ -2850,14 +2850,14 @@ export class OdooEditor extends EventTarget {
// we only remove the attribute to ensure we don't break some style.
// Otherwise we remove the entire inline element.
for (const emptyElement of element.querySelectorAll('[oe-zws-empty-inline]')) {
if (emptyElement.textContent.length === 1 && emptyElement.textContent.includes('\u200B')) {
if (isZWS(emptyElement)) {
if (emptyElement.classList.length > 0) {
emptyElement.removeAttribute('oe-zws-empty-inline');
} else {
emptyElement.remove();
}
} else {
emptyElement.textContent = emptyElement.textContent.replace('\u200B', '');
cleanZWS(emptyElement);
emptyElement.removeAttribute('oe-zws-empty-inline');
}
}
Expand All @@ -2874,10 +2874,10 @@ export class OdooEditor extends EventTarget {
el.removeAttribute('oe-keep-contenteditable');
}

// Remove Zero Width Spzces on Font awesome elements
// Remove Zero Width Spaces on Font awesome elements
const faSelector = 'i.fa,span.fa,i.fab,span.fab,i.fad,span.fad,i.far,span.far';
for (const el of element.querySelectorAll(faSelector)) {
el.textContent = el.textContent.replace('\u200B', '');
cleanZWS(el);
}

}
Expand Down
13 changes: 6 additions & 7 deletions addons/web_editor/static/lib/odoo-editor/src/utils/sanitize.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import {
moveNodes,
preserveCursor,
isFontAwesome,
isMediaElement,
getDeepRange,
isUnbreakable,
closestElement,
getUrlsInfosInString,
URL_REGEX,
isVoidElement,
} from './utils.js';

Expand Down Expand Up @@ -193,16 +191,17 @@ class Sanitize {
) {
node.setAttribute('contenteditable', 'false');
}

if (node.firstChild) {
this._parse(node.firstChild);
}

// Update link URL if label is a new valid link.
if (node.nodeName === 'A' && anchorEl === node) {
const linkLabel = node.textContent;
const match = linkLabel.match(URL_REGEX);
if (match && match[0] === node.textContent && !node.href.startsWith('mailto:')) {
const urlInfo = getUrlsInfosInString(linkLabel)[0];
node.setAttribute('href', urlInfo.url);
const linkLabel = node.innerText;
const urlInfo = getUrlsInfosInString(linkLabel);
if (urlInfo.length && urlInfo[0].label === linkLabel && !node.href.startsWith('mailto:')) {
node.setAttribute('href', urlInfo[0].url);
}
}
node = node.nextSibling;
Expand Down
11 changes: 11 additions & 0 deletions addons/web_editor/static/lib/odoo-editor/src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2427,3 +2427,14 @@ export function peek(arr) {
export function isMacOS() {
return window.navigator.userAgent.includes('Mac');
}

/**
* Remove zero-width spaces from the provided node and its descendants.
*
* @param {Node} node
*/
export function cleanZWS(node) {
[node, ...descendants(node)]
.filter(node => node.nodeType === Node.TEXT_NODE)
.forEach(node => node.nodeValue = node.nodeValue.replace(/\u200B/g, ''));
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ describe('Link', () => {
},
contentAfter: '<p>a<a href="https://google.com">google.comu[]</a>b</p>',
});
await testEditor(BasicEditor, {
contentBefore: '<p>a<a href="https://google.com">google.com[]</a></p>',
stepFunction: async editor => {
await insertLineBreak(editor);
await insertText(editor, 'odoo.com')
},
contentAfter: '<p>a<a href="https://google.com">google.com<br>odoo.com[]</a></p>',
});
});
});
describe('range not collapsed', () => {
Expand Down

0 comments on commit 249de26

Please sign in to comment.