diff --git a/static/js/theme.js b/static/js/theme.js index 77cea128b9..b51fc3294b 100644 --- a/static/js/theme.js +++ b/static/js/theme.js @@ -613,6 +613,44 @@ function initCodeClipboard(){ return actionMsg; } + document.addEventListener( 'copy', function( ev ){ + // shabby FF generates empty lines on cursor selection that we need to filter out; see #925 + var selection = document.getSelection(); + var node = selection.anchorNode; + + // in case of GC, it works without this handler; + // instead GC fails if this handler is active, because it still contains + // the line number nodes with class 'ln' in the selection, although + // they are flagged with 'user-select: none;' see https://issues.chromium.org/issues/41393366; + // so in case of GC we don't want to do anything and bail out early in below code + function selectionContainsLnClass( selection ) { + for (var i = 0; i < selection.rangeCount; i++) { + var range = selection.getRangeAt(i); + var fragment = range.cloneContents(); + if (fragment.querySelector('.ln')) { + return true; + } + } + return false; + } + + if( !selectionContainsLnClass( selection ) ){ + while( node ){ + // selection could start in a text node, so account for this as it + // obviously does not support `classList` + if( node.nodeType === Node.ELEMENT_NODE && node.classList.contains( 'highlight' ) ){ + // only do this if we are inside of a code highlight node; + // now fix FFs selection by calculating the text ourself + var text = selection.toString(); + ev.clipboardData.setData( 'text/plain', text ); + ev.preventDefault(); + break; + } + node = node.parentNode; + } + } + }); + var codeElements = document.querySelectorAll( 'code' ); for( var i = 0; i < codeElements.length; i++ ){ var code = codeElements[i];