chore(highlightjs): load theme by IDs

This commit is contained in:
Elian Doran 2025-05-18 17:50:31 +03:00
parent 8b11f25f0c
commit 66cbe468f5
No known key found for this signature in database
5 changed files with 356 additions and 96 deletions

View File

@ -1,4 +1,4 @@
import { ensureMimeTypes, highlight, highlightAuto, loadTheme } from "@triliumnext/highlightjs"; import { ensureMimeTypes, highlight, highlightAuto, loadTheme, Themes } from "@triliumnext/highlightjs";
import mime_types from "./mime_types.js"; import mime_types from "./mime_types.js";
import options from "./options.js"; import options from "./options.js";
@ -58,8 +58,17 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
export async function ensureMimeTypesForHighlighting() { export async function ensureMimeTypesForHighlighting() {
// Load theme. // Load theme.
const currentTheme = String(options.get("codeBlockTheme")); const currentThemeName = String(options.get("codeBlockTheme"));
loadTheme(currentTheme); const themePrefix = "default:";
let theme = null;
if (currentThemeName.includes(themePrefix)) {
theme = Themes[currentThemeName.substring(themePrefix.length)];
}
if (!theme) {
theme = Themes.default;
}
loadTheme(theme);
// Load mime types. // Load mime types.
const mimeTypes = mime_types.getMimeTypes(); const mimeTypes = mime_types.getMimeTypes();

View File

@ -57,14 +57,6 @@ const TPL = /*html*/`
</div> </div>
`; `;
// TODO: Deduplicate
interface Theme {
title: string;
val: string;
}
type Response = Record<string, Theme[]>;
/** /**
* Contains appearance settings for code blocks within text notes, such as the theme for the syntax highlighter. * Contains appearance settings for code blocks within text notes, such as the theme for the syntax highlighter.
*/ */
@ -78,10 +70,10 @@ export default class CodeBlockOptions extends OptionsWidget {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$themeSelect = this.$widget.find(".theme-select"); this.$themeSelect = this.$widget.find(".theme-select");
// Populate the list of themes. // Populate the list of themes.
for (const name of Object.keys(Themes)) { for (const [ id, theme ] of Object.entries(Themes)) {
const option = $("<option>") const option = $("<option>")
.attr("value", `default:${name}`) .attr("value", `default:${id}`)
.text(name); .text(theme.name);
this.$themeSelect.append(option); this.$themeSelect.append(option);
} }
this.$themeSelect.on("change", async () => { this.$themeSelect.on("change", async () => {

View File

@ -80,6 +80,7 @@ module.exports = composePlugins(
})) }))
})); }));
inlineCss(config);
inlineSvg(config); inlineSvg(config);
externalJson(config); externalJson(config);
@ -103,6 +104,17 @@ function inlineSvg(config) {
}); });
} }
function inlineCss(config) {
if (!config.module?.rules) {
return;
}
// Alter Nx's asset rule to avoid inlining SVG if they have ?raw prepended.
console.log(config.module.rules.map((r) => r.test.toString()));
const existingRule = config.module.rules.find((r) => r.test.toString().startsWith("/\\.css"));
existingRule.resourceQuery = { not: [/raw/] };
}
function externalJson(config) { function externalJson(config) {
if (!config.module?.rules) { if (!config.module?.rules) {
return; return;

View File

@ -46,7 +46,10 @@ export function highlight(code: string, options: HighlightOptions) {
} }
export async function loadTheme(theme: Theme) { export async function loadTheme(theme: Theme) {
console.log("Got", theme.default); console.log("Got theme", theme);
const loadedTheme = await theme.load();
console.log("Got", loadedTheme.default);
} }
export const { highlightAuto } = hljs; export const { highlightAuto } = hljs;

View File

@ -1,85 +1,329 @@
export type Theme = { default: typeof import("*.css", { with: { "resolution-mode": "import" } }); }; export interface Theme {
name: string;
load: () => Promise<{ default: typeof import("*.css", { with: { "resolution-mode": "import" } }); }>;
}
const themeDefinitions: Record<string, () => Promise<Theme>> = { const themeDefinitions: Record<string, Theme> = {
"a11y (Dark)": () => import("../node_modules/highlight.js/styles/a11y-dark.css?raw"), "1c light": {
"a11y (Light)": () => import("../node_modules/highlight.js/styles/a11y-light.css?raw"), name: "1C (Light)",
"Agate (Dark)": () => import("../node_modules/highlight.js/styles/agate.css?raw"), load: () => import("../node_modules/highlight.js/styles/1c-light.css?raw")
"An Old Hope (Dark)": () => import("../node_modules/highlight.js/styles/an-old-hope.css?raw"), },
"Android Studio (Dark)": () => import("../node_modules/highlight.js/styles/androidstudio.css?raw"), "a11y dark": {
"Arduino (Light)": () => import("../node_modules/highlight.js/styles/arduino-light.css?raw"), name: "a11y (Dark)",
"Arta (Dark)": () => import("../node_modules/highlight.js/styles/arta.css?raw"), load: () => import("../node_modules/highlight.js/styles/a11y-dark.css?raw")
"Ascetic (Light)": () => import("../node_modules/highlight.js/styles/ascetic.css?raw"), },
"Atom One with ReasonML support (Dark)": () => import("../node_modules/highlight.js/styles/atom-one-dark-reasonable.css?raw"), "a11y light": {
"Atom One (Dark)": () => import("../node_modules/highlight.js/styles/atom-one-dark.css?raw"), name: "a11y (Light)",
"Atom One (Light)": () => import("../node_modules/highlight.js/styles/atom-one-light.css?raw"), load: () => import("../node_modules/highlight.js/styles/a11y-light.css?raw")
"Brown Paper (Light)": () => import("../node_modules/highlight.js/styles/brown-paper.css?raw"), },
"CodePen Embed (Dark)": () => import("../node_modules/highlight.js/styles/codepen-embed.css?raw"), "agate": {
"Color Brewer (Light)": () => import("../node_modules/highlight.js/styles/color-brewer.css?raw"), name: "Agate (Dark)",
"Cybertopia Cherry (Dark)": () => import("../node_modules/highlight.js/styles/cybertopia-cherry.css?raw"), load: () => import("../node_modules/highlight.js/styles/agate.css?raw")
"Cybertopia Dimmer (Dark)": () => import("../node_modules/highlight.js/styles/cybertopia-dimmer.css?raw"), },
"Cybertopia Icecap (Dark)": () => import("../node_modules/highlight.js/styles/cybertopia-icecap.css?raw"), "an old hope": {
"Cybertopia Saturated (Dark)": () => import("../node_modules/highlight.js/styles/cybertopia-saturated.css?raw"), name: "An Old Hope (Dark)",
"Dark": () => import("../node_modules/highlight.js/styles/dark.css?raw"), load: () => import("../node_modules/highlight.js/styles/an-old-hope.css?raw")
"Original highlight.js Theme (Light)": () => import("../node_modules/highlight.js/styles/default.css?raw"), },
"devibeans (Dark)": () => import("../node_modules/highlight.js/styles/devibeans.css?raw"), "androidstudio": {
"Docco (Light)": () => import("../node_modules/highlight.js/styles/docco.css?raw"), name: "Android Studio (Dark)",
"FAR (Dark)": () => import("../node_modules/highlight.js/styles/far.css?raw"), load: () => import("../node_modules/highlight.js/styles/androidstudio.css?raw")
"FelipeC (Dark)": () => import("../node_modules/highlight.js/styles/felipec.css?raw"), },
"Foundation 4 Docs (Light)": () => import("../node_modules/highlight.js/styles/foundation.css?raw"), "arduino light": {
"GitHub Dimmed (Dark)": () => import("../node_modules/highlight.js/styles/github-dark-dimmed.css?raw"), name: "Arduino (Light)",
"GitHub (Dark)": () => import("../node_modules/highlight.js/styles/github-dark.css?raw"), load: () => import("../node_modules/highlight.js/styles/arduino-light.css?raw")
"GitHub (Light)": () => import("../node_modules/highlight.js/styles/github.css?raw"), },
"GML (Dark)": () => import("../node_modules/highlight.js/styles/gml.css?raw"), "arta": {
"Google Code (Light)": () => import("../node_modules/highlight.js/styles/googlecode.css?raw"), name: "Arta (Dark)",
"Gradient (Dark)": () => import("../node_modules/highlight.js/styles/gradient-dark.css?raw"), load: () => import("../node_modules/highlight.js/styles/arta.css?raw")
"Gradient (Light)": () => import("../node_modules/highlight.js/styles/gradient-light.css?raw"), },
"Grayscale (Light)": () => import("../node_modules/highlight.js/styles/grayscale.css?raw"), "ascetic": {
"hybrid (Dark)": () => import("../node_modules/highlight.js/styles/hybrid.css?raw"), name: "Ascetic (Light)",
"Idea (Light)": () => import("../node_modules/highlight.js/styles/idea.css?raw"), load: () => import("../node_modules/highlight.js/styles/ascetic.css?raw")
"IntelliJ (Light)": () => import("../node_modules/highlight.js/styles/intellij-light.css?raw"), },
"IR Black (Dark)": () => import("../node_modules/highlight.js/styles/ir-black.css?raw"), "atom one dark reasonable": {
"ISBL Editor (Dark)": () => import("../node_modules/highlight.js/styles/isbl-editor-dark.css?raw"), name: "Atom One with ReasonML support (Dark)",
"ISBL Editor (Light)": () => import("../node_modules/highlight.js/styles/isbl-editor-light.css?raw"), load: () => import("../node_modules/highlight.js/styles/atom-one-dark-reasonable.css?raw")
"Kimbie (Dark)": () => import("../node_modules/highlight.js/styles/kimbie-dark.css?raw"), },
"Kimbie (Light)": () => import("../node_modules/highlight.js/styles/kimbie-light.css?raw"), "atom one dark": {
"Lightfair (Light)": () => import("../node_modules/highlight.js/styles/lightfair.css?raw"), name: "Atom One (Dark)",
"Lioshi (Dark)": () => import("../node_modules/highlight.js/styles/lioshi.css?raw"), load: () => import("../node_modules/highlight.js/styles/atom-one-dark.css?raw")
"Magula (Light)": () => import("../node_modules/highlight.js/styles/magula.css?raw"), },
"Mono Blue (Light)": () => import("../node_modules/highlight.js/styles/mono-blue.css?raw"), "atom one light": {
"Monokai Sublime (Dark)": () => import("../node_modules/highlight.js/styles/monokai-sublime.css?raw"), name: "Atom One (Light)",
"Monokai (Dark)": () => import("../node_modules/highlight.js/styles/monokai.css?raw"), load: () => import("../node_modules/highlight.js/styles/atom-one-light.css?raw")
"Night Owl (Dark)": () => import("../node_modules/highlight.js/styles/night-owl.css?raw"), },
"NNFX (Dark)": () => import("../node_modules/highlight.js/styles/nnfx-dark.css?raw"), "brown paper": {
"NNFX (Light)": () => import("../node_modules/highlight.js/styles/nnfx-light.css?raw"), name: "Brown Paper (Light)",
"Nord (Dark)": () => import("../node_modules/highlight.js/styles/nord.css?raw"), load: () => import("../node_modules/highlight.js/styles/brown-paper.css?raw")
"Obsidian (Dark)": () => import("../node_modules/highlight.js/styles/obsidian.css?raw"), },
"Panda (Dark)": () => import("../node_modules/highlight.js/styles/panda-syntax-dark.css?raw"), "codepen embed": {
"Panda (Light)": () => import("../node_modules/highlight.js/styles/panda-syntax-light.css?raw"), name: "CodePen Embed (Dark)",
"Paraiso (Dark)": () => import("../node_modules/highlight.js/styles/paraiso-dark.css?raw"), load: () => import("../node_modules/highlight.js/styles/codepen-embed.css?raw")
"Paraiso (Light)": () => import("../node_modules/highlight.js/styles/paraiso-light.css?raw"), },
"Pojoaque (Dark)": () => import("../node_modules/highlight.js/styles/pojoaque.css?raw"), "color brewer": {
"PureBasic (Light)": () => import("../node_modules/highlight.js/styles/purebasic.css?raw"), name: "Color Brewer (Light)",
"Qt Creator (Dark)": () => import("../node_modules/highlight.js/styles/qtcreator-dark.css?raw"), load: () => import("../node_modules/highlight.js/styles/color-brewer.css?raw")
"Qt Creator (Light)": () => import("../node_modules/highlight.js/styles/qtcreator-light.css?raw"), },
"Rainbow (Dark)": () => import("../node_modules/highlight.js/styles/rainbow.css?raw"), "cybertopia cherry": {
"RouterOS Script (Light)": () => import("../node_modules/highlight.js/styles/routeros.css?raw"), name: "Cybertopia Cherry (Dark)",
"Rose Pine Dawn (Light)": () => import("../node_modules/highlight.js/styles/rose-pine-dawn.css?raw"), load: () => import("../node_modules/highlight.js/styles/cybertopia-cherry.css?raw")
"Rose Pine Moon (Dark)": () => import("../node_modules/highlight.js/styles/rose-pine-moon.css?raw"), },
"Rose Pine (Dark)": () => import("../node_modules/highlight.js/styles/rose-pine.css?raw"), "cybertopia dimmer": {
"School Book (Light)": () => import("../node_modules/highlight.js/styles/school-book.css?raw"), name: "Cybertopia Dimmer (Dark)",
"Shades of Purple (Dark)": () => import("../node_modules/highlight.js/styles/shades-of-purple.css?raw"), load: () => import("../node_modules/highlight.js/styles/cybertopia-dimmer.css?raw")
"Srcery (Dark)": () => import("../node_modules/highlight.js/styles/srcery.css?raw"), },
"Stack Overflow (Dark)": () => import("../node_modules/highlight.js/styles/stackoverflow-dark.css?raw"), "cybertopia icecap": {
"Stack Overflow (Light)": () => import("../node_modules/highlight.js/styles/stackoverflow-light.css?raw"), name: "Cybertopia Icecap (Dark)",
"Sunburst (Dark)": () => import("../node_modules/highlight.js/styles/sunburst.css?raw"), load: () => import("../node_modules/highlight.js/styles/cybertopia-icecap.css?raw")
"Tokyo Night (Dark)": () => import("../node_modules/highlight.js/styles/tokyo-night-dark.css?raw"), },
"Tokyo Night (Light)": () => import("../node_modules/highlight.js/styles/tokyo-night-light.css?raw"), "cybertopia saturated": {
"Tomorrow Night Blue (Dark)": () => import("../node_modules/highlight.js/styles/tomorrow-night-blue.css?raw"), name: "Cybertopia Saturated (Dark)",
"Tomorrow Night Bright (Dark)": () => import("../node_modules/highlight.js/styles/tomorrow-night-bright.css?raw"), load: () => import("../node_modules/highlight.js/styles/cybertopia-saturated.css?raw")
"Visual Studio (Light)": () => import("../node_modules/highlight.js/styles/vs.css?raw"), },
"Visual Studio 2015 (Dark)": () => import("../node_modules/highlight.js/styles/vs2015.css?raw"), "dark": {
"Xcode (Light)": () => import("../node_modules/highlight.js/styles/xcode.css?raw"), name: "Dark",
"xt256 (Dark)": () => import("../node_modules/highlight.js/styles/xt256.css?raw") load: () => import("../node_modules/highlight.js/styles/dark.css?raw")
},
"default": {
name: "Original highlight.js Theme (Light)",
load: () => import("../node_modules/highlight.js/styles/default.css?raw")
},
"devibeans": {
name: "devibeans (Dark)",
load: () => import("../node_modules/highlight.js/styles/devibeans.css?raw")
},
"docco": {
name: "Docco (Light)",
load: () => import("../node_modules/highlight.js/styles/docco.css?raw")
},
"far": {
name: "FAR (Dark)",
load: () => import("../node_modules/highlight.js/styles/far.css?raw")
},
"felipec": {
name: "FelipeC (Dark)",
load: () => import("../node_modules/highlight.js/styles/felipec.css?raw")
},
"foundation": {
name: "Foundation 4 Docs (Light)",
load: () => import("../node_modules/highlight.js/styles/foundation.css?raw")
},
"github dark dimmed": {
name: "GitHub Dimmed (Dark)",
load: () => import("../node_modules/highlight.js/styles/github-dark-dimmed.css?raw")
},
"github dark": {
name: "GitHub (Dark)",
load: () => import("../node_modules/highlight.js/styles/github-dark.css?raw")
},
"github": {
name: "GitHub (Light)",
load: () => import("../node_modules/highlight.js/styles/github.css?raw")
},
"gml": {
name: "GML (Dark)",
load: () => import("../node_modules/highlight.js/styles/gml.css?raw")
},
"googlecode": {
name: "Google Code (Light)",
load: () => import("../node_modules/highlight.js/styles/googlecode.css?raw")
},
"gradient dark": {
name: "Gradient (Dark)",
load: () => import("../node_modules/highlight.js/styles/gradient-dark.css?raw")
},
"gradient light": {
name: "Gradient (Light)",
load: () => import("../node_modules/highlight.js/styles/gradient-light.css?raw")
},
"grayscale": {
name: "Grayscale (Light)",
load: () => import("../node_modules/highlight.js/styles/grayscale.css?raw")
},
"hybrid": {
name: "hybrid (Dark)",
load: () => import("../node_modules/highlight.js/styles/hybrid.css?raw")
},
"idea": {
name: "Idea (Light)",
load: () => import("../node_modules/highlight.js/styles/idea.css?raw")
},
"intellij light": {
name: "IntelliJ (Light)",
load: () => import("../node_modules/highlight.js/styles/intellij-light.css?raw")
},
"ir black": {
name: "IR Black (Dark)",
load: () => import("../node_modules/highlight.js/styles/ir-black.css?raw")
},
"isbl editor dark": {
name: "ISBL Editor (Dark)",
load: () => import("../node_modules/highlight.js/styles/isbl-editor-dark.css?raw")
},
"isbl editor light": {
name: "ISBL Editor (Light)",
load: () => import("../node_modules/highlight.js/styles/isbl-editor-light.css?raw")
},
"kimbie dark": {
name: "Kimbie (Dark)",
load: () => import("../node_modules/highlight.js/styles/kimbie-dark.css?raw")
},
"kimbie light": {
name: "Kimbie (Light)",
load: () => import("../node_modules/highlight.js/styles/kimbie-light.css?raw")
},
"lightfair": {
name: "Lightfair (Light)",
load: () => import("../node_modules/highlight.js/styles/lightfair.css?raw")
},
"lioshi": {
name: "Lioshi (Dark)",
load: () => import("../node_modules/highlight.js/styles/lioshi.css?raw")
},
"magula": {
name: "Magula (Light)",
load: () => import("../node_modules/highlight.js/styles/magula.css?raw")
},
"mono blue": {
name: "Mono Blue (Light)",
load: () => import("../node_modules/highlight.js/styles/mono-blue.css?raw")
},
"monokai sublime": {
name: "Monokai Sublime (Dark)",
load: () => import("../node_modules/highlight.js/styles/monokai-sublime.css?raw")
},
"monokai": {
name: "Monokai (Dark)",
load: () => import("../node_modules/highlight.js/styles/monokai.css?raw")
},
"night owl": {
name: "Night Owl (Dark)",
load: () => import("../node_modules/highlight.js/styles/night-owl.css?raw")
},
"nnfx dark": {
name: "NNFX (Dark)",
load: () => import("../node_modules/highlight.js/styles/nnfx-dark.css?raw")
},
"nnfx light": {
name: "NNFX (Light)",
load: () => import("../node_modules/highlight.js/styles/nnfx-light.css?raw")
},
"nord": {
name: "Nord (Dark)",
load: () => import("../node_modules/highlight.js/styles/nord.css?raw")
},
"obsidian": {
name: "Obsidian (Dark)",
load: () => import("../node_modules/highlight.js/styles/obsidian.css?raw")
},
"panda syntax dark": {
name: "Panda (Dark)",
load: () => import("../node_modules/highlight.js/styles/panda-syntax-dark.css?raw")
},
"panda syntax light": {
name: "Panda (Light)",
load: () => import("../node_modules/highlight.js/styles/panda-syntax-light.css?raw")
},
"paraiso dark": {
name: "Paraiso (Dark)",
load: () => import("../node_modules/highlight.js/styles/paraiso-dark.css?raw")
},
"paraiso light": {
name: "Paraiso (Light)",
load: () => import("../node_modules/highlight.js/styles/paraiso-light.css?raw")
},
"pojoaque": {
name: "Pojoaque (Dark)",
load: () => import("../node_modules/highlight.js/styles/pojoaque.css?raw")
},
"purebasic": {
name: "PureBasic (Light)",
load: () => import("../node_modules/highlight.js/styles/purebasic.css?raw")
},
"qtcreator dark": {
name: "Qt Creator (Dark)",
load: () => import("../node_modules/highlight.js/styles/qtcreator-dark.css?raw")
},
"qtcreator light": {
name: "Qt Creator (Light)",
load: () => import("../node_modules/highlight.js/styles/qtcreator-light.css?raw")
},
"rainbow": {
name: "Rainbow (Dark)",
load: () => import("../node_modules/highlight.js/styles/rainbow.css?raw")
},
"routeros": {
name: "RouterOS Script (Light)",
load: () => import("../node_modules/highlight.js/styles/routeros.css?raw")
},
"rose pine dawn": {
name: "Rose Pine Dawn (Light)",
load: () => import("../node_modules/highlight.js/styles/rose-pine-dawn.css?raw")
},
"rose pine moon": {
name: "Rose Pine Moon (Dark)",
load: () => import("../node_modules/highlight.js/styles/rose-pine-moon.css?raw")
},
"rose pine": {
name: "Rose Pine (Dark)",
load: () => import("../node_modules/highlight.js/styles/rose-pine.css?raw")
},
"school book": {
name: "School Book (Light)",
load: () => import("../node_modules/highlight.js/styles/school-book.css?raw")
},
"shades of purple": {
name: "Shades of Purple (Dark)",
load: () => import("../node_modules/highlight.js/styles/shades-of-purple.css?raw")
},
"srcery": {
name: "Srcery (Dark)",
load: () => import("../node_modules/highlight.js/styles/srcery.css?raw")
},
"stackoverflow dark": {
name: "Stack Overflow (Dark)",
load: () => import("../node_modules/highlight.js/styles/stackoverflow-dark.css?raw")
},
"stackoverflow light": {
name: "Stack Overflow (Light)",
load: () => import("../node_modules/highlight.js/styles/stackoverflow-light.css?raw")
},
"sunburst": {
name: "Sunburst (Dark)",
load: () => import("../node_modules/highlight.js/styles/sunburst.css?raw")
},
"tokyo night dark": {
name: "Tokyo Night (Dark)",
load: () => import("../node_modules/highlight.js/styles/tokyo-night-dark.css?raw")
},
"tokyo night light": {
name: "Tokyo Night (Light)",
load: () => import("../node_modules/highlight.js/styles/tokyo-night-light.css?raw")
},
"tomorrow night blue": {
name: "Tomorrow Night Blue (Dark)",
load: () => import("../node_modules/highlight.js/styles/tomorrow-night-blue.css?raw")
},
"tomorrow night bright": {
name: "Tomorrow Night Bright (Dark)",
load: () => import("../node_modules/highlight.js/styles/tomorrow-night-bright.css?raw")
},
"vs": {
name: "Visual Studio (Light)",
load: () => import("../node_modules/highlight.js/styles/vs.css?raw")
},
"vs2015": {
name: "Visual Studio 2015 (Dark)",
load: () => import("../node_modules/highlight.js/styles/vs2015.css?raw")
},
"xcode": {
name: "Xcode (Light)",
load: () => import("../node_modules/highlight.js/styles/xcode.css?raw")
},
"xt256": {
name: "xt256 (Dark)",
load: () => import("../node_modules/highlight.js/styles/xt256.css?raw")
}
} }
export default themeDefinitions; export default themeDefinitions;