2022-01-26 12:08:38 +05:30
import { uniqueId } from 'lodash' ;
import { _ _ } from '~/locale' ;
import { spriteIcon } from '~/lib/utils/common_utils' ;
import { setAttributes } from '~/lib/utils/dom_utils' ;
class CopyCodeButton extends HTMLElement {
connectedCallback ( ) {
this . for = uniqueId ( 'code-' ) ;
2023-03-04 22:38:38 +05:30
const target = this . parentNode . querySelector ( 'pre' ) ;
if ( ! target ) return ;
target . setAttribute ( 'id' , this . for ) ;
2022-01-26 12:08:38 +05:30
this . appendChild ( this . createButton ( ) ) ;
}
createButton ( ) {
const button = document . createElement ( 'button' ) ;
setAttributes ( button , {
type : 'button' ,
class : 'btn btn-default btn-md gl-button btn-icon has-tooltip' ,
'data-title' : _ _ ( 'Copy to clipboard' ) ,
'data-clipboard-target' : ` pre# ${ this . for } ` ,
} ) ;
2022-10-11 01:57:18 +05:30
// eslint-disable-next-line no-unsanitized/property
2022-01-26 12:08:38 +05:30
button . innerHTML = spriteIcon ( 'copy-to-clipboard' ) ;
return button ;
}
}
function addCodeButton ( ) {
2022-03-02 08:16:31 +05:30
[ ... document . querySelectorAll ( 'pre.code.js-syntax-highlight:not(.content-editor-code-block)' ) ]
. filter ( ( el ) => el . getAttribute ( 'lang' ) !== 'mermaid' )
2022-01-26 12:08:38 +05:30
. filter ( ( el ) => ! el . closest ( '.js-markdown-code' ) )
. forEach ( ( el ) => {
const copyCodeEl = document . createElement ( 'copy-code' ) ;
copyCodeEl . setAttribute ( 'for' , uniqueId ( 'code-' ) ) ;
const wrapper = document . createElement ( 'div' ) ;
wrapper . className = 'gl-relative markdown-code-block js-markdown-code' ;
wrapper . appendChild ( el . cloneNode ( true ) ) ;
wrapper . appendChild ( copyCodeEl ) ;
el . parentNode . insertBefore ( wrapper , el ) ;
el . remove ( ) ;
} ) ;
}
export const initCopyCodeButton = ( selector = '#content-body' ) => {
if ( ! customElements . get ( 'copy-code' ) ) {
customElements . define ( 'copy-code' , CopyCodeButton ) ;
}
2023-01-13 00:05:48 +05:30
const exclude = document . querySelector ( '.file-content.code' ) ; // this behavior is not needed when viewing raw file content, so excluding it as the unnecessary dom lookups can become expensive
2022-01-26 12:08:38 +05:30
const el = document . querySelector ( selector ) ;
2023-01-13 00:05:48 +05:30
if ( ! el || exclude ) return ( ) => { } ;
2022-01-26 12:08:38 +05:30
const observer = new MutationObserver ( ( ) => addCodeButton ( ) ) ;
observer . observe ( document . querySelector ( selector ) , {
childList : true ,
subtree : true ,
} ) ;
return ( ) => observer . disconnect ( ) ;
} ;