Как использовать веб-работников для выделения блоков исходного кода с помощью highlightjs?
Как я могу использовать одного или нескольких веб-работников, чтобы выделить несколько небольших блоков исходного кода на моем веб-сайте?
3 ответа
Пример использования одного веб-работника
Чтобы использовать только одного веб-работника для выделения нескольких кодовых блоков, вы можете использовать следующий код, где highlight_code_worker_function
это рабочая функция.
<script>
function highlight_code() {
if (typeof (Worker) === undefined) return false;
var workerFunction = new Blob(['(' + highlight_code_worker_function.toString() + ')()'], {type: "text/javascript"});
var worker = new Worker(URL.createObjectURL(workerFunction));
var codeBlocks = $('div.readme pre, div.readme code');
worker.onmessage = function(event) {
var data = JSON.parse(event.data);
codeBlocks.eq(data.index).html(data.result).addClass('hljs');
};
worker.onerror = function() {
// do nothing
};
codeBlocks.each(function(index) {
worker.postMessage(JSON.stringify({index: index, code: $(this).text()}));
});
worker.postMessage(JSON.stringify({index: -1}));
}
function highlight_code_worker_function() {
onmessage = function(event) {
var data = JSON.parse(event.data);
if (data.index === -1) {
close(); // close worker
}
importScripts(''https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js'');
self.hljs.configure({tabReplace:4});
var result = self.hljs.highlightAuto(data.code);
postMessage(JSON.stringify({result: result.value, index: data.index}));
}
}
highlight_code();
</script>
Пример использования нескольких веб-работников
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/monokai_sublime.min.css">
<script type="text/javascript">
function highlight_code()
{
if (typeof (Worker) === undefined) return false;
var workerFunction = new Blob(['(' + highlight_code_worker_function.toString() + ')()'], {type: "text/javascript"});
var localWorkerURL = URL.createObjectURL(workerFunction);
$('div.readme pre, div.readme code').each(function() {
var code = $(this);
var worker = new Worker(localWorkerURL);
worker.onmessage = function(event) { code.html(event.data).addClass('hljs'); }
worker.postMessage(code.text()); // start worker
});
}
function highlight_code_worker_function()
{
onmessage = function(event) {
importScripts('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js');
self.hljs.configure({tabReplace:4});
var result = self.hljs.highlightAuto(event.data);
postMessage(result.value);
close(); // close worker
}
}
$(window).on('load', highlight_code);
</script>
Я знаю, что это старый вопрос, но я даю свой ответ, который может помочь любому будущему посетителю.
Вы можете указать некоторую задержку между выделением фрагментов кода, что повысит производительность, поскольку все рабочие процессы не будут работать одновременно. Я лично использовал этот подход на одном из своих веб-сайтов и получил огромную разницу в производительности.
script.js
const allPres = [...document.querySelectorAll('pre')];
for (let i = 0; i < allPres.length; i++) {
setTimeout(() => {
const block = allPres[i];
var code = block.innerText,
worker = new Worker('/worker.js');
worker.onmessage = function (event) {
var result = event.data;
block.innerHTML = result;
worker.terminate();
};
worker.postMessage(code);
}, i * 500) // putting just a delay of 500ms will make your website's performance nice than running all them together
}
worker.js
importScripts('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js');
self.onmessage = function (event) {
var result = hljs.highlightAuto(event.data);
postMessage(result.value);
};
пошаговая реализация здесь.
Вдохновленный официальной документацией, я пришел к надежному решению (как мне кажется).
Фактически я создал 3 скрипта:
- worker_functions.js
- worker.js
- скрипт в HTML
Просто потому, что мне нужно было динамически выделять код. Вот мой процесс:
- Загрузите страницу с необходимыми скриптами, ожидая загрузки DOM перед запуском скриптов.
- Получить данные из базы данных, вставить XML-контент в
data-my_attribute
внутри кнопки сeye
икона. - Нажатие этих кнопок будет нацелено на модальное открытие (bootstrap 4).
- При модальном показе (то есть до его показа) получите данные xml от кнопки, чтобы поместить их в мой блок кода.
- В показанном модальном окне (означает, что когда он отображается) активируйте выделение, отправив сообщение работнику.
РЕДАКТИРОВАТЬ: шаг 5 не требуется, потому что
jQuery(this).find('#codeblock').html(xml);
правильно сделано до начала процесса мелирования.
worker_functions.js
let highlight_worker;
/**
* Start the worker in order to highlighting code block when triggering
* @param worker_url - The javascript path of the worker
*/
function start_worker(worker_url) {
highlight_worker = new Worker(worker_url);
}
/**
* Start an highlighting process through the worker previously started
* @param querySelector - The DOM element on which the highlighted content should be returned
*/
function start_highlighting(querySelector) {
// Callback to insert the highlighted content to the expected element in DOM
highlight_worker.onmessage = (event) => {
querySelector.innerHTML = event.data;
}
// Post the content to be highlighted by the worker
highlight_worker.postMessage(querySelector.textContent);
}
Worker.js
Я использовал специальный пакет highlight.js, включив только языки, которые я хочу выделить.
/**
* When worker receives a message, import highlight.js then post back the resulting highlight
* @param event - The content to be highlighted
*/
onmessage = function (event) {
importScripts('highlight.pack.js');
var result = self.hljs.highlightAuto(event.data);
postMessage(result.value);
}
Скрипт в HTML - шаблон Django
Я импортирую
worker_functions
script, затем я добавляю прослушиватель событий, запускающий загрузку окна, запускаю воркер и активирую выделение модальных событий.
{% block scripts %}
<script src="{% static 'device/js/highlight/worker_functions.js' %}"></script>
<script type="text/javascript">
window.addEventListener("load", function (event) {
start_worker("{% static 'device/js/highlight/worker.js' %}");
$('#mifContentModal').on('show.bs.modal', function (e) {
// let xml = '<p class="text-break">' + e.relatedTarget.dataset.mif_content + '</p>'; // Before decompress
let xml = '<xmp>' + e.relatedTarget.dataset.mif_content + '</xmp>';
console.log(jQuery(this).find('#codeblock'));
jQuery(this).find('#codeblock').html(xml);
start_highlighting(codeblock); // It can be done right after adding the code in DOM
})
//$('#mifContentModal').on('shown.bs.modal', function (e) {
// let codeblock = document.getElementById("codeblock");
// start_highlighting(codeblock);
// // Then remove the xmp tag
// codeblock.innerHTML = jQuery(this).find('xmp').html();
//})
});
</script>
{% endblock %}
Затем я могу выделить, когда захочу, используя одного рабочего.