@@ -22,14 +22,16 @@ function onPaste(event: ClipboardEvent) {
2222 // Get the plaintext and html version of clipboard contents
2323 let text = transfer . getData ( 'text/plain' )
2424 const textHTML = transfer . getData ( 'text/html' )
25+ // Replace Unicode equivalent of " " with a space
26+ const textHTMLClean = textHTML . replace ( / \u00A0 / g, ' ' )
2527 if ( ! textHTML ) return
2628
2729 text = text . trim ( )
2830 if ( ! text ) return
2931
3032 // Generate DOM tree from HTML string
3133 const parser = new DOMParser ( )
32- const doc = parser . parseFromString ( textHTML , 'text/html' )
34+ const doc = parser . parseFromString ( textHTMLClean , 'text/html' )
3335
3436 const a = doc . getElementsByTagName ( 'a' )
3537 const markdown = transform ( a , text , linkify as MarkdownTransformer )
@@ -83,6 +85,43 @@ function hasHTML(transfer: DataTransfer): boolean {
8385 return transfer . types . includes ( 'text/html' )
8486}
8587
88+ // Makes markdown link from a link element, avoiding special GitHub links
8689function linkify ( element : HTMLAnchorElement ) : string {
87- return `[${ element . textContent } ](${ element . href } )`
90+ const label = element . textContent || ''
91+ const url = element . href || ''
92+ let markdown = ''
93+
94+ // Don't linkify user mentions like "@octocat"
95+ if ( isUserMention ( element ) ) {
96+ markdown = label
97+ // Don't linkify things like "#123" or commit comparisons
98+ } else if ( isSpecialLink ( element ) || areEqualLinks ( url , label ) ) {
99+ markdown = url
100+ // Otherwise, make a markdown link
101+ } else {
102+ markdown = `[${ label } ](${ url } )`
103+ }
104+
105+ return markdown
106+ }
107+
108+ // Special GitHub links have either a hover card or certain class name
109+ function isSpecialLink ( link : HTMLAnchorElement ) : boolean {
110+ return (
111+ link . className . indexOf ( 'commit-link' ) >= 0 ||
112+ ( ! ! link . getAttribute ( 'data-hovercard-type' ) && link . getAttribute ( 'data-hovercard-type' ) !== 'user' )
113+ )
114+ }
115+
116+ // Browsers sometimes copy a stray "/" at the end of a link
117+ // Also, unequal string casing shouldn't disqualify links from being equal
118+ function areEqualLinks ( link1 : string , link2 : string ) {
119+ link1 = link1 . slice ( - 1 ) === '/' ? link1 . slice ( 0 , - 1 ) : link1
120+ link2 = link2 . slice ( - 1 ) === '/' ? link2 . slice ( 0 , - 1 ) : link2
121+ return link1 . toLowerCase ( ) === link2 . toLowerCase ( )
122+ }
123+
124+ // User mentions have a "@" and a hovercard attribute of type "user"
125+ function isUserMention ( link : HTMLAnchorElement ) : boolean {
126+ return link . textContent ?. slice ( 0 , 1 ) === '@' && link . getAttribute ( 'data-hovercard-type' ) === 'user'
88127}
0 commit comments