Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): fix new lines being added via elementFromString #4767

Merged
merged 1 commit into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions demos/src/Issues/2720/React/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('<pre><code>foo\nbar</code></pre>')
cy.get('.tiptap').should('contain.html', '<pre><code>foo\nbar</code></pre>')
})
})
})
1 change: 0 additions & 1 deletion packages/core/src/helpers/createNodeFromContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 21 additions & 1 deletion packages/core/src/utilities/elementFromString.ts
Original file line number Diff line number Diff line change
@@ -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 = `<body>${value}</body>`

return new window.DOMParser().parseFromString(wrappedValue, 'text/html').body
const html = new window.DOMParser().parseFromString(wrappedValue, 'text/html').body

removeWhitespaces(html)

return removeWhitespaces(html)
Copy link

@yurtsiv yurtsiv Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but does it have to be two calls of removeWhitespaces?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch - going to remove this for the next patch release.

}