From 983a7166b40c7c3f1446cfcff07e896e26c8af0f Mon Sep 17 00:00:00 2001 From: Davide Rizzo Date: Sat, 7 May 2022 01:29:18 +0200 Subject: [PATCH 1/2] fix: skip child nodes of links --- src/paste-markdown-html.ts | 4 +++- test/test.js | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/paste-markdown-html.ts b/src/paste-markdown-html.ts index 3283f84..58bc91e 100644 --- a/src/paste-markdown-html.ts +++ b/src/paste-markdown-html.ts @@ -30,7 +30,9 @@ 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) + const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ELEMENT, node => + node.parentNode && isLink(node.parentNode) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT + ) const markdown = convertToMarkdown(plaintext, walker) diff --git a/test/test.js b/test/test.js index 526f88a..697f05b 100644 --- a/test/test.js +++ b/test/test.js @@ -148,6 +148,18 @@ describe('paste-markdown', function () { assert.equal(textarea.value, markdownSentence) }) + it('deals with links with nested html', function () { + // eslint-disable-next-line github/unescaped-html-literal + const sentence = `foo + bar + foo bar` + const plaintextSentence = 'foo bar foo bar' + const markdownSentence = '[foo](https://example.com/) [bar](https://example.com/) foo bar' + + paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence}) + assert.equal(textarea.value, markdownSentence) + }) + it("doesn't render any markdown for html link without corresponding plaintext", function () { // eslint-disable-next-line github/unescaped-html-literal const link = ` From fd12c0f306ef6269dd2d1006b5d31362ceb16315 Mon Sep 17 00:00:00 2001 From: Davide Rizzo Date: Sat, 7 May 2022 01:32:01 +0200 Subject: [PATCH 2/2] fix: normalize whitespace in link labels --- src/paste-markdown-html.ts | 9 +++++---- test/test.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/paste-markdown-html.ts b/src/paste-markdown-html.ts index 58bc91e..ceab3a9 100644 --- a/src/paste-markdown-html.ts +++ b/src/paste-markdown-html.ts @@ -55,7 +55,9 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string { // Walk through the DOM tree while (currentNode && index < NODE_LIMIT) { index++ - const text = isLink(currentNode) ? currentNode.textContent || '' : (currentNode.firstChild as Text)?.wholeText || '' + const text = isLink(currentNode) + ? (currentNode.textContent || '').replace(/[\t\n\r ]+/g, ' ') + : (currentNode.firstChild as Text)?.wholeText || '' // No need to transform whitespace if (isEmptyString(text)) { @@ -68,7 +70,7 @@ function convertToMarkdown(plaintext: string, walker: TreeWalker): string { if (markdownFoundIndex >= 0) { if (isLink(currentNode)) { - const markdownLink = linkify(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 = @@ -99,8 +101,7 @@ function hasHTML(transfer: DataTransfer): boolean { } // Makes markdown link from a link element, avoiding special GitHub links -function linkify(element: HTMLAnchorElement): string { - const label = element.textContent || '' +function linkify(element: HTMLAnchorElement, label: string): string { const url = element.href || '' let markdown = '' diff --git a/test/test.js b/test/test.js index 697f05b..fa80458 100644 --- a/test/test.js +++ b/test/test.js @@ -160,6 +160,16 @@ describe('paste-markdown', function () { assert.equal(textarea.value, markdownSentence) }) + it('deals with link labels that contains line breaks in html', function () { + // eslint-disable-next-line github/unescaped-html-literal + const sentence = 'foo\nbar' + const plaintextSentence = 'foo bar' + const markdownSentence = '[foo bar](https://example.com/)' + + paste(textarea, {'text/html': sentence, 'text/plain': plaintextSentence}) + assert.equal(textarea.value, markdownSentence) + }) + it("doesn't render any markdown for html link without corresponding plaintext", function () { // eslint-disable-next-line github/unescaped-html-literal const link = `