From 2235908c28f388eda041d1d5d017554d513fe909 Mon Sep 17 00:00:00 2001 From: bdbch <6538827+bdbch@users.noreply.github.com> Date: Wed, 10 Jan 2024 13:43:48 +0100 Subject: [PATCH] fix(core): fix new lines being added via elementFromString (#4767) Co-authored-by: bdbch --- demos/src/Issues/2720/React/index.spec.js | 7 ++++++ .../core/src/helpers/createNodeFromContent.ts | 1 - .../core/src/utilities/elementFromString.ts | 22 ++++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/demos/src/Issues/2720/React/index.spec.js b/demos/src/Issues/2720/React/index.spec.js index 6035fd14a5..025c7b7b3d 100644 --- a/demos/src/Issues/2720/React/index.spec.js +++ b/demos/src/Issues/2720/React/index.spec.js @@ -20,4 +20,11 @@ context('/src/Issues/2720/React/', () => { // check if the content html is correct cy.get('.tiptap').should('contain.html', 'Hello World\nThis is content with a new line. Is this working?\n\nLets see if multiple new lines are inserted correctly') }) + + it('should keep newlines in pre tag', () => { + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('
foo\nbar
') + cy.get('.tiptap').should('contain.html', '
foo\nbar
') + }) + }) }) diff --git a/packages/core/src/helpers/createNodeFromContent.ts b/packages/core/src/helpers/createNodeFromContent.ts index 7b161d67ec..b6a7e74895 100644 --- a/packages/core/src/helpers/createNodeFromContent.ts +++ b/packages/core/src/helpers/createNodeFromContent.ts @@ -40,7 +40,6 @@ export function createNodeFromContent( } if (typeof content === 'string') { - content = content.split('\n').map(part => part.trim()).join('') // we need to remove new lines since the parser will add breaks const parser = DOMParser.fromSchema(schema) return options.slice diff --git a/packages/core/src/utilities/elementFromString.ts b/packages/core/src/utilities/elementFromString.ts index bbfd794bd5..69a27634a9 100644 --- a/packages/core/src/utilities/elementFromString.ts +++ b/packages/core/src/utilities/elementFromString.ts @@ -1,6 +1,26 @@ +const removeWhitespaces = (node: HTMLElement) => { + const children = node.childNodes + + for (let i = children.length - 1; i >= 0; i -= 1) { + const child = children[i] + + if (child.nodeType === 3 && child.nodeValue && !/\S/.test(child.nodeValue)) { + node.removeChild(child) + } else if (child.nodeType === 1) { + removeWhitespaces(child as HTMLElement) + } + } + + return node +} + export function elementFromString(value: string): HTMLElement { // add a wrapper to preserve leading and trailing whitespace const wrappedValue = `${value}` - return new window.DOMParser().parseFromString(wrappedValue, 'text/html').body + const html = new window.DOMParser().parseFromString(wrappedValue, 'text/html').body + + removeWhitespaces(html) + + return removeWhitespaces(html) }