Changeset View
Changeset View
Standalone View
Standalone View
assets/src/bundles/webapp/code-highlighting.js
/** | /** | ||||
* Copyright (C) 2018-2019 The Software Heritage developers | * Copyright (C) 2018-2021 The Software Heritage developers | ||||
* See the AUTHORS file at the top-level directory of this distribution | * See the AUTHORS file at the top-level directory of this distribution | ||||
* License: GNU Affero General Public License version 3, or any later version | * License: GNU Affero General Public License version 3, or any later version | ||||
* See top-level LICENSE file for more information | * See top-level LICENSE file for more information | ||||
*/ | */ | ||||
import {removeUrlFragment} from 'utils/functions'; | import {removeUrlFragment} from 'utils/functions'; | ||||
// keep track of the first highlighted line | // keep track of the first highlighted line | ||||
let firstHighlightedLine = null; | let firstHighlightedLine = null; | ||||
// highlighting color | // highlighting color | ||||
const lineHighlightColor = 'rgb(193, 255, 193)'; | const lineHighlightColor = 'rgb(193, 255, 193)'; | ||||
// function to highlight a line | // function to highlight a line | ||||
export function highlightLine(i, firstHighlighted = false) { | export function highlightLine(i, firstHighlighted = false) { | ||||
const lineTd = $(`.hljs-ln-line[data-line-number="${i}"]`); | const lineTd = $(`.hljs-ln-line[data-line-number="${i}"]`); | ||||
lineTd.css('background-color', lineHighlightColor); | lineTd.css('background-color', lineHighlightColor); | ||||
if (firstHighlighted) { | if (firstHighlighted) { | ||||
firstHighlightedLine = i; | firstHighlightedLine = i; | ||||
} | } | ||||
return lineTd; | return lineTd; | ||||
} | } | ||||
// function to highlight a range of lines | |||||
export function highlightLines(first, last) { | |||||
if (!first) { | |||||
return; | |||||
} | |||||
if (!last) { | |||||
last = first; | |||||
} | |||||
for (let i = first; i <= last; ++i) { | |||||
highlightLine(i); | |||||
} | |||||
} | |||||
// function to reset highlighting | // function to reset highlighting | ||||
export function resetHighlightedLines() { | export function resetHighlightedLines() { | ||||
firstHighlightedLine = null; | firstHighlightedLine = null; | ||||
$('.hljs-ln-line[data-line-number]').css('background-color', 'inherit'); | $('.hljs-ln-line[data-line-number]').css('background-color', 'inherit'); | ||||
} | } | ||||
export function scrollToLine(lineDomElt) { | export function scrollToLine(lineDomElt, offset = 70) { | ||||
if ($(lineDomElt).closest('.swh-content').length > 0) { | if ($(lineDomElt).closest('.swh-content').length > 0) { | ||||
$('html, body').animate({ | $('html, body').animate({ | ||||
scrollTop: $(lineDomElt).offset().top - 70 | scrollTop: $(lineDomElt).offset().top - offset | ||||
}, 500); | }, 500); | ||||
} | } | ||||
} | } | ||||
export async function highlightCode(showLineNumbers = true) { | export async function highlightCode(showLineNumbers = true) { | ||||
await import(/* webpackChunkName: "highlightjs" */ 'utils/highlightjs'); | await import(/* webpackChunkName: "highlightjs" */ 'utils/highlightjs'); | ||||
Show All 12 Lines | function parseUrlFragmentForLinesToHighlight() { | ||||
} | } | ||||
resetHighlightedLines(); | resetHighlightedLines(); | ||||
if (lines.length === 1) { | if (lines.length === 1) { | ||||
firstHighlightedLine = parseInt(lines[0]); | firstHighlightedLine = parseInt(lines[0]); | ||||
scrollToLine(highlightLine(lines[0])); | scrollToLine(highlightLine(lines[0])); | ||||
} else if (lines[0] < lines[lines.length - 1]) { | } else if (lines[0] < lines[lines.length - 1]) { | ||||
firstHighlightedLine = parseInt(lines[0]); | firstHighlightedLine = parseInt(lines[0]); | ||||
scrollToLine(highlightLine(lines[0])); | scrollToLine(highlightLine(lines[0])); | ||||
for (let i = lines[0] + 1; i <= lines[lines.length - 1]; ++i) { | highlightLines(lines[0] + 1, lines[lines.length - 1]); | ||||
highlightLine(i); | |||||
} | |||||
} | } | ||||
} | } | ||||
$(document).ready(() => { | $(document).ready(() => { | ||||
// highlight code and add line numbers | // highlight code and add line numbers | ||||
$('code').each((i, elt) => { | $('code').each((i, elt) => { | ||||
hljs.highlightElement(elt); | hljs.highlightElement(elt); | ||||
if (showLineNumbers) { | if (showLineNumbers) { | ||||
Show All 9 Lines | $(document).ready(() => { | ||||
// when the user clicks on a line number (lines range | // when the user clicks on a line number (lines range | ||||
// can also be highlighted while holding the shift key) | // can also be highlighted while holding the shift key) | ||||
$('.swh-content').click(evt => { | $('.swh-content').click(evt => { | ||||
if (evt.target.classList.contains('hljs-ln-n')) { | if (evt.target.classList.contains('hljs-ln-n')) { | ||||
const line = parseInt($(evt.target).data('line-number')); | const line = parseInt($(evt.target).data('line-number')); | ||||
if (evt.shiftKey && firstHighlightedLine && line > firstHighlightedLine) { | if (evt.shiftKey && firstHighlightedLine && line > firstHighlightedLine) { | ||||
const firstLine = firstHighlightedLine; | const firstLine = firstHighlightedLine; | ||||
resetHighlightedLines(); | resetHighlightedLines(); | ||||
for (let i = firstLine; i <= line; ++i) { | highlightLines(firstLine, line); | ||||
highlightLine(i); | |||||
} | |||||
firstHighlightedLine = firstLine; | firstHighlightedLine = firstLine; | ||||
window.location.hash = `#L${firstLine}-L${line}`; | window.location.hash = `#L${firstLine}-L${line}`; | ||||
} else { | } else { | ||||
resetHighlightedLines(); | resetHighlightedLines(); | ||||
highlightLine(line); | highlightLine(line); | ||||
window.location.hash = `#L${line}`; | window.location.hash = `#L${line}`; | ||||
scrollToLine(evt.target); | scrollToLine(evt.target); | ||||
} | } | ||||
} else if ($(evt.target).closest('.hljs-ln').length) { | } else if ($(evt.target).closest('.hljs-ln').length) { | ||||
resetHighlightedLines(); | resetHighlightedLines(); | ||||
removeUrlFragment(); | removeUrlFragment(); | ||||
} | } | ||||
}); | }); | ||||
// update lines highlighting when the url fragment changes | // update lines highlighting when the url fragment changes | ||||
$(window).on('hashchange', () => parseUrlFragmentForLinesToHighlight()); | $(window).on('hashchange', () => parseUrlFragmentForLinesToHighlight()); | ||||
// schedule lines highlighting if any as hljs.lineNumbersElement() is async | // schedule lines highlighting if any as hljs.lineNumbersElement() is async | ||||
setTimeout(() => { | setTimeout(() => { | ||||
parseUrlFragmentForLinesToHighlight(); | parseUrlFragmentForLinesToHighlight(); | ||||
}); | }); | ||||
}); | }); | ||||
} | } | ||||
export function disableCodeSelection() { | |||||
$('.swh-content').unbind(); | |||||
} |