Skip to content

Commit 4491e12

Browse files
committed
Bring back copy Markdown to clipboard functionality
This was enabled by default, but didn't work perfectly for our use-cases. This brings it back in off-by-default mode so it can be enabled and experimented with. Basically undoes 550e43a
1 parent 5f74a7c commit 4491e12

3 files changed

Lines changed: 52 additions & 3 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@ This sets up a keyboard event handler so that selecting any text within `.my-quo
3030
```js
3131
install(element, {
3232
quoteMarkdown: true,
33+
copyMarkdown: false,
3334
scopeSelector: '.comment-body'
3435
})
3536
```
3637

3738
The optional `scopeSelector` parameter ensures that even if the user selection bleeds outside of the scoped element, the quoted portion will always be contained inside the scope. This is useful to avoid accidentally quoting parts of the UI that might be interspersed between quotable content.
3839

40+
In `copyMarkdown: true` mode, the browser clipboard copy action is intercepted for user selections within `element` and the Markdown representation of the content is placed on clipboard under the `text/x-gfm` MIME-type.
41+
3942
## Events
4043

4144
* `quote-selection-markdown` (bubbles: true, cancelable: false) - fired on the quote region to optionally inject custom syntax into the `fragment` element in `quoteMarkdown: true` mode

quote-selection.js

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ const edgeBrowser = /\bEdge\//.test(navigator.userAgent)
99

1010
type ConfigOptions = {|
1111
quoteMarkdown?: boolean,
12+
copyMarkdown?: boolean,
1213
scopeSelector?: string
1314
|}
1415

1516
type ContainerConfig = {|
1617
quoteMarkdown: boolean,
18+
copyMarkdown: boolean,
1719
scopeSelector: string
1820
|}
1921

@@ -33,19 +35,62 @@ export function subscribe(container: Element, options?: ConfigOptions): Subscrip
3335
export function install(container: Element, options?: ConfigOptions) {
3436
const firstInstall = installed === 0
3537
installed += containers.has(container) ? 0 : 1
36-
const config: ContainerConfig = Object.assign({quoteMarkdown: false, scopeSelector: ''}, options)
38+
const config: ContainerConfig = Object.assign(
39+
{
40+
quoteMarkdown: false,
41+
copyMarkdown: false,
42+
scopeSelector: ''
43+
},
44+
options
45+
)
3746
containers.set(container, config)
3847
if (firstInstall) {
3948
document.addEventListener('keydown', quoteSelection)
4049
}
50+
if (config.copyMarkdown) {
51+
container.addEventListener('copy', onCopy)
52+
}
4153
}
4254

4355
export function uninstall(container: Element) {
44-
installed -= containers.has(container) ? 1 : 0
56+
const config = containers.get(container)
57+
if (config == null) return
4558
containers.delete(container)
46-
if (!installed) {
59+
installed -= 1
60+
if (installed === 0) {
4761
document.removeEventListener('keydown', quoteSelection)
4862
}
63+
if (config.copyMarkdown) {
64+
container.removeEventListener('copy', onCopy)
65+
}
66+
}
67+
68+
function onCopy(event: ClipboardEvent) {
69+
const target = event.target
70+
if (!(target instanceof HTMLElement)) return
71+
if (isFormField(target)) return
72+
73+
const transfer = event.clipboardData
74+
if (!transfer) return
75+
76+
const selection = window.getSelection()
77+
let range
78+
try {
79+
range = selection.getRangeAt(0)
80+
} catch (err) {
81+
return
82+
}
83+
84+
const text = selection.toString()
85+
const quoted = extractQuote(text, range, true)
86+
if (!quoted) return
87+
88+
transfer.setData('text/plain', text)
89+
transfer.setData('text/x-gfm', quoted.selectionText)
90+
event.preventDefault()
91+
92+
selection.removeAllRanges()
93+
selection.addRange(range)
4994
}
5095

5196
function eventIsNotRelevant(event: KeyboardEvent): boolean {

quote-selection.js.flow

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
type ConfigOptions = {|
44
quoteMarkdown?: boolean,
5+
copyMarkdown?: boolean,
56
scopeSelector?: string
67
|}
78

0 commit comments

Comments
 (0)