Server-side syntax highlighting for all code (#12047)

* Server-side syntax hilighting for all code

This PR does a few things:

* Remove all traces of highlight.js
* Use chroma library to provide fast syntax hilighting directly on the server
* Provide syntax hilighting for diffs
* Re-style both unified and split diffs views
* Add custom syntax hilighting styling for both regular and arc-green

Fixes #7729
Fixes #10157
Fixes #11825
Fixes #7728
Fixes #3872
Fixes #3682

And perhaps gets closer to #9553

* fix line marker

* fix repo search

* Fix single line select

* properly load settings

* npm uninstall highlight.js

* review suggestion

* code review

* forgot to call function

* fix test

* Apply suggestions from code review

suggestions from @silverwind thanks

Co-authored-by: silverwind <me@silverwind.io>

* code review

* copy/paste error

* Use const for highlight size limit

* Update web_src/less/_repository.less

Co-authored-by: Lauris BH <lauris@nix.lv>

* update size limit to 1MB and other styling tweaks

* fix highlighting for certain diff sections

* fix test

* add worker back as suggested

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
mrsdizzie 2020-06-30 17:34:03 -04:00 committed by GitHub
parent ce5f2b9845
commit af7ffaa279
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
336 changed files with 37293 additions and 769 deletions

View file

@ -16,7 +16,6 @@ import initMarkdownAnchors from './markdown/anchors.js';
import attachTribute from './features/tribute.js';
import createDropzone from './features/dropzone.js';
import initTableSort from './features/tablesort.js';
import highlight from './features/highlight.js';
import ActivityTopAuthors from './components/ActivityTopAuthors.vue';
import {initNotificationsTable, initNotificationCount} from './features/notification.js';
import {createCodeEditor} from './features/codeeditor.js';
@ -46,9 +45,6 @@ function initCommentPreviewTab($form) {
}, (data) => {
const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`);
$previewPanel.html(data);
$('pre code', $previewPanel[0]).each(function () {
highlight(this);
});
});
});
@ -78,9 +74,6 @@ function initEditPreviewTab($form) {
}, (data) => {
const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`);
$previewPanel.html(data);
$('pre code', $previewPanel[0]).each(function () {
highlight(this);
});
});
});
}
@ -986,9 +979,6 @@ async function initRepository() {
$renderContent.html($('#no-content').html());
} else {
$renderContent.html(data.content);
$('pre code', $renderContent[0]).each(function () {
highlight(this);
});
}
const $content = $segment.parent();
if (!$content.find('.ui.small.images').length) {
@ -1345,9 +1335,6 @@ function initWikiForm() {
wiki: true
}, (data) => {
preview.innerHTML = `<div class="markdown ui segment">${data}</div>`;
$(preview).find('pre code').each((_, e) => {
highlight(e);
});
});
};
if (!simplemde.isSideBySideActive()) {
@ -2003,27 +1990,27 @@ function searchRepositories() {
}
function initCodeView() {
if ($('.code-view .linenums').length > 0) {
if ($('.code-view .lines-num').length > 0) {
$(document).on('click', '.lines-num span', function (e) {
const $select = $(this);
const $list = $select.parent().siblings('.lines-code').find('ol.linenums > li');
const $list = $('.code-view td.lines-code');
selectRange($list, $list.filter(`[rel=${$select.attr('id')}]`), (e.shiftKey ? $list.filter('.active').eq(0) : null));
deSelect();
});
$(window).on('hashchange', () => {
let m = window.location.hash.match(/^#(L\d+)-(L\d+)$/);
const $list = $('.code-view ol.linenums > li');
const $list = $('.code-view td.lines-code');
let $first;
if (m) {
$first = $list.filter(`.${m[1]}`);
selectRange($list, $first, $list.filter(`.${m[2]}`));
$first = $list.filter(`[rel=${m[1]}]`);
selectRange($list, $first, $list.filter(`[rel=${m[2]}]`));
$('html, body').scrollTop($first.offset().top - 200);
return;
}
m = window.location.hash.match(/^#(L|n)(\d+)$/);
if (m) {
$first = $list.filter(`.L${m[2]}`);
$first = $list.filter(`[rel=L${m[2]}]`);
selectRange($list, $first);
$('html, body').scrollTop($first.offset().top - 200);
}
@ -2485,7 +2472,6 @@ $(document).ready(async () => {
// parallel init of async loaded features
await Promise.all([
highlight(document.querySelectorAll('pre code')),
attachTribute(document.querySelectorAll('#content, .emoji-input')),
initGitGraph(),
initClipboard(),
@ -2524,7 +2510,7 @@ function selectRange($list, $select, $from) {
}
const classes = [];
for (let i = a; i <= b; i++) {
classes.push(`.L${i}`);
classes.push(`[rel=L${i}]`);
}
$list.filter(classes.join(',')).addClass('active');
changeHash(`#L${a}-L${b}`);