diff --git a/packages/rich-text-editor/src/vaadin-rich-text-editor.js b/packages/rich-text-editor/src/vaadin-rich-text-editor.js index a07073f4ee..692877e9e9 100644 --- a/packages/rich-text-editor/src/vaadin-rich-text-editor.js +++ b/packages/rich-text-editor/src/vaadin-rich-text-editor.js @@ -1013,7 +1013,26 @@ class RichTextEditor extends ElementMixin(ThemableMixin(PolymerElement)) { * @param {string} htmlValue */ dangerouslySetHtmlValue(htmlValue) { + const whitespaceCharacters = { + '\t': '__VAADIN_RICH_TEXT_EDITOR_TAB', + ' ': '__VAADIN_RICH_TEXT_EDITOR_DOUBLE_SPACE', + }; + // Replace whitespace characters with placeholders before the Delta conversion to prevent Quill from trimming them + Object.entries(whitespaceCharacters).forEach(([character, replacement]) => { + htmlValue = htmlValue.replaceAll(/>[^<]* match.replaceAll(character, replacement)); // NOSONAR + }); + const deltaFromHtml = this._editor.clipboard.convert(htmlValue); + + // Restore whitespace characters after the conversion + Object.entries(whitespaceCharacters).forEach(([character, replacement]) => { + deltaFromHtml.ops.forEach((op) => { + if (typeof op.insert === 'string') { + op.insert = op.insert.replaceAll(replacement, character); + } + }); + }); + this._editor.setContents(deltaFromHtml, SOURCE.API); } diff --git a/packages/rich-text-editor/test/basic.test.js b/packages/rich-text-editor/test/basic.test.js index b1bf85fab1..23a8e79b13 100644 --- a/packages/rich-text-editor/test/basic.test.js +++ b/packages/rich-text-editor/test/basic.test.js @@ -690,6 +690,41 @@ describe('rich text editor', () => { expect(rte.htmlValue).to.equal('
Hello
world
'); }); + it('should not lose leading tab characters from the resulting htmlValue', () => { + const htmlWithLeadingTab = '\tTab
'; + rte.dangerouslySetHtmlValue(htmlWithLeadingTab); + flushValueDebouncer(); + expect(rte.htmlValue).to.equal(htmlWithLeadingTab); + }); + + it('should not lose extra space characters from the resulting htmlValue', () => { + const htmlWithExtraSpaces = 'Extra spaces
'; + rte.dangerouslySetHtmlValue(htmlWithExtraSpaces); + flushValueDebouncer(); + expect(rte.htmlValue).to.equal(htmlWithExtraSpaces); + }); + + it('should not break code block attributes', () => { + const htmlWithCodeBlock = `code\n`; + rte.dangerouslySetHtmlValue(htmlWithCodeBlock); + flushValueDebouncer(); + expect(rte.htmlValue).to.equal(htmlWithCodeBlock); + }); + + it('should support double spaces inside html tags', () => { + const htmlWithCodeBlock = `
code\n`; + rte.dangerouslySetHtmlValue(htmlWithCodeBlock); + flushValueDebouncer(); + expect(rte.htmlValue).to.equal(`
code\n`); + }); + + it('should support tabs inside html tags', () => { + const htmlWithCodeBlock = `
code\n`; + rte.dangerouslySetHtmlValue(htmlWithCodeBlock); + flushValueDebouncer(); + expect(rte.htmlValue).to.equal(`
code\n`); + }); + it('should return the quill editor innerHTML', () => { expect(rte.htmlValue).to.equal('