diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "file-loader": "^3.0.1", "font-awesome": "^4.7.0", "highlight.js": "^9.15.6", - "highlightjs-line-numbers.js": "^2.6.0", + "highlightjs-line-numbers.js": "^2.7.0", "iframe-resizer": "^4.0.4", "imports-loader": "^0.8.0", "jquery": "^3.3.1", diff --git a/swh/web/assets/config/webpack.config.development.js b/swh/web/assets/config/webpack.config.development.js --- a/swh/web/assets/config/webpack.config.development.js +++ b/swh/web/assets/config/webpack.config.development.js @@ -364,10 +364,6 @@ './node_modules/admin-lte/dist/js/adminlte.js' }, licenseOverride: { - './swh/web/assets/src/thirdparty/highlightjs-line-numbers/highlightjs-line-numbers.js': { - 'spdxLicenseExpression': 'MIT', - 'licenseFilePath': './swh/web/assets/src/thirdparty/highlightjs-line-numbers/LICENSE' - }, './swh/web/assets/src/thirdparty/jquery.tabSlideOut/jquery.tabSlideOut.js': { 'spdxLicenseExpression': 'GPL-3.0', 'licenseFilePath': './swh/web/assets/src/thirdparty/jquery.tabSlideOut/LICENSE' diff --git a/swh/web/assets/src/bundles/revision/diff-utils.js b/swh/web/assets/src/bundles/revision/diff-utils.js --- a/swh/web/assets/src/bundles/revision/diff-utils.js +++ b/swh/web/assets/src/bundles/revision/diff-utils.js @@ -65,11 +65,6 @@ return ret; } -function adjustCodeBlockLeftMargin(diffElt) { - let left = $(diffElt).find('.hljs-ln-numbers-container').width(); - $(diffElt).find('.hljs-ln-code-container').css('margin-left', left + 'px'); -} - // to compute diff and process it for display export function computeDiff(diffUrl, diffId) { @@ -144,10 +139,8 @@ let diffToStr = ''; let linesOffset = 0; - let codeLineElts = $(`#${diffId} .hljs-ln-code-container`).children(); - $(`#${diffId} .hljs-ln-numbers`).each((i, lnElt) => { - let lnText = $(codeLineElts[i]).text(); + let lnText = lnElt.nextSibling.innerText; let linesInfo = linesInfoRegExp.exec(lnText); let fromLine = ''; let toLine = ''; @@ -218,55 +211,45 @@ hljs.lineNumbersBlock(block); }); - function highlightDiffLines(diffId) { - let codeLineElts = $(`#${diffId} .hljs-ln-code-container`).children(); - $(`#${diffId} .hljs-ln-numbers`).each((i, lnElt) => { - let lnTextElt = codeLineElts[i]; - let lnText = $(lnTextElt).text(); + // hljs.lineNumbersBlock is asynchronous so we have to postpone our + // next treatments by adding it at the end of the current js events queue + setTimeout(() => { + // diff highlighting for added/removed lines on top of code highlighting + $(`.${diffId} .hljs-ln-numbers`).each((i, lnElt) => { + let lnText = lnElt.nextSibling.innerText; let linesInfo = linesInfoRegExp.exec(lnText); if (linesInfo) { - $(lnElt).addClass('swh-diff-lines-info'); - $(lnTextElt).addClass('swh-diff-lines-info'); - $(lnTextElt).text(''); - $(lnTextElt).append(`${lnText}`); + $(lnElt).parent().addClass('swh-diff-lines-info'); + let linesInfoText = $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').text(); + $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').children().remove(); + $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').text(''); + $(lnElt).parent().find('.hljs-ln-code .hljs-ln-line').append(`${linesInfoText}`); } else if (lnText.length > 0 && lnText[0] === '-') { - $(lnElt).addClass('swh-diff-removed-line'); - $(lnTextElt).addClass('swh-diff-removed-line'); + $(lnElt).parent().addClass('swh-diff-removed-line'); } else if (lnText.length > 0 && lnText[0] === '+') { - $(lnElt).addClass('swh-diff-added-line'); - $(lnTextElt).addClass('swh-diff-added-line'); + $(lnElt).parent().addClass('swh-diff-added-line'); } }); - } - - // hljs.lineNumbersBlock is asynchronous so we have to postpone our - // next treatments by adding it at the end of the current js events queue - setTimeout(() => { - - // diff highlighting for added/removed lines on top of code highlighting - highlightDiffLines(diffId); - highlightDiffLines(`${diffId}-from`); - highlightDiffLines(`${diffId}-to`); // set line numbers for unified diff - $(`#${diffId} .hljs-ln-numbers .hljs-ln-n`).each((i, lnElt) => { - $(lnElt).attr( + $(`#${diffId} .hljs-ln-numbers`).each((i, lnElt) => { + $(lnElt).children().attr( 'data-line-number', formatDiffLineNumbers(fromToLines[i][0], fromToLines[i][1], maxNumberChars)); }); // set line numbers for the from side-by-side diff - $(`#${diffId}-from .hljs-ln-numbers .hljs-ln-n`).each((i, lnElt) => { - $(lnElt).attr( + $(`#${diffId}-from .hljs-ln-numbers`).each((i, lnElt) => { + $(lnElt).children().attr( 'data-line-number', formatDiffLineNumbers(fromLines[i], null, maxNumberChars)); }); // set line numbers for the to side-by-side diff - $(`#${diffId}-to .hljs-ln-numbers .hljs-ln-n`).each((i, lnElt) => { - $(lnElt).attr( + $(`#${diffId}-to .hljs-ln-numbers`).each((i, lnElt) => { + $(lnElt).children().attr( 'data-line-number', formatDiffLineNumbers(null, toLines[i], maxNumberChars)); @@ -305,8 +288,6 @@ setDiffVisible(diffId); - adjustCodeBlockLeftMargin(`#${diffId}`); - }); }); } @@ -429,8 +410,6 @@ export function showSplittedDiff(event, diffId) { $(`#${diffId}-unified-diff`).css('display', 'none'); $(`#${diffId}-splitted-diff`).css('display', 'block'); - adjustCodeBlockLeftMargin(`#${diffId}-from`); - adjustCodeBlockLeftMargin(`#${diffId}-to`); } // callback when the user clicks on the 'Compute all diffs' button diff --git a/swh/web/assets/src/thirdparty/highlightjs-line-numbers/LICENSE b/swh/web/assets/src/thirdparty/highlightjs-line-numbers/LICENSE deleted file mode 100644 --- a/swh/web/assets/src/thirdparty/highlightjs-line-numbers/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Yauheni Pakala - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/swh/web/assets/src/thirdparty/highlightjs-line-numbers/highlightjs-line-numbers.js b/swh/web/assets/src/thirdparty/highlightjs-line-numbers/highlightjs-line-numbers.js deleted file mode 100644 --- a/swh/web/assets/src/thirdparty/highlightjs-line-numbers/highlightjs-line-numbers.js +++ /dev/null @@ -1,260 +0,0 @@ -// jshint multistr:true - -(function (w, d) { - 'use strict'; - - var TABLE_NAME = 'hljs-ln', - LINE_NAME = 'hljs-ln-line', - NUMBERS_CONTAINER_NAME = 'hljs-ln-numbers-container', - CODE_CONTAINER_NAME = 'hljs-ln-code-container', - CODE_BLOCK_NAME = 'hljs-ln-code', - NUMBERS_BLOCK_NAME = 'hljs-ln-numbers', - NUMBER_LINE_NAME = 'hljs-ln-n', - DATA_ATTR_NAME = 'data-line-number', - BREAK_LINE_REGEXP = /\r\n|\r|\n/g; - - var resizeHandlerSet = false; - - if (w.hljs) { - w.hljs.initLineNumbersOnLoad = initLineNumbersOnLoad; - w.hljs.lineNumbersBlock = lineNumbersBlock; - w.hljs.lineNumbersValue = lineNumbersValue; - - addStyles(); - } else { - w.console.error('highlight.js not detected!'); - } - - function addStyles () { - var css = d.createElement('style'); - css.type = 'text/css'; - css.innerHTML = format( - '.{0} table{float:left; border-collapse:collapse}' + - '.{0} table td{padding:0}' + - '.{1}::before{content:attr({2})}' + - '.{3}::before{content: "\\200B"}', // force display of empty lines of code - [ - TABLE_NAME, - NUMBER_LINE_NAME, - DATA_ATTR_NAME, - CODE_BLOCK_NAME - ]); - d.getElementsByTagName('head')[0].appendChild(css); - } - - function initLineNumbersOnLoad (options) { - if (d.readyState === 'interactive' || d.readyState === 'complete') { - documentReady(options); - } else { - w.addEventListener('DOMContentLoaded', function () { - documentReady(options); - }); - } - } - - function documentReady (options) { - try { - var blocks = d.querySelectorAll('code.hljs,code.nohighlight'); - - for (var i in blocks) { - if (blocks.hasOwnProperty(i)) { - lineNumbersBlock(blocks[i], options); - } - } - } catch (e) { - w.console.error('LineNumbers error: ', e); - } - } - - function adjustLineNumbersHeights(element) { - var lnNumbers = element.querySelectorAll('.' + NUMBERS_BLOCK_NAME); - var lnCode = element.querySelectorAll('.' + CODE_BLOCK_NAME); - - for (var i = 0 ; i < lnNumbers.length; ++i) { - lnNumbers[i].style.height = lnCode[i].offsetHeight + 'px'; - } - } - - function lineNumbersBlock (element, options) { - if (typeof element !== 'object') return; - async(function () { - element.innerHTML = lineNumbersInternal(element, options); - // adjust left margin of code div as line numbers is a float left dom element - var lineNumbersContainer = element.querySelector('.' + NUMBERS_CONTAINER_NAME); - if (lineNumbersContainer) { - var codeMargin = lineNumbersContainer.offsetWidth; - var codeContainerStyle = 'margin-left:' + codeMargin + 'px'; - var codeContainer = element.querySelector('.' + CODE_CONTAINER_NAME); - codeContainer.style.cssText = codeContainerStyle; - - // adjust each line number cell height to the one of the div containing - // the wrapped line of code and set a handler to execute this - // operation when the browser window gets resized. - adjustLineNumbersHeights(element); - if (!resizeHandlerSet) { - window.addEventListener('resize', function() { - var hljsLnElts = document.querySelectorAll('.' + TABLE_NAME); - for (var i = 0 ; i < hljsLnElts.length; ++i) { - adjustLineNumbersHeights(hljsLnElts[i]); - } - }); - resizeHandlerSet = true; - } - } - }); - } - - function lineNumbersValue (value, options) { - if (typeof value !== 'string') return; - - var element = document.createElement('code') - element.innerHTML = value - - return lineNumbersInternal(element, options); - } - - function lineNumbersInternal (element, options) { - // define options or set default - options = options || { - singleLine: false - }; - - // convert options - var firstLineIndex = !!options.singleLine ? 0 : 1; - - duplicateMultilineNodes(element); - - return addLineNumbersBlockFor(element.innerHTML, firstLineIndex); - } - - function addLineNumbersBlockFor (inputHtml, firstLineIndex) { - - var lines = getLines(inputHtml); - - // if last line contains only carriage return remove it - if (lines[lines.length-1].trim() === '') { - lines.pop(); - } - - if (lines.length > firstLineIndex) { - // Previous implementation was using a single table element - // to render the line numbers and the lines of code. - // But to overcome an annoying copy/paste behavior when using Firefox or Edge - // (see https://github.com/wcoder/highlightjs-line-numbers.js/issues/51) - // the following workaround is used while obtaining the exact same rendering - // as before: - // 1. render the lines number in a table with single column - // 2. render the lines of code in a div - // 3. wrap these in a div and make the table float left - // 4. adjust the left margin of the code div once inserted in the dom - var htmlLinesNumber = ''; - var htmlCode = ''; - - for (var i = 0, l = lines.length; i < l; i++) { - htmlLinesNumber += format( - '' + - '' + - '
' + - '' + - '', - [ - LINE_NAME, - NUMBERS_BLOCK_NAME, - NUMBER_LINE_NAME, - DATA_ATTR_NAME, - i + 1 - ]); - - htmlCode += format( - '
{4}
', - [ - LINE_NAME, - CODE_BLOCK_NAME, - DATA_ATTR_NAME, - i + 1, - lines[i].length > 0 ? lines[i] : ' ' - ]); - } - - return format( - '
' + - '{2}
' + - '
{4}
' + - '
', - [ - TABLE_NAME, - NUMBERS_CONTAINER_NAME, - htmlLinesNumber, - CODE_CONTAINER_NAME, - htmlCode - ]); - } - - return inputHtml; - } - - /** - * Recursive method for fix multi-line elements implementation in highlight.js - * Doing deep passage on child nodes. - * @param {HTMLElement} element - */ - function duplicateMultilineNodes (element) { - var nodes = element.childNodes; - for (var node in nodes) { - if (nodes.hasOwnProperty(node)) { - var child = nodes[node]; - if (getLinesCount(child.textContent) > 0) { - if (child.childNodes.length > 0) { - duplicateMultilineNodes(child); - } else { - duplicateMultilineNode(child.parentNode); - } - } - } - } - } - - /** - * Method for fix multi-line elements implementation in highlight.js - * @param {HTMLElement} element - */ - function duplicateMultilineNode (element) { - var className = element.className; - - if ( ! /hljs-/.test(className)) return; - - var lines = getLines(element.innerHTML); - - for (var i = 0, result = ''; i < lines.length; i++) { - var lineText = lines[i].length > 0 ? lines[i] : ' '; - result += format('{1}\n', [ className, lineText ]); - } - - element.innerHTML = result.trim(); - } - - function getLines (text) { - if (text.length === 0) return []; - return text.split(BREAK_LINE_REGEXP); - } - - function getLinesCount (text) { - return (text.trim().match(BREAK_LINE_REGEXP) || []).length; - } - - function async (func) { - w.setTimeout(func, 0); - } - - /** - * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript} - * @param {string} format - * @param {array} args - */ - function format (format, args) { - return format.replace(/\{(\d+)\}/g, function(m, n){ - return args[n] ? args[n] : m; - }); - } - -}(window, document)); diff --git a/swh/web/assets/src/utils/highlightjs.css b/swh/web/assets/src/utils/highlightjs.css --- a/swh/web/assets/src/utils/highlightjs.css +++ b/swh/web/assets/src/utils/highlightjs.css @@ -24,7 +24,7 @@ color: #aaa; border-right: 1px solid #ccc; vertical-align: top; - padding-right: 5px !important; + padding-right: 1px !important; } /* for block of code */ diff --git a/swh/web/assets/src/utils/highlightjs.js b/swh/web/assets/src/utils/highlightjs.js --- a/swh/web/assets/src/utils/highlightjs.js +++ b/swh/web/assets/src/utils/highlightjs.js @@ -8,6 +8,6 @@ // highlightjs chunk that will be lazily loaded import 'highlight.js'; -import 'thirdparty/highlightjs-line-numbers/highlightjs-line-numbers'; +import 'highlightjs-line-numbers.js'; import 'highlight.js/styles/github.css'; import './highlightjs.css'; diff --git a/yarn.lock b/yarn.lock --- a/yarn.lock +++ b/yarn.lock @@ -4075,10 +4075,10 @@ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.6.tgz#72d4d8d779ec066af9a17cb14360c3def0aa57c4" integrity sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ== -highlightjs-line-numbers.js@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/highlightjs-line-numbers.js/-/highlightjs-line-numbers.js-2.6.0.tgz#daab1b0a6eeae9d742fccf1ba6b07ff9d1ff960b" - integrity sha512-Ffx42SmswE41lKHafsXT7jGhao4Rn2TN/12y3MwzBn0b1MYGSd9kpW7fpnAEhXqUdBeCtgG78tmrqhIDNc21TQ== +highlightjs-line-numbers.js@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/highlightjs-line-numbers.js/-/highlightjs-line-numbers.js-2.7.0.tgz#b202f7dc547cb9ab64d8b3ad571d834817815bdf" + integrity sha512-2kgZkfGy3TB6rF1o1XJtUThDyraLAFd6iiAIE1MEH89om8VwyHsal6BBnIOP2yOuq2TCuuGd0YD6aGHa6iq3/g== hmac-drbg@^1.0.0: version "1.0.1"