Skip to content

Commit

Permalink
Merge pull request #93 from susanwere/fix-pasting-markdown-with-html
Browse files Browse the repository at this point in the history
fix pasting of markdown containing links
  • Loading branch information
keithamus authored Mar 21, 2024
2 parents 239dfc2 + 8d487f9 commit 38f2616
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 14 deletions.
27 changes: 13 additions & 14 deletions src/paste-markdown-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function onPaste(event: ClipboardEvent) {
// Generate DOM tree from HTML string
const parser = new DOMParser()
const doc = parser.parseFromString(textHTMLClean, 'text/html')
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ELEMENT, node =>
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ALL, node =>
node.parentNode && isLink(node.parentNode) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT,
)

Expand All @@ -64,15 +64,17 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string {
index++
const text = isLink(currentNode)
? (currentNode.textContent || '').replace(/[\t\n\r ]+/g, ' ')
: (currentNode.firstChild as Text)?.wholeText || ''
: (currentNode as Text)?.wholeText || ''

// No need to transform whitespace
if (isEmptyString(text)) {
currentNode = walker.nextNode()
continue
}

// update value of markdownIgnoreBeforeIndex with current index if the current node is not a link
if (!isLink(currentNode)) {
markdownIgnoreBeforeIndex += text.replace(/[\t\n\r ]+/g, ' ').trimStart().length
}

// No need to transform whitespace
if (isEmptyString(text)) {
currentNode = walker.nextNode()
continue
}
Expand All @@ -81,14 +83,11 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string {
const markdownFoundIndex = markdown.indexOf(text, markdownIgnoreBeforeIndex)

if (markdownFoundIndex >= 0) {
if (isLink(currentNode)) {
const markdownLink = linkify(currentNode, text)
// Transform 'example link plus more text' into 'example [link](example link) plus more text'
// Method: 'example [link](example link) plus more text' = 'example ' + '[link](example link)' + ' plus more text'
markdown =
markdown.slice(0, markdownFoundIndex) + markdownLink + markdown.slice(markdownFoundIndex + text.length)
markdownIgnoreBeforeIndex = markdownFoundIndex + markdownLink.length
}
const markdownLink = linkify(currentNode, text)
// Transform 'example link plus more text' into 'example [link](example link) plus more text'
// Method: 'example [link](example link) plus more text' = 'example ' + '[link](example link)' + ' plus more text'
markdown = markdown.slice(0, markdownFoundIndex) + markdownLink + markdown.slice(markdownFoundIndex + text.length)
markdownIgnoreBeforeIndex = markdownFoundIndex + markdownLink.length
}

currentNode = walker.nextNode()
Expand Down
39 changes: 39 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,45 @@ describe('paste-markdown', function () {
paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
assert.equal(textarea.value, markdownSentence)
})

it('finds the right link when identical labels are present chrome and edge', function () {
// eslint-disable-next-line github/unescaped-html-literal
const sentence = `<meta charset='utf-8'>
<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>`

const markdownSentence = `foo bar
bar [bar](https://www.abcxyz.org/)
bar [bar](https://www.abcxyz.com/) foo`

const plaintextSentence = `foo bar
bar bar
bar bar foo`

paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
assert.equal(textarea.value, markdownSentence)
})

it('finds the right link when identical labels are present firefox', function () {
// eslint-disable-next-line github/unescaped-html-literal
const sentence = `<meta charset='utf-8'>
<div><div><p>foo bar<br>
bar <a href="https://www.abcxyz.org/">bar</a></p>
<p>bar <a href="https://www.abcxyz.com/">bar</a> foo</p></div></div>`
const markdownSentence = `foo bar
bar [bar](https://www.abcxyz.org/)
bar [bar](https://www.abcxyz.com/) foo`

const plaintextSentence = `foo bar
bar bar
bar bar foo`

paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence})
assert.equal(textarea.value, markdownSentence)
})
})
})

Expand Down

0 comments on commit 38f2616

Please sign in to comment.