// Localization support const messages = { 'en': { 'copy': 'Copy', 'copy_to_clipboard': 'Copy to clipboard', 'copy_success': 'Copied!', 'copy_failure': 'Failed to copy', }, 'es' : { 'copy': 'Copiar', 'copy_to_clipboard': 'Copiar al portapapeles', 'copy_success': '¡Copiado!', 'copy_failure': 'Error al copiar', }, 'de' : { 'copy': 'Kopieren', 'copy_to_clipboard': 'In die Zwischenablage kopieren', 'copy_success': 'Kopiert!', 'copy_failure': 'Fehler beim Kopieren', } } let locale = 'en' if( document.documentElement.lang !== undefined && messages[document.documentElement.lang] !== undefined ) { locale = document.documentElement.lang } /** * Set up copy/paste for code blocks */ const runWhenDOMLoaded = cb => { if (document.readyState != 'loading') { cb() } else if (document.addEventListener) { document.addEventListener('DOMContentLoaded', cb) } else { document.attachEvent('onreadystatechange', function() { if (document.readyState == 'complete') cb() }) } } const codeCellId = index => `codecell${index}` // Clears selected text since ClipboardJS will select the text when copying const clearSelection = () => { if (window.getSelection) { window.getSelection().removeAllRanges() } else if (document.selection) { document.selection.empty() } } // Changes tooltip text for two seconds, then changes it back const temporarilyChangeTooltip = (el, newText) => { const oldText = el.getAttribute('data-tooltip') el.setAttribute('data-tooltip', newText) setTimeout(() => el.setAttribute('data-tooltip', oldText), 2000) } const addCopyButtonToCodeCells = () => { // If ClipboardJS hasn't loaded, wait a bit and try again. This // happens because we load ClipboardJS asynchronously. if (window.ClipboardJS === undefined) { setTimeout(addCopyButtonToCodeCells, 250) return } // Add copybuttons to all of our code cells const codeCells = document.querySelectorAll('div.highlight pre') codeCells.forEach((codeCell, index) => { const id = codeCellId(index) codeCell.setAttribute('id', id) const pre_bg = getComputedStyle(codeCell).backgroundColor; const clipboardButton = id => ` ${messages[locale]['copy_to_clipboard']} ` codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) }) function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } // Callback when a copy button is clicked. Will be passed the node that was clicked // should then grab the text and replace pieces of text that shouldn't be used in output function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true) { var regexp; var match; // create regexp to capture prompt and remaining line if (isRegexp) { regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') } else { regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') } const outputLines = []; var promptFound = false; for (const line of textContent.split('\n')) { match = line.match(regexp) if (match) { promptFound = true if (removePrompts) { outputLines.push(match[2]) } else { outputLines.push(line) } } else { if (!onlyCopyPromptLines) { outputLines.push(line) } } } // If no lines with the prompt were found then just use original lines if (promptFound) { textContent = outputLines.join('\n'); } // Remove a trailing newline to avoid auto-running when pasting if (textContent.endsWith("\n")) { textContent = textContent.slice(0, -1) } return textContent } var copyTargetText = (trigger) => { var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); return formatCopyText(target.innerText, '$ ', false, true, true) } // Initialize with a callback so we can modify the text before copy const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) // Update UI with error/success messages clipboard.on('success', event => { clearSelection() temporarilyChangeTooltip(event.trigger, messages[locale]['copy_success']) }) clipboard.on('error', event => { temporarilyChangeTooltip(event.trigger, messages[locale]['copy_failure']) }) } runWhenDOMLoaded(addCopyButtonToCodeCells)