2025-05-18 17:12:45 +03:00
|
|
|
import { ensureMimeTypes, highlight, highlightAuto, loadTheme } from "@triliumnext/highlightjs";
|
2024-12-19 20:27:27 +02:00
|
|
|
import mime_types from "./mime_types.js";
|
|
|
|
import options from "./options.js";
|
|
|
|
|
2024-12-19 20:47:55 +02:00
|
|
|
export function getStylesheetUrl(theme: string) {
|
2024-12-19 20:27:27 +02:00
|
|
|
if (!theme) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const defaultPrefix = "default:";
|
2025-01-09 18:07:02 +02:00
|
|
|
if (theme.startsWith(defaultPrefix)) {
|
2024-12-19 20:27:27 +02:00
|
|
|
return `${window.glob.assetPath}/node_modules/@highlightjs/cdn-assets/styles/${theme.substr(defaultPrefix.length)}.min.css`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Identifies all the code blocks (as `pre code`) under the specified hierarchy and uses the highlight.js library to obtain the highlighted text which is then applied on to the code blocks.
|
2025-01-09 18:07:02 +02:00
|
|
|
*
|
2024-12-19 20:27:27 +02:00
|
|
|
* @param $container the container under which to look for code blocks and to apply syntax highlighting to them.
|
|
|
|
*/
|
2024-12-19 20:47:55 +02:00
|
|
|
export async function applySyntaxHighlight($container: JQuery<HTMLElement>) {
|
2024-12-19 20:27:27 +02:00
|
|
|
if (!isSyntaxHighlightEnabled()) {
|
|
|
|
return;
|
2025-01-09 18:07:02 +02:00
|
|
|
}
|
2024-12-19 20:27:27 +02:00
|
|
|
|
|
|
|
const codeBlocks = $container.find("pre code");
|
|
|
|
for (const codeBlock of codeBlocks) {
|
|
|
|
const normalizedMimeType = extractLanguageFromClassList(codeBlock);
|
|
|
|
if (!normalizedMimeType) {
|
|
|
|
continue;
|
|
|
|
}
|
2025-01-09 18:07:02 +02:00
|
|
|
|
2024-12-19 20:27:27 +02:00
|
|
|
applySingleBlockSyntaxHighlight($(codeBlock), normalizedMimeType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Applies syntax highlight to the given code block (assumed to be <pre><code>), using highlight.js.
|
|
|
|
*/
|
2024-12-19 20:47:55 +02:00
|
|
|
export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLElement>, normalizedMimeType: string) {
|
2024-12-19 20:27:27 +02:00
|
|
|
$codeBlock.parent().toggleClass("hljs");
|
|
|
|
const text = $codeBlock.text();
|
|
|
|
|
|
|
|
let highlightedText = null;
|
|
|
|
if (normalizedMimeType === mime_types.MIME_TYPE_AUTO) {
|
2025-05-18 10:05:02 +03:00
|
|
|
highlightedText = highlightAuto(text);
|
2024-12-19 20:27:27 +02:00
|
|
|
} else if (normalizedMimeType) {
|
2025-05-18 15:16:53 +03:00
|
|
|
await ensureMimeTypesForHighlighting();
|
|
|
|
highlightedText = highlight(text, { language: normalizedMimeType });
|
2024-12-19 20:27:27 +02:00
|
|
|
}
|
2025-01-09 18:07:02 +02:00
|
|
|
|
|
|
|
if (highlightedText) {
|
2024-12-19 20:27:27 +02:00
|
|
|
$codeBlock.html(highlightedText.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-18 15:16:53 +03:00
|
|
|
export async function ensureMimeTypesForHighlighting() {
|
2025-05-18 17:12:45 +03:00
|
|
|
// Load theme.
|
|
|
|
const currentTheme = String(options.get("codeBlockTheme"));
|
|
|
|
loadTheme(currentTheme);
|
|
|
|
|
|
|
|
// Load mime types.
|
2025-05-18 15:16:53 +03:00
|
|
|
const mimeTypes = mime_types.getMimeTypes();
|
|
|
|
await ensureMimeTypes(mimeTypes);
|
|
|
|
}
|
|
|
|
|
2024-12-19 20:27:27 +02:00
|
|
|
/**
|
|
|
|
* Indicates whether syntax highlighting should be enabled for code blocks, by querying the value of the `codeblockTheme` option.
|
|
|
|
* @returns whether syntax highlighting should be enabled for code blocks.
|
|
|
|
*/
|
|
|
|
export function isSyntaxHighlightEnabled() {
|
|
|
|
const theme = options.get("codeBlockTheme");
|
|
|
|
return theme && theme !== "none";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given a HTML element, tries to extract the `language-` class name out of it.
|
2025-01-09 18:07:02 +02:00
|
|
|
*
|
2024-12-19 20:47:55 +02:00
|
|
|
* @param el the HTML element from which to extract the language tag.
|
2024-12-19 20:27:27 +02:00
|
|
|
* @returns the normalized MIME type (e.g. `text-css` instead of `language-text-css`).
|
|
|
|
*/
|
2024-12-19 20:47:55 +02:00
|
|
|
function extractLanguageFromClassList(el: HTMLElement) {
|
2024-12-19 20:27:27 +02:00
|
|
|
const prefix = "language-";
|
|
|
|
for (const className of el.classList) {
|
|
|
|
if (className.startsWith(prefix)) {
|
|
|
|
return className.substring(prefix.length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2025-01-09 18:07:02 +02:00
|
|
|
}
|