Skip to content

Commit 1ae93ac

Browse files
authored
Fix whitespace collapsing
1 parent 5376351 commit 1ae93ac

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

src/paste-markdown-html.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ function onPaste(event: ClipboardEvent) {
3838
// Get the plaintext and html version of clipboard contents
3939
let plaintext = transfer.getData('text/plain')
4040
const textHTML = transfer.getData('text/html')
41-
// Replace Unicode equivalent of "&nbsp" with a space
42-
const textHTMLClean = textHTML.replace(/\u00A0/g, ' ').replace(/\uC2A0/g, ' ')
41+
42+
const textHTMLClean = normalizeHtmlWhitespace(textHTML)
4343
if (!textHTML) return
4444

4545
plaintext = plaintext.trim()
@@ -161,13 +161,20 @@ function hasHTML(transfer: DataTransfer): boolean {
161161
return transfer.types.includes('text/html')
162162
}
163163

164-
function stripLineBreaks(text: string): string {
165-
return text.replace(/[\t\n\r ]+/g, ' ')
164+
/** Collapse whitespace in HTML to normalize it with the plain-text representation. Also convert nbsp into regular space. */
165+
function normalizeHtmlWhitespace(text: string): string {
166+
// Collapse regular whitespace characters but preserve non-breaking spaces without collapsing
167+
return text
168+
.replace(/[\t\n\r ]+/g, ' ')
169+
.trim()
170+
.replace(/[\u00A0\uC2A0]/g, ' ')
166171
}
167172

168173
// Makes markdown link from a link element, avoiding special GitHub links
169174
function linkify(element: HTMLAnchorElement): string {
170-
const label = stripLineBreaks(element.textContent ?? '')
175+
// Inline tags can have hard linebreaks in HTML, but not in Markdown, so we must collapse them to one line
176+
const label = element.textContent ?? ''
177+
171178
const url = element.href || ''
172179
let markdown = ''
173180

@@ -186,8 +193,7 @@ function linkify(element: HTMLAnchorElement): string {
186193
}
187194

188195
function simpleInlineTag(element: Node, markdownBuilder: (text: string) => string): string {
189-
const text = stripLineBreaks(element.textContent ?? '')
190-
return markdownBuilder(text)
196+
return markdownBuilder(element.textContent ?? '')
191197
}
192198

193199
// Special GitHub links have either a hover card or certain class name

test/test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,16 @@ describe('paste-markdown', function () {
342342
assert.equal(textarea.value, markdownSentence)
343343
})
344344

345+
it('deals with link labels that contain `br` elements', function () {
346+
// eslint-disable-next-line github/unescaped-html-literal
347+
const sentence = '<a href="https://example.com/">foo<br />bar</a>'
348+
const plaintextSentence = 'foo bar'
349+
const markdownSentence = '[foo bar](https://example.com/)'
350+
351+
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
352+
assert.equal(textarea.value, markdownSentence)
353+
})
354+
345355
it("doesn't render any markdown for html link without corresponding plaintext", function () {
346356
// eslint-disable-next-line github/unescaped-html-literal
347357
const link = `<meta charset='utf-8'><a href="https://github.com/monalisa/playground/issues/1">

0 commit comments

Comments
 (0)