Skip to content

Commit

Permalink
fix(content): also trim leading/trailing   whitespace
Browse files Browse the repository at this point in the history
  • Loading branch information
dfreier authored and marcbachmann committed Feb 28, 2024
1 parent 33241bd commit c234c7e
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 2 deletions.
76 changes: 76 additions & 0 deletions spec/content.spec.js
Expand Up @@ -626,6 +626,82 @@ describe('Content', function () {
expect(result).to.equal('ac')
})

describe('trim leading white space', function () {
it('removes single regular whitespace', function () {
const element = createElement('<div> hello world</div>')
const result = content.extractContent(element)
expect(result).to.equal('hello world')
})

it('removes multiple regular whitespaces', function () {
const element = createElement('<div> hello world</div>')
const result = content.extractContent(element)
expect(result).to.equal('hello world')
})

it('removes &nbsp;', function () {
const element = createElement('<div>&nbsp; &nbsp;hello world</div>')
const result = content.extractContent(element)
expect(result).to.equal('hello world')
})

it('removes multiple regular whitespaces before tag', function () {
const element = createElement('<div> <strong>hello world</strong></div>')
const result = content.extractContent(element)
expect(result).to.equal('<strong>hello world</strong>')
})

it('removes &nbsp; before tag', function () {
const element = createElement('<div>&nbsp;<strong>hello world</strong></div>')
const result = content.extractContent(element)
expect(result).to.equal('<strong>hello world</strong>')
})

it('keeps whitespace within tag', function () {
const element = createElement('<div>&nbsp;<strong> hello world</strong></div>')
const result = content.extractContent(element)
expect(result).to.equal('<strong> hello world</strong>')
})
})

describe('trim trailing white space', function () {
it('removes single regular whitespace', function () {
const element = createElement('<div>hello world </div>')
const result = content.extractContent(element)
expect(result).to.equal('hello world')
})

it('removes multiple regular whitespaces', function () {
const element = createElement('<div>hello world </div>')
const result = content.extractContent(element)
expect(result).to.equal('hello world')
})

it('removes &nbsp;', function () {
const element = createElement('<div>hello world&nbsp; &nbsp;</div>')
const result = content.extractContent(element)
expect(result).to.equal('hello world')
})

it('removes multiple regular whitespaces after tag', function () {
const element = createElement('<div><strong>hello world</strong> </div>')
const result = content.extractContent(element)
expect(result).to.equal('<strong>hello world</strong>')
})

it('removes &nbsp; after tag', function () {
const element = createElement('<div><strong>hello world</strong>&nbsp;</div>')
const result = content.extractContent(element)
expect(result).to.equal('<strong>hello world</strong>')
})

it('keeps whitespace within tag', function () {
const element = createElement('<div><strong>hello world </strong>&nbsp;</div>')
const result = content.extractContent(element)
expect(result).to.equal('<strong>hello world </strong>')
})
})

describe('called with keepUiElements', function () {

it('does not unwrap a "ui-unwrap" span', function () {
Expand Down
17 changes: 15 additions & 2 deletions src/content.js
Expand Up @@ -15,6 +15,10 @@ const zeroWidthSpace = /\u200B/g
const zeroWidthNonBreakingSpace = /\uFEFF/g
const whitespaceExceptSpace = /[^\S ]/g

const everythingWhitespace = /^\s+$/
const leadingWhitespace = /^\s+/
const trailingWhitespace = /\s+$/

// Clean up the Html.
export function tidyHtml (element) {
// if (element.normalize) element.normalize()
Expand Down Expand Up @@ -143,25 +147,34 @@ export function cloneRangeContents (range) {

function removeWhitespaces (node, type, firstCall = true) {
let elem
// loop through all children:
// from left to right if type = 'firstChild',
// from right to left if type = 'lastChild'
while ((elem = node[type])) {
if (elem.nodeType === nodeType.textNode) {
if (/^\s+$/.test(elem.textContent)) node.removeChild(elem)
// Just remove text nodes if they consist only of whitespace
if (everythingWhitespace.test(elem.textContent)) node.removeChild(elem)
else break
} else if (elem.nodeName === 'BR') {
elem.remove()
} else {
// For element nodes (e.g. <strong> tags), we repeat the logic recursively
// to remove empty text nodes or <br> tags.
if (elem[type]) removeWhitespaces(elem, type, false)
break
}
}

// Text nodes with leading/trailing whitespace can be trimmed if config allows.
// We only do it to the outermost text node. Once a text was wrapped in
// another element, we preserve the whitespace.
if (!firstCall) return
elem = node[type]
if (elem?.nodeType !== nodeType.textNode) return
// Remove whitespaces at the end or start of a block with content
// e.g. ' Hello world' > 'Hello World'
if (config.trimLeadingAndTrailingWhitespaces) {
elem.textContent = elem.textContent.replace(type.startsWith('last') ? / +$/ : /^ +/, '')
elem.textContent = elem.textContent.replace(type.startsWith('last') ? trailingWhitespace : leadingWhitespace, '')
}
}

Expand Down

0 comments on commit c234c7e

Please sign in to comment.