From 13097bcacbb90a6d79a378db5d86233ae29b7805 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 15:08:26 +0800 Subject: [PATCH 01/13] Skip selections across elements --- src/libs/copy-markdown.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 6034535f90b2..27d681b82c40 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -7,7 +7,9 @@ export default event => { const container = range.commonAncestorContainer; const containerEl = container.closest ? container : container.parentNode; - if (containerEl.closest('pre')) { + // Exclude pure code selections and selections across markdown elements: + // https://github.com/sindresorhus/refined-github/issues/522#issuecomment-311271274 + if (containerEl.closest('pre') || containerEl.querySelector('.markdown-body')) { return; } From cb3638eb2e5ea3cdfe9fa45120eb749d3a73cbdd Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 16:11:50 +0800 Subject: [PATCH 02/13] Drop `g-emoji` elements --- src/libs/copy-markdown.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 27d681b82c40..2c270e000cab 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -1,6 +1,15 @@ import toMarkdown from 'to-markdown'; import copyToClipboard from 'copy-text-to-clipboard'; +const converters = [ + // Drop unnecessary elements + // is GH's emoji wrapper + { + filter: node => node.matches('g-emoji'), + replacement: content => content + } +]; + export default event => { const selection = window.getSelection(); const range = selection.getRangeAt(0); @@ -18,7 +27,11 @@ export default event => { const holder = document.createElement('div'); holder.append(range.cloneContents()); - const markdown = toMarkdown(holder.innerHTML, {gfm: true}); + + const markdown = toMarkdown(holder.innerHTML, { + converters, + gfm: true + }); copyToClipboard(markdown); }; From 5413c3d03a73a7811532cd1a6c1096cf95c41d0a Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 16:13:06 +0800 Subject: [PATCH 03/13] Drop tasks from lists --- src/libs/copy-markdown.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 2c270e000cab..8528e8b87df6 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -1,12 +1,15 @@ import toMarkdown from 'to-markdown'; import copyToClipboard from 'copy-text-to-clipboard'; +const unwrapContent = content => content; + const converters = [ // Drop unnecessary elements // is GH's emoji wrapper + // input and .handle appear in "- [ ] lists", let's not copy tasks { - filter: node => node.matches('g-emoji'), - replacement: content => content + filter: node => node.matches('g-emoji,.handle,input.task-list-item-checkbox'), + replacement: unwrapContent } ]; From 6ae8063cd148828d001086b1587e55af497a205a Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 16:56:49 +0800 Subject: [PATCH 04/13] Drop autolinks around images --- src/libs/copy-markdown.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 8528e8b87df6..24fb25c673e7 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -10,6 +10,16 @@ const converters = [ { filter: node => node.matches('g-emoji,.handle,input.task-list-item-checkbox'), replacement: unwrapContent + }, + + // Unwrap images + { + filter: node => node.tagName === 'A' && // It's a link + node.childNodes.length === 1 && // It has one child + node.firstChild.tagName === 'IMG' && // Its child is an image + node.firstChild.src === node.href, // It links to its own image + replacement: unwrapContent + }, } ]; From 23bbbff5553044d9e4d83c628c05ecd69a743a0f Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 16:57:10 +0800 Subject: [PATCH 05/13] Keep if it has width, height or align --- src/libs/copy-markdown.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 24fb25c673e7..9d29b3ddb989 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -20,6 +20,11 @@ const converters = [ node.firstChild.src === node.href, // It links to its own image replacement: unwrapContent }, + + // Keep if it's customized + { + filter: node => node.matches('img[width],img[height],img[align]'), + replacement: (content, element) => element.outerHTML } ]; From 69fc3894a0453cc91cbb3c0e4715840dde7dc557 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 16:57:38 +0800 Subject: [PATCH 06/13] Unwrap commit/issue autolinks --- src/libs/copy-markdown.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 9d29b3ddb989..84b4b20c9484 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -12,6 +12,12 @@ const converters = [ replacement: unwrapContent }, + // Unwrap commit/issue autolinks + { + filter: node => node.matches('.commit-link,.issue-link'), + replacement: (content, element) => element.href + }, + // Unwrap images { filter: node => node.tagName === 'A' && // It's a link From de2251988358785d5d27ab168ef81fda1730ffca Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 17:06:02 +0800 Subject: [PATCH 07/13] Unwrap some shortened links --- src/libs/copy-markdown.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 84b4b20c9484..7b3f2a2f53c9 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -2,6 +2,7 @@ import toMarkdown from 'to-markdown'; import copyToClipboard from 'copy-text-to-clipboard'; const unwrapContent = content => content; +const unshortenRegex = /^https:[/][/](www[.])?|[/]$/g; const converters = [ // Drop unnecessary elements @@ -14,7 +15,8 @@ const converters = [ // Unwrap commit/issue autolinks { - filter: node => node.matches('.commit-link,.issue-link'), + filter: node => node.matches('.commit-link,.issue-link') || // GH autolinks + (node.href && node.href.replace(unshortenRegex, '') === node.textContent), // Some of bfred-it/shorten-repo-url replacement: (content, element) => element.href }, From ee4c05036efe3698a60949438420691009667796 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 17:52:56 +0800 Subject: [PATCH 08/13] Wrap orphaned
  • s in their original parent This allows partial list selections. Without a parent,
  • s will be rendered inline elements by to-markdown --- src/libs/copy-markdown.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 7b3f2a2f53c9..24c5388cd647 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -54,6 +54,13 @@ export default event => { const holder = document.createElement('div'); holder.append(range.cloneContents()); + // Wrap orphaned
  • s in their original parent + if (holder.firstChild.tagName === 'LI') { + const list = document.createElement(containerEl.tagName); + list.append(...holder.childNodes); + holder.appendChild(list); + } + const markdown = toMarkdown(holder.innerHTML, { converters, gfm: true From 28bbf53724705b9faf730882b842fa26798e4cca Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 18:22:44 +0800 Subject: [PATCH 09/13] Add support for
      lists that start after 1 --- src/libs/copy-markdown.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 24c5388cd647..4353091a616e 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -33,6 +33,20 @@ const converters = [ { filter: node => node.matches('img[width],img[height],img[align]'), replacement: (content, element) => element.outerHTML + }, + + // Add support for
        lists that start after 1 + // Until https://github.com/domchristie/to-markdown/pull/187 is in + { + filter: 'li', + replacement: (content, node) => { + content = content.replace(/^\s+/, '').replace(/\n/gm, '\n '); + const parent = node.parentNode; + const index = parent.start + Array.prototype.indexOf.call(parent.children, node); + const prefix = /ol/i.test(parent.nodeName) ? index + '. ' : '* '; + + return prefix + content; + } } ]; From ad35be4cc001223a0aa9c99ba45f7ac9233f733a Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 18:35:38 +0800 Subject: [PATCH 10/13] Keep the original number of orphaned
      1. s in numbered lists --- src/libs/copy-markdown.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 4353091a616e..072a815d5236 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -69,8 +69,13 @@ export default event => { holder.append(range.cloneContents()); // Wrap orphaned
      2. s in their original parent + // And keep the their original number if (holder.firstChild.tagName === 'LI') { const list = document.createElement(containerEl.tagName); + try { + const originalLi = range.startContainer.parentNode.closest('li'); + list.start = containerEl.start + [...containerEl.children].indexOf(originalLi); + } catch (err) {} list.append(...holder.childNodes); holder.appendChild(list); } From 9bb0ad7c5172429bd731355c5200b06194322751 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 18:37:01 +0800 Subject: [PATCH 11/13] It should only prevent the original copy if it succeeds --- src/libs/copy-markdown.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 072a815d5236..573838a2c22a 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -62,9 +62,6 @@ export default event => { return; } - event.stopImmediatePropagation(); - event.preventDefault(); - const holder = document.createElement('div'); holder.append(range.cloneContents()); @@ -86,4 +83,7 @@ export default event => { }); copyToClipboard(markdown); + + event.stopImmediatePropagation(); + event.preventDefault(); }; From 75ad7c36a28fdc7827ee67e32c95a923f227e168 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Tue, 27 Jun 2017 19:15:49 +0800 Subject: [PATCH 12/13] =?UTF-8?q?Add=20tests=20=E2=9A=A1=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/libs/copy-markdown.js | 10 ++-- test/copy-markdown.js | 101 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 test/copy-markdown.js diff --git a/package.json b/package.json index 8bc522611e95..5c76996f531f 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "babel-cli": "^6.24.1", "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", "chrome-webstore-upload-cli": "^1.0.0", + "common-tags": "^1.4.0", "dot-json": "^1.0.3", "npm-run-all": "^4.0.2", "webext": "^1.9.1-with-submit.1", diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index 573838a2c22a..e14f13c44594 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -50,6 +50,11 @@ const converters = [ } ]; +export const getSmarterMarkdown = html => toMarkdown(html, { + converters, + gfm: true +}); + export default event => { const selection = window.getSelection(); const range = selection.getRangeAt(0); @@ -77,10 +82,7 @@ export default event => { holder.appendChild(list); } - const markdown = toMarkdown(holder.innerHTML, { - converters, - gfm: true - }); + const markdown = getSmarterMarkdown(holder.innerHTML); copyToClipboard(markdown); diff --git a/test/copy-markdown.js b/test/copy-markdown.js new file mode 100644 index 000000000000..6f9f44a67bd7 --- /dev/null +++ b/test/copy-markdown.js @@ -0,0 +1,101 @@ +import test from 'ava'; +import {stripIndent} from 'common-tags'; +import {getSmarterMarkdown} from '../src/libs/copy-markdown'; + +test('base markdown', t => { + t.is( + getSmarterMarkdown('this is markdown'), + '[this](url) is **markdown**' + ); +}); + +test('drop ', t => { + t.is( + getSmarterMarkdown('🔥'), + '🔥' + ); +}); + +test('drop tasks from lists', t => { + t.is( + getSmarterMarkdown(stripIndent` +
          +
        • try me out
        • +
        • test across lines
        • +
        + `), + stripIndent` + * try me out + * test across lines + ` + ); +}); + +test('drop autolinks around images', t => { + t.is( + getSmarterMarkdown(stripIndent` + + `), + stripIndent` + ![](https://camo.githubusercontent.com/7a0ef30dc39981585543e0bbd816392a52dddd8a/687474703a2f2f692e696d6775722e636f6d2f4b6361644c36472e706e67) + ` + ); +}); + +test('keep img tags if they have width, height or align', t => { + t.is( + getSmarterMarkdown(stripIndent` + copy + `), + stripIndent` + copy + ` + ); +}); + +test('drop autolinks from issue links and commit links', t => { + t.is( + getSmarterMarkdown(stripIndent` + #522 + `), + 'https://github.com/sindresorhus/refined-github/issues/522' + ); + t.is( + getSmarterMarkdown(stripIndent` + 833d598 + `), + 'https://github.com/sindresorhus/refined-github/commit/833d5984fffb18a44b83d965b397f82e0ff3085e' + ); +}); + +test('drop autolinks around some shortened links', t => { + t.is( + getSmarterMarkdown(stripIndent` +

        npmjs.com

        +

        twitter.com/bfred_it

        +

        github.com

        + `), + stripIndent` + https://www.npmjs.com/ + + https://twitter.com/bfred_it + + https://github.com/ + ` + ); +}); + +test('wrap orphaned li in their original parent', t => { + t.is( + getSmarterMarkdown(stripIndent` +
          +
        1. big lists
        2. +
        3. deserve big numbers
        4. +
        + `), + stripIndent` + 99. big lists + 100. deserve big numbers + ` + ); +}); From 06dc117e65f2c78475aab53cf469f704d45e4576 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Wed, 5 Jul 2017 22:55:41 +0800 Subject: [PATCH 13/13] Update to-markdown@3.1.0 Include ol[start] support --- package.json | 2 +- src/libs/copy-markdown.js | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/package.json b/package.json index 5c76996f531f..f3c80cf461e6 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "linkify-urls": "^1.0.2", "select-dom": "^4.1.0", "shorten-repo-url": "^1.1.0", - "to-markdown": "^3.0.4", + "to-markdown": "^3.1.0", "to-semver": "^1.1.0", "webext-dynamic-content-scripts": "^2.0.1", "webext-options-sync": "^0.11.0" diff --git a/src/libs/copy-markdown.js b/src/libs/copy-markdown.js index e14f13c44594..df953499caee 100644 --- a/src/libs/copy-markdown.js +++ b/src/libs/copy-markdown.js @@ -33,20 +33,6 @@ const converters = [ { filter: node => node.matches('img[width],img[height],img[align]'), replacement: (content, element) => element.outerHTML - }, - - // Add support for
          lists that start after 1 - // Until https://github.com/domchristie/to-markdown/pull/187 is in - { - filter: 'li', - replacement: (content, node) => { - content = content.replace(/^\s+/, '').replace(/\n/gm, '\n '); - const parent = node.parentNode; - const index = parent.start + Array.prototype.indexOf.call(parent.children, node); - const prefix = /ol/i.test(parent.nodeName) ? index + '. ' : '* '; - - return prefix + content; - } } ];