diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 7a9bb4c68c..775e7a01f4 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -390,9 +390,13 @@ export function sanitizeEditableContent(element: any, cleanLineBreaks: boolean = selection.removeAllRanges(); selection.addRange(range); - for (let i = 0; i < innerText.length - tail_len; i++) { - (selection as any).modify("move", "forward", "character"); + while (selection.toString().length < innerText.length - tail_len) { + const selLen = selection.toString().length; + (selection as any).modify("extend", "forward", "character"); + if (selection.toString().length == selLen) break; } + range = selection.getRangeAt(0); + range.setStart(range.endContainer, range.endOffset); } } function mergeValues(src: any, dest: any) { diff --git a/tests/utilstests.ts b/tests/utilstests.ts index 81f7f55e04..d218c264a2 100644 --- a/tests/utilstests.ts +++ b/tests/utilstests.ts @@ -16,14 +16,15 @@ function checkSanitizer(element, text, selectionNodeIndex, selectionStart, clean range.collapse(true); selection.removeAllRanges(); selection.addRange(range); - sanitizeEditableContent(element, cleanLineBreaks); - const newSelection = document.getSelection(); + const range = document.getSelection().getRangeAt(0); + if (element.childNodes.length > 0) range.setStart(element.childNodes[0], 0); return { text: element.innerHTML, plainText: element.innerText, - offset: newSelection.getRangeAt(0).startOffset, - nodeText: newSelection.getRangeAt(0).startContainer.textContent + position: selection?.toString().length, + offset: range.endOffset, + nodeText: range.endContainer.textContent }; } QUnit.test( @@ -70,6 +71,10 @@ QUnit.test( assert.equal(res.offset, 2); assert.equal(res.nodeText, "some"); + var res = checkSanitizer(element, "some
text

", 3, 0, false); + assert.equal(res.plainText, "some\ntext\n\n"); + assert.equal(res.position, 10); + var res = checkSanitizer(element, "some
text
and more", 2, 3, false); assert.equal(res.plainText, "some\ntext\nand more"); assert.equal(res.offset, 3); @@ -79,6 +84,34 @@ QUnit.test( } ); +QUnit.test( + "utils: sanitizer with grapheme clusters", + function (assert) { + var element: HTMLSpanElement = document.createElement("span"); + document.body.appendChild(element); + element.contentEditable = "true"; + + var res = checkSanitizer(element, "พุธ", 0, 2, false); + assert.equal(res.plainText.length, 3); + assert.equal(res.plainText, "พุธ"); + assert.equal(res.offset, 2); + assert.equal(res.nodeText, "พุธ"); + + var res = checkSanitizer(element, "sพุธe", 0, 3, false); + assert.equal(res.plainText.length, 5); + assert.equal(res.plainText, "sพุธe"); + assert.equal(res.offset, 3); + assert.equal(res.nodeText, "sพุธe"); + + var res = checkSanitizer(element, "พุธs
พุธe", 2, 2, false); + assert.equal(res.plainText, "พุธs\nพุธe"); + assert.equal(res.offset, 2); + assert.equal(res.nodeText, "พุธe"); + + element.remove(); + } +); + export function createIActionArray(count: number): Array { let result: Array = []; for (let index = 0; index < count; ++index) {