mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 10:02:59 +08:00
chore(highlightjs): introduce client-level list of themes
This commit is contained in:
parent
488761d4b9
commit
8b11f25f0c
@ -31,7 +31,6 @@ const HIGHLIGHT_JS: Library = {
|
||||
}
|
||||
}
|
||||
|
||||
const currentTheme = String(optionsService.get("codeBlockTheme"));
|
||||
loadHighlightingTheme(currentTheme);
|
||||
|
||||
return Array.from(scriptsToLoad);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ensureMimeTypes, highlight, highlightAuto } from "@triliumnext/highlightjs";
|
||||
import { ensureMimeTypes, highlight, highlightAuto, loadTheme } from "@triliumnext/highlightjs";
|
||||
import mime_types from "./mime_types.js";
|
||||
import options from "./options.js";
|
||||
|
||||
@ -57,6 +57,11 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
|
||||
}
|
||||
|
||||
export async function ensureMimeTypesForHighlighting() {
|
||||
// Load theme.
|
||||
const currentTheme = String(options.get("codeBlockTheme"));
|
||||
loadTheme(currentTheme);
|
||||
|
||||
// Load mime types.
|
||||
const mimeTypes = mime_types.getMimeTypes();
|
||||
await ensureMimeTypes(mimeTypes);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import library_loader from "../../../../services/library_loader.js";
|
||||
import server from "../../../../services/server.js";
|
||||
import OptionsWidget from "../options_widget.js";
|
||||
import { ensureMimeTypesForHighlighting } from "../../../../services/syntax_highlight.js";
|
||||
import { Themes } from "@triliumnext/highlightjs";
|
||||
|
||||
const SAMPLE_LANGUAGE = "javascript";
|
||||
const SAMPLE_CODE = `\
|
||||
@ -76,6 +77,13 @@ export default class CodeBlockOptions extends OptionsWidget {
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$themeSelect = this.$widget.find(".theme-select");
|
||||
// Populate the list of themes.
|
||||
for (const name of Object.keys(Themes)) {
|
||||
const option = $("<option>")
|
||||
.attr("value", `default:${name}`)
|
||||
.text(name);
|
||||
this.$themeSelect.append(option);
|
||||
}
|
||||
this.$themeSelect.on("change", async () => {
|
||||
const newTheme = String(this.$themeSelect.val());
|
||||
library_loader.loadHighlightingTheme(newTheme);
|
||||
@ -107,25 +115,6 @@ export default class CodeBlockOptions extends OptionsWidget {
|
||||
}
|
||||
|
||||
async optionsLoaded(options: OptionMap) {
|
||||
const themeGroups = await server.get<Response>("options/codeblock-themes");
|
||||
this.$themeSelect.empty();
|
||||
|
||||
for (const [key, themes] of Object.entries(themeGroups)) {
|
||||
const $group = key ? $("<optgroup>").attr("label", key) : null;
|
||||
|
||||
for (const theme of themes) {
|
||||
const option = $("<option>").attr("value", theme.val).text(theme.title);
|
||||
|
||||
if ($group) {
|
||||
$group.append(option);
|
||||
} else {
|
||||
this.$themeSelect.append(option);
|
||||
}
|
||||
}
|
||||
if ($group) {
|
||||
this.$themeSelect.append($group);
|
||||
}
|
||||
}
|
||||
this.$themeSelect.val(options.codeBlockTheme);
|
||||
this.setCheckboxState(this.$wordWrap, options.codeBlockWordWrap);
|
||||
this.$widget.closest(".note-detail-printable").toggleClass("word-wrap", options.codeBlockWordWrap === "true");
|
||||
|
@ -6,7 +6,6 @@ import searchService from "../../services/search/services/search.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import type { Request } from "express";
|
||||
import { changeLanguage, getLocales } from "../../services/i18n.js";
|
||||
import { listSyntaxHighlightingThemes } from "../../services/code_block_theme.js";
|
||||
import type { OptionNames } from "@triliumnext/commons";
|
||||
|
||||
// options allowed to be updated directly in the Options dialog
|
||||
@ -190,10 +189,6 @@ function getUserThemes() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getSyntaxHighlightingThemes() {
|
||||
return listSyntaxHighlightingThemes();
|
||||
}
|
||||
|
||||
function getSupportedLocales() {
|
||||
return getLocales();
|
||||
}
|
||||
@ -210,6 +205,5 @@ export default {
|
||||
updateOption,
|
||||
updateOptions,
|
||||
getUserThemes,
|
||||
getSyntaxHighlightingThemes,
|
||||
getSupportedLocales
|
||||
};
|
||||
|
@ -217,7 +217,6 @@ function register(app: express.Application) {
|
||||
apiRoute(PUT, "/api/options/:name/:value*", optionsApiRoute.updateOption);
|
||||
apiRoute(PUT, "/api/options", optionsApiRoute.updateOptions);
|
||||
apiRoute(GET, "/api/options/user-themes", optionsApiRoute.getUserThemes);
|
||||
apiRoute(GET, "/api/options/codeblock-themes", optionsApiRoute.getSyntaxHighlightingThemes);
|
||||
apiRoute(GET, "/api/options/locales", optionsApiRoute.getSupportedLocales);
|
||||
|
||||
apiRoute(PST, "/api/password/change", passwordApiRoute.changePassword);
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import themeNames from "./code_block_theme_names.json" with { type: "json" };
|
||||
import { t } from "i18next";
|
||||
import { join } from "path";
|
||||
import { isDev, isElectron, getResourceDir } from "./utils.js";
|
||||
@ -70,10 +69,6 @@ export function readThemesFromFileSystem(path: string): ColorTheme[] {
|
||||
const nameWithoutExtension = name.replace(".min.css", "");
|
||||
let title = nameWithoutExtension.replace(/-/g, " ");
|
||||
|
||||
if (title in themeNames) {
|
||||
title = (themeNames as Record<string, string>)[title];
|
||||
}
|
||||
|
||||
return {
|
||||
val: `default:${nameWithoutExtension}`,
|
||||
title: title
|
||||
|
@ -1,82 +0,0 @@
|
||||
{
|
||||
"1c light": "1C (Light)",
|
||||
"a11y dark": "a11y (Dark)",
|
||||
"a11y light": "a11y (Light)",
|
||||
"agate": "Agate (Dark)",
|
||||
"an old hope": "An Old Hope (Dark)",
|
||||
"androidstudio": "Android Studio (Dark)",
|
||||
"arduino light": "Arduino (Light)",
|
||||
"arta": "Arta (Dark)",
|
||||
"ascetic": "Ascetic (Light)",
|
||||
"atom one dark reasonable": "Atom One with ReasonML support (Dark)",
|
||||
"atom one dark": "Atom One (Dark)",
|
||||
"atom one light": "Atom One (Light)",
|
||||
"brown paper": "Brown Paper (Light)",
|
||||
"codepen embed": "CodePen Embed (Dark)",
|
||||
"color brewer": "Color Brewer (Light)",
|
||||
"cybertopia cherry": "Cybertopia Cherry (Dark)",
|
||||
"cybertopia dimmer": "Cybertopia Dimmer (Dark)",
|
||||
"cybertopia icecap": "Cybertopia Icecap (Dark)",
|
||||
"cybertopia saturated": "Cybertopia Saturated (Dark)",
|
||||
"dark": "Dark",
|
||||
"default": "Original highlight.js Theme (Light)",
|
||||
"devibeans": "devibeans (Dark)",
|
||||
"docco": "Docco (Light)",
|
||||
"far": "FAR (Dark)",
|
||||
"felipec": "FelipeC (Dark)",
|
||||
"foundation": "Foundation 4 Docs (Light)",
|
||||
"github dark dimmed": "GitHub Dimmed (Dark)",
|
||||
"github dark": "GitHub (Dark)",
|
||||
"github": "GitHub (Light)",
|
||||
"gml": "GML (Dark)",
|
||||
"googlecode": "Google Code (Light)",
|
||||
"gradient dark": "Gradient (Dark)",
|
||||
"gradient light": "Gradient (Light)",
|
||||
"grayscale": "Grayscale (Light)",
|
||||
"hybrid": "hybrid (Dark)",
|
||||
"idea": "Idea (Light)",
|
||||
"intellij light": "IntelliJ (Light)",
|
||||
"ir black": "IR Black (Dark)",
|
||||
"isbl editor dark": "ISBL Editor (Dark)",
|
||||
"isbl editor light": "ISBL Editor (Light)",
|
||||
"kimbie dark": "Kimbie (Dark)",
|
||||
"kimbie light": "Kimbie (Light)",
|
||||
"lightfair": "Lightfair (Light)",
|
||||
"lioshi": "Lioshi (Dark)",
|
||||
"magula": "Magula (Light)",
|
||||
"mono blue": "Mono Blue (Light)",
|
||||
"monokai sublime": "Monokai Sublime (Dark)",
|
||||
"monokai": "Monokai (Dark)",
|
||||
"night owl": "Night Owl (Dark)",
|
||||
"nnfx dark": "NNFX (Dark)",
|
||||
"nnfx light": "NNFX (Light)",
|
||||
"nord": "Nord (Dark)",
|
||||
"obsidian": "Obsidian (Dark)",
|
||||
"panda syntax dark": "Panda (Dark)",
|
||||
"panda syntax light": "Panda (Light)",
|
||||
"paraiso dark": "Paraiso (Dark)",
|
||||
"paraiso light": "Paraiso (Light)",
|
||||
"pojoaque": "Pojoaque (Dark)",
|
||||
"purebasic": "PureBasic (Light)",
|
||||
"qtcreator dark": "Qt Creator (Dark)",
|
||||
"qtcreator light": "Qt Creator (Light)",
|
||||
"rainbow": "Rainbow (Dark)",
|
||||
"routeros": "RouterOS Script (Light)",
|
||||
"rose pine dawn": "Rose Pine Dawn (Light)",
|
||||
"rose pine moon": "Rose Pine Moon (Dark)",
|
||||
"rose pine": "Rose Pine (Dark)",
|
||||
"school book": "School Book (Light)",
|
||||
"shades of purple": "Shades of Purple (Dark)",
|
||||
"srcery": "Srcery (Dark)",
|
||||
"stackoverflow dark": "Stack Overflow (Dark)",
|
||||
"stackoverflow light": "Stack Overflow (Light)",
|
||||
"sunburst": "Sunburst (Dark)",
|
||||
"tokyo night dark": "Tokyo Night (Dark)",
|
||||
"tokyo night light": "Tokyo Night (Light)",
|
||||
"tomorrow night blue": "Tomorrow Night Blue (Dark)",
|
||||
"tomorrow night bright": "Tomorrow Night Bright (Dark)",
|
||||
"vs": "Visual Studio (Light)",
|
||||
"vs2015": "Visual Studio 2015 (Dark)",
|
||||
"xcode": "Xcode (Light)",
|
||||
"xt256": "xt256 (Dark)"
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
import hljs from "../node_modules/highlight.js/es/core.js";
|
||||
import { normalizeMimeTypeForCKEditor, type MimeType } from "@triliumnext/commons";
|
||||
import definitions from "./syntax_highlighting.js";
|
||||
import syntaxDefinitions from "./syntax_highlighting.js";
|
||||
import { type Theme } from "./themes.js";
|
||||
import { type HighlightOptions } from "highlight.js";
|
||||
|
||||
export { default as Themes } from "./themes.js";
|
||||
|
||||
const registeredMimeTypes = new Set<string>();
|
||||
const unsupportedMimeTypes = new Set<string>();
|
||||
|
||||
@ -18,7 +21,7 @@ export async function ensureMimeTypes(mimeTypes: MimeType[]) {
|
||||
}
|
||||
|
||||
registeredMimeTypes.add(mime);
|
||||
const loader = definitions[mime];
|
||||
const loader = syntaxDefinitions[mime];
|
||||
if (!loader) {
|
||||
unsupportedMimeTypes.add(mime);
|
||||
continue;
|
||||
@ -42,4 +45,8 @@ export function highlight(code: string, options: HighlightOptions) {
|
||||
return hljs.highlight(code, options);
|
||||
}
|
||||
|
||||
export async function loadTheme(theme: Theme) {
|
||||
console.log("Got", theme.default);
|
||||
}
|
||||
|
||||
export const { highlightAuto } = hljs;
|
||||
|
85
packages/highlightjs/src/themes.ts
Normal file
85
packages/highlightjs/src/themes.ts
Normal file
@ -0,0 +1,85 @@
|
||||
export type Theme = { default: typeof import("*.css", { with: { "resolution-mode": "import" } }); };
|
||||
|
||||
const themeDefinitions: Record<string, () => Promise<Theme>> = {
|
||||
"a11y (Dark)": () => import("../node_modules/highlight.js/styles/a11y-dark.css?raw"),
|
||||
"a11y (Light)": () => import("../node_modules/highlight.js/styles/a11y-light.css?raw"),
|
||||
"Agate (Dark)": () => import("../node_modules/highlight.js/styles/agate.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"),
|
||||
"Arduino (Light)": () => import("../node_modules/highlight.js/styles/arduino-light.css?raw"),
|
||||
"Arta (Dark)": () => import("../node_modules/highlight.js/styles/arta.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"),
|
||||
"Atom One (Dark)": () => import("../node_modules/highlight.js/styles/atom-one-dark.css?raw"),
|
||||
"Atom One (Light)": () => import("../node_modules/highlight.js/styles/atom-one-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"),
|
||||
"Color Brewer (Light)": () => import("../node_modules/highlight.js/styles/color-brewer.css?raw"),
|
||||
"Cybertopia Cherry (Dark)": () => import("../node_modules/highlight.js/styles/cybertopia-cherry.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"),
|
||||
"Cybertopia Saturated (Dark)": () => import("../node_modules/highlight.js/styles/cybertopia-saturated.css?raw"),
|
||||
"Dark": () => import("../node_modules/highlight.js/styles/dark.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"),
|
||||
"Docco (Light)": () => import("../node_modules/highlight.js/styles/docco.css?raw"),
|
||||
"FAR (Dark)": () => import("../node_modules/highlight.js/styles/far.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"),
|
||||
"GitHub Dimmed (Dark)": () => import("../node_modules/highlight.js/styles/github-dark-dimmed.css?raw"),
|
||||
"GitHub (Dark)": () => import("../node_modules/highlight.js/styles/github-dark.css?raw"),
|
||||
"GitHub (Light)": () => import("../node_modules/highlight.js/styles/github.css?raw"),
|
||||
"GML (Dark)": () => import("../node_modules/highlight.js/styles/gml.css?raw"),
|
||||
"Google Code (Light)": () => import("../node_modules/highlight.js/styles/googlecode.css?raw"),
|
||||
"Gradient (Dark)": () => import("../node_modules/highlight.js/styles/gradient-dark.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"),
|
||||
"hybrid (Dark)": () => import("../node_modules/highlight.js/styles/hybrid.css?raw"),
|
||||
"Idea (Light)": () => import("../node_modules/highlight.js/styles/idea.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"),
|
||||
"ISBL Editor (Dark)": () => import("../node_modules/highlight.js/styles/isbl-editor-dark.css?raw"),
|
||||
"ISBL Editor (Light)": () => import("../node_modules/highlight.js/styles/isbl-editor-light.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"),
|
||||
"Lightfair (Light)": () => import("../node_modules/highlight.js/styles/lightfair.css?raw"),
|
||||
"Lioshi (Dark)": () => import("../node_modules/highlight.js/styles/lioshi.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"),
|
||||
"Monokai Sublime (Dark)": () => import("../node_modules/highlight.js/styles/monokai-sublime.css?raw"),
|
||||
"Monokai (Dark)": () => import("../node_modules/highlight.js/styles/monokai.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"),
|
||||
"NNFX (Light)": () => import("../node_modules/highlight.js/styles/nnfx-light.css?raw"),
|
||||
"Nord (Dark)": () => import("../node_modules/highlight.js/styles/nord.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"),
|
||||
"Panda (Light)": () => import("../node_modules/highlight.js/styles/panda-syntax-light.css?raw"),
|
||||
"Paraiso (Dark)": () => import("../node_modules/highlight.js/styles/paraiso-dark.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"),
|
||||
"PureBasic (Light)": () => import("../node_modules/highlight.js/styles/purebasic.css?raw"),
|
||||
"Qt Creator (Dark)": () => import("../node_modules/highlight.js/styles/qtcreator-dark.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"),
|
||||
"RouterOS Script (Light)": () => import("../node_modules/highlight.js/styles/routeros.css?raw"),
|
||||
"Rose Pine Dawn (Light)": () => import("../node_modules/highlight.js/styles/rose-pine-dawn.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"),
|
||||
"School Book (Light)": () => import("../node_modules/highlight.js/styles/school-book.css?raw"),
|
||||
"Shades of Purple (Dark)": () => import("../node_modules/highlight.js/styles/shades-of-purple.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"),
|
||||
"Stack Overflow (Light)": () => import("../node_modules/highlight.js/styles/stackoverflow-light.css?raw"),
|
||||
"Sunburst (Dark)": () => import("../node_modules/highlight.js/styles/sunburst.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"),
|
||||
"Tomorrow Night Blue (Dark)": () => import("../node_modules/highlight.js/styles/tomorrow-night-blue.css?raw"),
|
||||
"Tomorrow Night Bright (Dark)": () => import("../node_modules/highlight.js/styles/tomorrow-night-bright.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"),
|
||||
"Xcode (Light)": () => import("../node_modules/highlight.js/styles/xcode.css?raw"),
|
||||
"xt256 (Dark)": () => import("../node_modules/highlight.js/styles/xt256.css?raw")
|
||||
}
|
||||
|
||||
export default themeDefinitions;
|
Loading…
x
Reference in New Issue
Block a user