Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix pasting of markdown that contain links
  • Loading branch information
Susan Were Susan Were
Susan Were authored and Susan Were committed Mar 19, 2024
commit a4ae79586881465d042b1f56b494ac7849d3835d
16 changes: 9 additions & 7 deletions src/paste-markdown-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ function onPaste(event: ClipboardEvent) {
// Generate DOM tree from HTML string
const parser = new DOMParser()
const doc = parser.parseFromString(textHTMLClean, 'text/html')
const whatToShow = navigator.userAgent.indexOf('Firefox') > -1 ? NodeFilter.SHOW_ALL : NodeFilter.SHOW_ELEMENT
const walker = doc.createTreeWalker(doc.body, whatToShow, node =>
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ALL, node =>
node.parentNode && isLink(node.parentNode) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT
)

Expand All @@ -63,18 +62,23 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string {
// Walk through the DOM tree
while (currentNode && index < NODE_LIMIT) {
index++
const currentNodeText =
navigator.userAgent.indexOf('Firefox') > -1 ? (currentNode as Text) : (currentNode.firstChild as Text)
const text = isLink(currentNode)
? (currentNode.textContent || '').replace(/[\t\n\r ]+/g, ' ')
: currentNodeText?.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
currentNode = walker.nextNode()
continue
}

// Find the index where "text" is found in "markdown" _after_ "markdownIgnoreBeforeIndex"
const markdownFoundIndex = markdown.indexOf(text, markdownIgnoreBeforeIndex)

Expand All @@ -86,8 +90,6 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string {
markdown =
markdown.slice(0, markdownFoundIndex) + markdownLink + markdown.slice(markdownFoundIndex + text.length)
markdownIgnoreBeforeIndex = markdownFoundIndex + markdownLink.length
} else {
markdownIgnoreBeforeIndex = markdownFoundIndex + text.length
}
}

Expand Down
76 changes: 76 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,82 @@ describe('paste-markdown', function () {
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)
})

it('pastes markdown with links correctly when identical labels are present', function () {
// eslint-disable-next-line github/unescaped-html-literal
const sentence = `<meta charset='utf-8'><span>
foo bar baz <a href="https://www.abcxyz.com/">bar</a></span>`
const plaintextSentence = 'foo bar baz bar'
const markdownSentence = 'foo bar baz [bar](https://www.abcxyz.com/)'

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

it('pastes markdown with line breaks and links correctly when identical labels are present', function () {
// eslint-disable-next-line github/unescaped-html-literal
const sentence = `<meta charset='utf-8'>
<p>foo bar
bar baz <a href="https://www.abcxyz.org/">bar</a> </p>
<p>baz <a href="https://www.abcxyz.com/">baz</a> foo</p>`
const plaintextSentence = 'foo bar bar baz bar baz baz foo'
const markdownSentence = 'foo bar bar baz [bar](https://www.abcxyz.org/) baz [baz](https://www.abcxyz.com/) foo'

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

it('pastes markdown with multiple links and labels correctly', function () {
// eslint-disable-next-line i18n-text/no-en
const commonSentence = 'Great example for example resources for developers'
// eslint-disable-next-line github/unescaped-html-literal
const sentence = `<meta charset='utf-8'><span>
${commonSentence}: <a href="https://www.example.com/">example</a> and <a href="https://www.example.com/">example</a>.</span>`
const plaintextSentence = `${commonSentence}: example and example.`
const markdownSentence = `${commonSentence}: [example](https://www.example.com/) and [example](https://www.example.com/).`

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

it('finds the right link when identical labels are present', function () {
// eslint-disable-next-line github/unescaped-html-literal
const sentence = `<meta charset='utf-8'><span>example<span> </span>
Expand Down