Files
com.xaymar.www/assets/js/highlight.mjs
T

96 lines
2.6 KiB
JavaScript
Raw Normal View History

2024-05-16 11:40:24 +02:00
'use strict';
// Highlight.JS: https://highlightjs.org/
async function initializeHighlightJS() {
const languageRE = /\blanguage-([a-zA-Z0-9_\-]+)\b/gi;
const noLanguageRE = /\bno-language\b/gi;
2024-06-05 06:45:22 +02:00
const languages = new Set();
2024-06-02 06:31:08 +02:00
const selector = "code.block[class*=\"language\"]";
2024-06-05 06:45:22 +02:00
const blocks = document.querySelectorAll(selector);
2024-06-02 06:31:08 +02:00
2024-06-05 06:45:22 +02:00
// Early-Exit if there's nothing to highlight anyway to reduce waste.
if (blocks.length == 0) {
2024-06-02 06:31:08 +02:00
console.log("highlight.JS: Skipping, as it is not needed here.");
return;
}
2024-05-16 11:40:24 +02:00
2024-06-05 06:45:22 +02:00
// Load and configure highlight.JS
2024-05-16 11:40:24 +02:00
console.log("highlight.JS: Loading...");
let highlightJS = await import("./highlightjs/highlight.mjs");
window.highlightJS = highlightJS.default;
console.log("highlight.JS: Configuring...");
window.highlightJS.configure({
"noHighlightRe": noLanguageRE,
"languageDetectRe": languageRE,
"cssSelector": "code.block[class*=\"language\"]",
"throwUnescapedHTML": true,
});
2024-06-05 06:45:22 +02:00
// Find all languages used.
for (let block of blocks) {
for (let classname of block.classList) {
for (let match of classname.matchAll(languageRE)) {
if (match.length > 0) {
languages.add(match[1]);
}
}
}
}
2024-05-16 11:40:24 +02:00
// Import all languages.
let langs = [];
for (let lang of languages) {
console.log(`highlight.JS: Importing language definition for '${lang}'...`);
2024-06-02 06:24:10 +02:00
langs.push(new Promise(async (resolve, reject) => {
const start = performance.now();
const max_attempts = 5;
let attempt = 0;
let mod = undefined;
let err = null;
for (let attempt = 1; attempt <= 5; attempt++) {
try {
2024-06-05 06:45:22 +02:00
// Firefox breaks here because it hates 429 Too Many Requests. All other browsers work.
2024-06-02 06:24:10 +02:00
mod = await import(`./highlightjs/languages/${lang}.min.js`);
break;
2024-06-02 06:31:08 +02:00
} catch (ex) {
2024-06-02 06:24:10 +02:00
err = ex;
await new Promise((resolve, reject) => {
2024-06-02 06:31:08 +02:00
setTimeout(() => { resolve() }, 1000);
2024-06-02 06:24:10 +02:00
})
}
}
if (!mod) {
reject(err);
} else {
window.highlightJS.registerLanguage(lang, mod.default);
console.log(`highlight.JS: Imported language definition for '${lang}' after ${(performance.now() - start).toFixed(2)}ms.`);
resolve(mod);
}
2024-05-16 11:40:24 +02:00
}));
}
await Promise.allSettled(langs)
// Highlight everything.
function highlightAllCode() {
console.log(`highlight.JS: Applying highlighting all valid code blocks...`);
2024-06-05 06:45:22 +02:00
try {
window.highlightJS.highlightAll();
} catch (ex) {
console.error(`highlight.JS: ${ex}`);
}
2024-05-16 11:40:24 +02:00
};
if (document.readyState === "complete"
|| document.readyState === "loaded"
|| document.readyState === "interactive") {
highlightAllCode();
} else {
document.addEventListener('DOMContentLoaded', () => {
highlightAllCode();
});
}
}
initializeHighlightJS();