1
+ // introduces special behavior for ShellSession
2
+
3
+ // Localization support
4
+ const messages = {
5
+ 'en' : {
6
+ 'copy' : 'Copy' ,
7
+ 'copy_to_clipboard' : 'Copy to clipboard' ,
8
+ 'copy_success' : 'Copied!' ,
9
+ 'copy_failure' : 'Failed to copy' ,
10
+ } ,
11
+ 'es' : {
12
+ 'copy' : 'Copiar' ,
13
+ 'copy_to_clipboard' : 'Copiar al portapapeles' ,
14
+ 'copy_success' : '¡Copiado!' ,
15
+ 'copy_failure' : 'Error al copiar' ,
16
+ } ,
17
+ 'de' : {
18
+ 'copy' : 'Kopieren' ,
19
+ 'copy_to_clipboard' : 'In die Zwischenablage kopieren' ,
20
+ 'copy_success' : 'Kopiert!' ,
21
+ 'copy_failure' : 'Fehler beim Kopieren' ,
22
+ }
23
+ }
24
+
25
+ let locale = 'en'
26
+ if ( document . documentElement . lang !== undefined
27
+ && messages [ document . documentElement . lang ] !== undefined ) {
28
+ locale = document . documentElement . lang
29
+ }
30
+
31
+ /**
32
+ * Set up copy/paste for code blocks
33
+ */
34
+
35
+ const runWhenDOMLoaded = cb => {
36
+ if ( document . readyState != 'loading' ) {
37
+ cb ( )
38
+ } else if ( document . addEventListener ) {
39
+ document . addEventListener ( 'DOMContentLoaded' , cb )
40
+ } else {
41
+ document . attachEvent ( 'onreadystatechange' , function ( ) {
42
+ if ( document . readyState == 'complete' ) cb ( )
43
+ } )
44
+ }
45
+ }
46
+
47
+ const codeCellId = index => `codecell${ index } `
48
+
49
+ // Clears selected text since ClipboardJS will select the text when copying
50
+ const clearSelection = ( ) => {
51
+ if ( window . getSelection ) {
52
+ window . getSelection ( ) . removeAllRanges ( )
53
+ } else if ( document . selection ) {
54
+ document . selection . empty ( )
55
+ }
56
+ }
57
+
58
+ // Changes tooltip text for two seconds, then changes it back
59
+ const temporarilyChangeTooltip = ( el , newText ) => {
60
+ const oldText = el . getAttribute ( 'data-tooltip' )
61
+ el . setAttribute ( 'data-tooltip' , newText )
62
+ setTimeout ( ( ) => el . setAttribute ( 'data-tooltip' , oldText ) , 2000 )
63
+ }
64
+
65
+ // Callback when a copy button is clicked. Will be passed the node that was clicked
66
+ // should then grab the text and replace pieces of text that shouldn't be used in output
67
+ var copyTargetText = ( trigger ) => {
68
+ var target = document . querySelector ( trigger . attributes [ 'data-clipboard-target' ] . value ) ;
69
+ var textContent = target . innerText . split ( '\n' ) ;
70
+ var copybuttonPromptText = '$ ' ; // Inserted from config
71
+ var onlyCopyPromptLines = true ; // Inserted from config
72
+ var removePrompts = true ; // Inserted from config
73
+
74
+ grandParent = target . parentElement . parentElement ;
75
+ blockType = grandParent . classList ;
76
+ if ( blockType [ 0 ] . includes ( "ShellSession" ) ) {
77
+ onlyCopyPromptLines = false ;
78
+ }
79
+
80
+ // Text content line filtering based on prompts (if a prompt text is given)
81
+ if ( copybuttonPromptText . length > 0 ) {
82
+ // If only copying prompt lines, remove all lines that don't start w/ prompt
83
+ if ( onlyCopyPromptLines ) {
84
+ linesWithPrompt = textContent . filter ( ( line ) => {
85
+ return line . startsWith ( copybuttonPromptText ) || ( line . length == 0 ) ; // Keep newlines
86
+ } ) ;
87
+ // Check to make sure we have at least one non-empty line
88
+ var nonEmptyLines = linesWithPrompt . filter ( ( line ) => { return line . length > 0 } ) ;
89
+ // If we detected lines w/ prompt, then overwrite textContent w/ those lines
90
+ if ( ( linesWithPrompt . length > 0 ) && ( nonEmptyLines . length > 0 ) ) {
91
+ textContent = linesWithPrompt ;
92
+ }
93
+ }
94
+ // Remove the starting prompt from any remaining lines
95
+ if ( removePrompts ) {
96
+ textContent . forEach ( ( line , index ) => {
97
+ if ( line . startsWith ( copybuttonPromptText ) ) {
98
+ textContent [ index ] = line . slice ( copybuttonPromptText . length ) ;
99
+ }
100
+ } ) ;
101
+ }
102
+ }
103
+ textContent = textContent . join ( '\n' ) ;
104
+ // Remove a trailing newline to avoid auto-running when pasting
105
+ if ( textContent . endsWith ( "\n" ) ) {
106
+ textContent = textContent . slice ( 0 , - 1 )
107
+ }
108
+ return textContent
109
+ }
110
+
111
+ const addCopyButtonToCodeCells = ( ) => {
112
+ // If ClipboardJS hasn't loaded, wait a bit and try again. This
113
+ // happens because we load ClipboardJS asynchronously.
114
+ if ( window . ClipboardJS === undefined ) {
115
+ setTimeout ( addCopyButtonToCodeCells , 250 )
116
+ return
117
+ }
118
+
119
+ // Add copybuttons to all of our code cells
120
+ const codeCells = document . querySelectorAll ( 'div.highlight pre' )
121
+ codeCells . forEach ( ( codeCell , index ) => {
122
+ const id = codeCellId ( index )
123
+ codeCell . setAttribute ( 'id' , id )
124
+ const pre_bg = getComputedStyle ( codeCell ) . backgroundColor ;
125
+
126
+ const clipboardButton = id =>
127
+ `<a class="copybtn o-tooltip--left" style="background-color: ${ pre_bg } " data-tooltip="${ messages [ locale ] [ 'copy' ] } " data-clipboard-target="#${ id } ">
128
+ <img src="${ DOCUMENTATION_OPTIONS . URL_ROOT } _static/copy-button.svg" alt="${ messages [ locale ] [ 'copy_to_clipboard' ] } ">
129
+ </a>`
130
+ codeCell . insertAdjacentHTML ( 'afterend' , clipboardButton ( id ) )
131
+ } )
132
+
133
+ // Initialize with a callback so we can modify the text before copy
134
+ const clipboard = new ClipboardJS ( '.copybtn' , { text : copyTargetText } )
135
+
136
+ // Update UI with error/success messages
137
+ clipboard . on ( 'success' , event => {
138
+ clearSelection ( )
139
+ temporarilyChangeTooltip ( event . trigger , messages [ locale ] [ 'copy_success' ] )
140
+ } )
141
+
142
+ clipboard . on ( 'error' , event => {
143
+ temporarilyChangeTooltip ( event . trigger , messages [ locale ] [ 'copy_failure' ] )
144
+ } )
145
+ }
146
+
147
+ runWhenDOMLoaded ( addCopyButtonToCodeCells )
0 commit comments