1- $ ( ( ) => {
2- $ ( ".post--content pre > code" )
3- . parent ( )
4- . each ( function ( ) {
5- const content = $ ( this ) . text ( )
6- $ ( this )
7- . wrap ( '<div style="position:relative;"></div>' )
8- . parent ( )
9- . prepend ( $ ( '<button class="copy-button button is-muted is-outlined has-margin-2">Copy</button>' )
10- . click ( function ( ) {
11- navigator . clipboard . writeText ( content ) ;
12- $ ( this ) . text ( 'Copied!' ) ;
13- setTimeout ( ( ) => { $ ( this ) . text ( 'Copy' ) ; } , 2000 ) ;
14- } ) )
1+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
2+ /**
3+ * @param {string } content
4+ * @returns {HTMLButtonElement }
5+ */
6+ const createCopyButton = ( content , isSmall = false ) => {
7+ const button = document . createElement ( 'button' ) ;
8+ button . classList . add ( 'copy-button' , 'button' , 'is-muted' , 'is-outlined' , 'has-margin-2' ) ;
9+ button . textContent = 'Copy' ;
10+
11+ if ( isSmall ) {
12+ button . classList . add ( 'is-small' ) ;
13+ }
14+
15+ button . addEventListener ( 'click' , async ( ) => {
16+ const originalButtonText = button . textContent ;
17+
18+ try {
19+ await navigator . clipboard . writeText ( content ) ;
20+ button . textContent = 'Copied!' ;
21+ }
22+ catch ( e ) {
23+ console . warn ( e ) ;
24+ button . textContent = 'Failed!' ;
25+ }
26+ finally {
27+ setTimeout ( ( ) => {
28+ button . textContent = originalButtonText ;
29+ } , 2000 ) ;
30+ }
31+ } ) ;
32+
33+ return button ;
34+ } ;
35+
36+ /**
37+ * @param {Element } element
38+ * @returns {HTMLDivElement }
39+ */
40+ const wrapRelative = ( element ) => {
41+ const wrapper = document . createElement ( 'div' ) ;
42+ wrapper . style . position = 'relative' ;
43+ wrapper . append ( element . cloneNode ( true ) ) ;
44+ element . replaceWith ( wrapper ) ;
45+ return wrapper ;
46+ } ;
47+
48+ if ( ! window . isSecureContext ) {
49+ return ;
50+ }
51+
52+ document . querySelectorAll ( '.post--content pre > code' ) . forEach ( ( child ) => {
53+ const { parentElement : element } = child ;
54+
55+ if ( ! element ) {
56+ return ;
57+ }
58+
59+ const { textContent } = element ;
60+
61+ // code blocks always have a trailing newline added
62+ const normalizedText = textContent . replace ( / \n $ / , '' ) ;
63+
64+ if ( ! normalizedText ) {
65+ return ;
66+ }
67+
68+ const numLines = normalizedText . split ( / \r ? \n / ) . length ;
69+
70+ if ( numLines < 1 ) {
71+ return ;
72+ }
73+
74+ const button = createCopyButton ( textContent , numLines === 1 ) ;
75+ const wrapper = wrapRelative ( element ) ;
76+ wrapper . prepend ( button ) ;
1577 } ) ;
16- } ) ;
78+ } ) ;
0 commit comments