Skip to content

Commit a4ae795

Browse files
Susan WereSusan Were
authored andcommitted
fix pasting of markdown that contain links
1 parent 025f305 commit a4ae795

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

src/paste-markdown-html.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ function onPaste(event: ClipboardEvent) {
3737
// Generate DOM tree from HTML string
3838
const parser = new DOMParser()
3939
const doc = parser.parseFromString(textHTMLClean, 'text/html')
40-
const whatToShow = navigator.userAgent.indexOf('Firefox') > -1 ? NodeFilter.SHOW_ALL : NodeFilter.SHOW_ELEMENT
41-
const walker = doc.createTreeWalker(doc.body, whatToShow, node =>
40+
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ALL, node =>
4241
node.parentNode && isLink(node.parentNode) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT
4342
)
4443

@@ -63,18 +62,23 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string {
6362
// Walk through the DOM tree
6463
while (currentNode && index < NODE_LIMIT) {
6564
index++
66-
const currentNodeText =
67-
navigator.userAgent.indexOf('Firefox') > -1 ? (currentNode as Text) : (currentNode.firstChild as Text)
6865
const text = isLink(currentNode)
6966
? (currentNode.textContent || '').replace(/[\t\n\r ]+/g, ' ')
70-
: currentNodeText?.wholeText || ''
67+
: (currentNode as Text)?.wholeText || ''
7168

7269
// No need to transform whitespace
7370
if (isEmptyString(text)) {
7471
currentNode = walker.nextNode()
7572
continue
7673
}
7774

75+
// update value of markdownIgnoreBeforeIndex with current index if the current node is not a link
76+
if (!isLink(currentNode)) {
77+
markdownIgnoreBeforeIndex += text.replace(/[\t\n\r ]+/g, ' ').trimStart().length
78+
currentNode = walker.nextNode()
79+
continue
80+
}
81+
7882
// Find the index where "text" is found in "markdown" _after_ "markdownIgnoreBeforeIndex"
7983
const markdownFoundIndex = markdown.indexOf(text, markdownIgnoreBeforeIndex)
8084

@@ -86,8 +90,6 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string {
8690
markdown =
8791
markdown.slice(0, markdownFoundIndex) + markdownLink + markdown.slice(markdownFoundIndex + text.length)
8892
markdownIgnoreBeforeIndex = markdownFoundIndex + markdownLink.length
89-
} else {
90-
markdownIgnoreBeforeIndex = markdownFoundIndex + text.length
9193
}
9294
}
9395

test/test.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,82 @@ describe('paste-markdown', function () {
358358
assert.equal(textarea.value, markdownSentence)
359359
})
360360

361+
it('finds the right link when identical labels are present chrome and edge', function () {
362+
// eslint-disable-next-line github/unescaped-html-literal
363+
const sentence = `<meta charset='utf-8'>
364+
<p>foo bar<br>bar<span> </span><a href="https://www.abcxyz.org/">bar</a></p><p>bar<span> </span><a href="https://www.abcxyz.com/">bar</a><span> </span>foo</p>`
365+
366+
const markdownSentence = `foo bar
367+
bar [bar](https://www.abcxyz.org/)
368+
369+
bar [bar](https://www.abcxyz.com/) foo`
370+
371+
const plaintextSentence = `foo bar
372+
bar bar
373+
374+
bar bar foo`
375+
376+
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
377+
assert.equal(textarea.value, markdownSentence)
378+
})
379+
380+
it('finds the right link when identical labels are present firefox', function () {
381+
// eslint-disable-next-line github/unescaped-html-literal
382+
const sentence = `<meta charset='utf-8'>
383+
<div><div><p>foo bar<br>
384+
bar <a href="https://www.abcxyz.org/">bar</a></p>
385+
<p>bar <a href="https://www.abcxyz.com/">bar</a> foo</p></div></div>`
386+
const markdownSentence = `foo bar
387+
bar [bar](https://www.abcxyz.org/)
388+
389+
bar [bar](https://www.abcxyz.com/) foo`
390+
391+
const plaintextSentence = `foo bar
392+
bar bar
393+
394+
bar bar foo`
395+
396+
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
397+
assert.equal(textarea.value, markdownSentence)
398+
})
399+
400+
it('pastes markdown with links correctly when identical labels are present', function () {
401+
// eslint-disable-next-line github/unescaped-html-literal
402+
const sentence = `<meta charset='utf-8'><span>
403+
foo bar baz <a href="https://www.abcxyz.com/">bar</a></span>`
404+
const plaintextSentence = 'foo bar baz bar'
405+
const markdownSentence = 'foo bar baz [bar](https://www.abcxyz.com/)'
406+
407+
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
408+
assert.equal(textarea.value, markdownSentence)
409+
})
410+
411+
it('pastes markdown with line breaks and links correctly when identical labels are present', function () {
412+
// eslint-disable-next-line github/unescaped-html-literal
413+
const sentence = `<meta charset='utf-8'>
414+
<p>foo bar
415+
bar baz <a href="https://www.abcxyz.org/">bar</a> </p>
416+
<p>baz <a href="https://www.abcxyz.com/">baz</a> foo</p>`
417+
const plaintextSentence = 'foo bar bar baz bar baz baz foo'
418+
const markdownSentence = 'foo bar bar baz [bar](https://www.abcxyz.org/) baz [baz](https://www.abcxyz.com/) foo'
419+
420+
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
421+
assert.equal(textarea.value, markdownSentence)
422+
})
423+
424+
it('pastes markdown with multiple links and labels correctly', function () {
425+
// eslint-disable-next-line i18n-text/no-en
426+
const commonSentence = 'Great example for example resources for developers'
427+
// eslint-disable-next-line github/unescaped-html-literal
428+
const sentence = `<meta charset='utf-8'><span>
429+
${commonSentence}: <a href="https://www.example.com/">example</a> and <a href="https://www.example.com/">example</a>.</span>`
430+
const plaintextSentence = `${commonSentence}: example and example.`
431+
const markdownSentence = `${commonSentence}: [example](https://www.example.com/) and [example](https://www.example.com/).`
432+
433+
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
434+
assert.equal(textarea.value, markdownSentence)
435+
})
436+
361437
it('finds the right link when identical labels are present', function () {
362438
// eslint-disable-next-line github/unescaped-html-literal
363439
const sentence = `<meta charset='utf-8'><span>example<span> </span>

0 commit comments

Comments
 (0)