diff --git a/README.md b/README.md index b07da54..71e8ec0 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ $(document).ready(function() { If your needs cool style, add styles by taste: ```css /* for block of numbers */ -.hljs-ln td.hljs-ln-numbers { +.hljs-ln-numbers { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; @@ -70,7 +70,7 @@ If your needs cool style, add styles by taste: } /* for block of code */ -.hljs-ln td.hljs-ln-code { +.hljs-ln-code { padding-left: 10px; } ``` @@ -95,5 +95,19 @@ hljs.initLineNumbersOnLoad({ hljs.lineNumbersBlock(myCodeBlock, myOptions); ``` +## CSS selectors + +You may need to select some lines of code after rendering. For instance, you may want +to highlight a range of lines, selected by users, by changing their background color. +The CSS selectors below can be used to perform these selection operations. + +CSS selector | description +-----------------------------------------|----------------------- +`.hljs-ln-line` | Select all lines, including line numbers +`.hljs-ln-numbers` | Select all line numbers, excluding lines of code +`.hljs-ln-code` | Select all lines of code, excluding line numbers +`.hljs-ln-line[data-line-number="i"]` | Select the ith line, including line number +`.hljs-ln-numbers[data-line-number="i"]` | Select the ith line number, excluding the line of code +`.hljs-ln-code[data-line-number="i"]` | Select the ith line of code, excluding the line number --- © 2018 Yauheni Pakala | MIT License diff --git a/src/highlightjs-line-numbers.js b/src/highlightjs-line-numbers.js index b2613ff..c1f98ff 100644 --- a/src/highlightjs-line-numbers.js +++ b/src/highlightjs-line-numbers.js @@ -21,6 +21,113 @@ w.console.error('highlight.js not detected!'); } + function isHljsLnCodeDescendant(domElt) { + var curElt = domElt; + while (curElt) { + if (curElt.className && curElt.className.indexOf('hljs-ln-code') !== -1) { + return true; + } + curElt = curElt.parentNode; + } + return false; + } + + function getHljsLnTable(hljsLnDomElt) { + var curElt = hljsLnDomElt; + while (curElt.nodeName !== 'TABLE') { + curElt = curElt.parentNode; + } + return curElt; + } + + // Function to workaround a copy issue with Microsoft Edge. + // Due to hljs-ln wrapping the lines of code inside a
element wrapping the first line of selected code + var tdAnchor = selection.anchorNode; + while (tdAnchor.nodeName !== 'TD') { + tdAnchor = tdAnchor.parentNode; + } + + // get the | element wrapping the last line of selected code + var tdFocus = selection.focusNode; + while (tdFocus.nodeName !== 'TD') { + tdFocus = tdFocus.parentNode; + } + + // extract line numbers + var firstLineNumber = parseInt(tdAnchor.dataset.lineNumber); + var lastLineNumber = parseInt(tdFocus.dataset.lineNumber); + + // multi-lines copied case + if (firstLineNumber != lastLineNumber) { + + var firstLineText = tdAnchor.textContent; + var lastLineText = tdFocus.textContent; + + // if the selection was made backward, swap values + if (firstLineNumber > lastLineNumber) { + var tmp = firstLineNumber; + firstLineNumber = lastLineNumber; + lastLineNumber = tmp; + tmp = firstLineText; + firstLineText = lastLineText; + lastLineText = tmp; + } + + // discard not copied characters in first line + while (selectionText.indexOf(firstLineText) !== 0) { + firstLineText = firstLineText.slice(1); + } + + // discard not copied characters in last line + while (selectionText.lastIndexOf(lastLineText) === -1) { + lastLineText = lastLineText.slice(0, -1); + } + + // reconstruct and return the real copied text + var selectedText = firstLineText; + var hljsLnTable = getHljsLnTable(tdAnchor); + for (var i = firstLineNumber + 1 ; i < lastLineNumber ; ++i) { + var codeLineSel = format('.{0}[{1}="{2}"]', [CODE_BLOCK_NAME, DATA_ATTR_NAME, i]); + var codeLineElt = hljsLnTable.querySelector(codeLineSel); + selectedText += '\n' + codeLineElt.textContent; + } + selectedText += '\n' + lastLineText; + return selectedText; + // single copied line case + } else { + return selectionText; + } + } + + // ensure consistent code copy/paste behavior across all browsers + // (see https://github.com/wcoder/highlightjs-line-numbers.js/issues/51) + document.addEventListener('copy', function(e) { + // get current selection + var selection = window.getSelection(); + // override behavior when one wants to copy line of codes + if (isHljsLnCodeDescendant(selection.anchorNode)) { + var selectionText; + // workaround an issue with Microsoft Edge as copied line breaks + // are removed otherwise from the selection string + if (window.navigator.userAgent.indexOf("Edge") !== -1) { + selectionText = edgeGetSelectedCodeLines(selection); + } else { + // other browsers can directly use the selection string + selectionText = selection.toString(); + } + e.clipboardData.setData('text/plain', selectionText); + e.preventDefault(); + } + }); + function addStyles () { var css = d.createElement('style'); css.type = 'text/css'; @@ -106,16 +213,16 @@ for (var i = 0, l = lines.length; i < l; i++) { html += format( ' | ||
' + - '' + + ' | ' + + '' + ' | ' + - '' +
- ' {6} ' +
+ ' | ' + + '{6}' + ' | ' + '