Skip to content

Commit

Permalink
Use a web worker for syntax highlighting, drop IE11 support
Browse files Browse the repository at this point in the history
Syntax highlighting is now done in a separate thread which should help
performance on large files.

The web worker is initialized from a function which is not something
IE11 supports and which would force us to create a separate .js file
for the worker code.

For the reason above, I think it's a good opportunity to end IE11 support
with this commit, so it should be landed in the next minor release
version.

The code uses various ES2017 features and should work in all evergreen
browsers.

Fixes: go-gitea#6147
  • Loading branch information
silverwind committed Aug 3, 2019
1 parent 7d9a130 commit ababfbf
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 13 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extends:
- eslint:recommended

parserOptions:
ecmaVersion: 2015
ecmaVersion: 2017

env:
browser: true
Expand All @@ -25,3 +25,4 @@ rules:
no-unused-vars: [error, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, ignoreRestSiblings: true}]
prefer-const: [2, {destructuring: all}]
no-var: [2]
no-empty: [2, {allowEmptyCatch: true}]
6 changes: 5 additions & 1 deletion modules/highlight/highlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ var (
".ini": {},
".json": {},
".java": {},
".js": {},
".less": {},
".lua": {},
".php": {},
Expand All @@ -68,6 +67,11 @@ var (
".escript": "erlang",
".ex": "elixir",
".exs": "elixir",
".js": "javascript",
".jsx": "javascript",
".mjs": "javascript",
".ts": "typescript",
".tsx": "typescript",
}
)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
"> 1%",
"last 2 firefox versions",
"last 2 safari versions",
"ie 11"
"not ie 11"
]
}
79 changes: 70 additions & 9 deletions public/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ function initCommentPreviewTab($form) {
$previewPanel.html(data);
emojify.run($previewPanel[0]);
$('pre code', $previewPanel[0]).each(function () {
hljs.highlightBlock(this);
highlight(this);
});
}
);
Expand Down Expand Up @@ -171,7 +171,7 @@ function initEditPreviewTab($form) {
$previewPanel.html(data);
emojify.run($previewPanel[0]);
$('pre code', $previewPanel[0]).each(function () {
hljs.highlightBlock(this);
highlight(this);
});
}
);
Expand Down Expand Up @@ -862,7 +862,7 @@ function initRepository() {
$renderContent.html(data.content);
emojify.run($renderContent[0]);
$('pre code', $renderContent[0]).each(function () {
hljs.highlightBlock(this);
highlight(this);
});
}
});
Expand Down Expand Up @@ -1935,6 +1935,71 @@ function u2fRegisterRequest() {
});
}

function createWorker(fn, ...args) {
const argsString = args.map(arg => JSON.stringify(arg)).join(", ");
const url = URL.createObjectURL(new Blob([`(${fn})(${argsString})`], {type: 'application/javascript'})),
worker = new Worker(url);
URL.revokeObjectURL(url);
return worker;
}

function randomString() {
return Math.random().toString(36).substring(7);
}

function createHighlightWorker() {
if (!window.config || !window.config.hljsUrl) return;

// convert relative URL to absolute for importScripts to accept it
let url;
try {
url = new URL(window.config.hljsUrl, location.origin).href;
} catch (err) {}
if (!url) return;

window.highlightWorker = createWorker(url => {
self.importScripts(url);
self.onmessage = ({data}) => {
const {id, texts} = data;
if (!id || !texts || !texts.length) return;

const results = texts.map(text => {
return (self.hljs.highlightAuto(text) || {}).value;
});
self.postMessage({id, results});
}
}, url);
}

function highlight(nodes) {
if (!window.highlightWorker) return;

nodes = [].slice.call(nodes || []);
if (!nodes.length) return;

// requestId is used to identify this particular highlight request so we can prevent race conditions
// when parallel highlighting requests do not finish in the order they were sent in.
const requestId = randomString();

function listener({data}) {
const {id, results} = data;
if (id !== requestId) return;

window.highlightWorker.removeEventListener("message", listener);

for (const [index, result] of Object.entries(results)) {
// highlight.js in a web worker does not accept HTML strings so we have to pass .textContent to it
// and replicate what the golang templating does by re-adding these ol > li wrappings.
const lines = result.split(/\r?\n/).map((line, i) => `<li class="L${i + 1}" rel="L${i + 1}">${line}</li>`);
nodes[index].classList.add("hljs");
nodes[index].innerHTML = `<ol class="linenums">${lines.join("")}<ol>`;
}
}

window.highlightWorker.addEventListener("message", listener);
window.highlightWorker.postMessage({id: requestId, texts: nodes.map(node => node.textContent)});
}

function initWipTitle() {
$(".title_wip_desc > a").click(function (e) {
e.preventDefault();
Expand Down Expand Up @@ -2006,12 +2071,8 @@ $(document).ready(function () {
});

// Highlight JS
if (typeof hljs != 'undefined') {
const nodes = [].slice.call(document.querySelectorAll('pre code') || []);
for (let i = 0; i < nodes.length; i++) {
hljs.highlightBlock(nodes[i]);
}
}
createHighlightWorker();
highlight(document.querySelectorAll('pre code'));

// Dropzone
const $dropzone = $('#dropzone');
Expand Down
7 changes: 6 additions & 1 deletion templates/base/footer.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<script src="{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1"></script>
<script src="{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1"></script>
<script src="{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script>
<script>
window.config = {};
</script>
{{if .RequireSimpleMDE}}
<script src="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js"></script>
<script src="{{AppSubUrl}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script>
Expand All @@ -31,7 +34,9 @@

<!-- Third-party libraries -->
{{if .RequireHighlightJS}}
<script src="{{AppSubUrl}}/vendor/plugins/highlight/highlight.pack.js"></script>
<script>
window.config.hljsUrl = "{{AppSubUrl}}/vendor/plugins/highlight/highlight.pack.js";
</script>
{{end}}
{{if .RequireMinicolors}}
<script src="{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script>
Expand Down

0 comments on commit ababfbf

Please sign in to comment.