[FIX] web_editor: prevent line breaks at edges of anchor on press enter

When pressing enter at the edge of an anchor that is a child of an
unbreakable element, we inserted line breaks in the anchor itself, which
is unexpected. This inserts the anchors after/before it instead.

closes odoo/odoo#81662

X-original-commit: df6f8dd0c54c40ea7edbd3821ae068d79b1b7af7
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
Antoine Guenet
2021-12-20 16:04:49 +00:00
parent d049e3d7d7
commit c53ebf8244
5 changed files with 47 additions and 4 deletions
@@ -46,6 +46,7 @@ import {
YOUTUBE_URL_GET_VIDEO_ID,
unwrapContents,
peek,
rightPos,
} from './utils/utils.js';
import { editorCommands } from './commands/commands.js';
import { Powerbox } from './powerbox/Powerbox.js';
@@ -2138,7 +2139,21 @@ export class OdooEditor extends EventTarget {
this.historyRollback();
ev.preventDefault();
if (this._applyCommand('oEnter') === UNBREAKABLE_ROLLBACK_CODE) {
this._applyCommand('oShiftEnter');
const brs = this._applyCommand('oShiftEnter');
const anchor = brs[0].parentElement;
if (anchor.nodeName === 'A') {
if (brs.includes(anchor.firstChild)) {
brs.forEach(br => anchor.before(br));
setSelection(...rightPos(brs[brs.length - 1]));
this.sanitize();
this.historyStep();
} else if (brs.includes(anchor.lastChild)) {
brs.forEach(br => anchor.after(br));
setSelection(...rightPos(brs[0]));
this.sanitize();
this.historyStep();
}
}
}
} else if (['insertText', 'insertCompositionText'].includes(ev.inputType)) {
// insertCompositionText, courtesy of Samsung keyboard.
@@ -12,7 +12,7 @@ import {
} from '../utils/utils.js';
Text.prototype.oShiftEnter = function (offset) {
this.parentElement.oShiftEnter(splitTextNode(this, offset));
return this.parentElement.oShiftEnter(splitTextNode(this, offset));
};
HTMLElement.prototype.oShiftEnter = function (offset) {
@@ -39,4 +39,6 @@ HTMLElement.prototype.oShiftEnter = function (offset) {
break;
}
}
return brEls;
};
@@ -139,7 +139,7 @@ const testMultiEditor = spec => {
clientInfo.editor.onExternalHistorySteps(missingSteps.concat([step]));
},
});
clientInfo.editor.keyboardType = 'PHYSICAL_KEYBOARD';
clientInfo.editor.keyboardType = 'PHYSICAL';
const selection = selections[clientInfo.clientId];
if (selection) {
setTestSelection(selection, iframeDocument);
@@ -2248,6 +2248,31 @@ X[]
contentAfter: '<p><b>abc</b></p><p>[]<br></p>',
});
});
it.only('should insert line breaks outside the edges of an anchor', async () => {
const pressEnter = editor => {
editor.document.execCommand('insertParagraph');
}
await testEditor(BasicEditor, {
contentBefore: '<div>ab<a>[]cd</a></div>',
stepFunction: pressEnter,
contentAfter: '<div>ab<br><a>[]cd</a></div>',
});
await testEditor(BasicEditor, {
contentBefore: '<div><a>a[]b</a></div>',
stepFunction: pressEnter,
contentAfter: '<div><a>a<br>[]b</a></div>',
});
await testEditor(BasicEditor, {
contentBefore: '<div><a>ab[]</a></div>',
stepFunction: pressEnter,
contentAfter: '<div><a>ab</a><br>[]<br></div>',
});
await testEditor(BasicEditor, {
contentBefore: '<div><a>ab[]</a>cd</div>',
stepFunction: pressEnter,
contentAfter: '<div><a>ab</a><br>[]cd</div>',
});
});
});
describe('With attributes', () => {
it('should insert an empty paragraph before a paragraph with a span with a class', async () => {
@@ -296,9 +296,10 @@ export async function testEditor(Editor = OdooEditor, spec) {
const selection = parseTextualSelection(testNode);
const editor = new Editor(testNode, { toSanitize: false });
editor.keyboardType = 'PHYSICAL_KEYBOARD';
editor.keyboardType = 'PHYSICAL';
if (selection) {
setTestSelection(selection);
editor._recordHistorySelection();
} else {
document.getSelection().removeAllRanges();
}