Merge remote-tracking branch 'origin/develop' into client_vite

This commit is contained in:
Elian Doran 2025-05-19 16:50:00 +03:00
commit a5f0b3b9b2
No known key found for this signature in database
62 changed files with 2143 additions and 1006 deletions

View File

@ -1,83 +0,0 @@
/*
* highlight.js terraform syntax highlighting definition
*
* @see https://github.com/highlightjs/highlight.js
*
* :TODO:
*
* @package: highlightjs-terraform
* @author: Nikos Tsirmirakis <nikos.tsirmirakis@winopsdba.com>
* @since: 2019-03-20
*
* Description: Terraform (HCL) language definition
* Category: scripting
*/
var module = module ? module : {}; // shim for browser use
function hljsDefineTerraform(hljs) {
var NUMBERS = {
className: 'number',
begin: '\\b\\d+(\\.\\d+)?',
relevance: 0
};
var STRINGS = {
className: 'string',
begin: '"',
end: '"',
contains: [{
className: 'variable',
begin: '\\${',
end: '\\}',
relevance: 9,
contains: [{
className: 'string',
begin: '"',
end: '"'
}, {
className: 'meta',
begin: '[A-Za-z_0-9]*' + '\\(',
end: '\\)',
contains: [
NUMBERS, {
className: 'string',
begin: '"',
end: '"',
contains: [{
className: 'variable',
begin: '\\${',
end: '\\}',
contains: [{
className: 'string',
begin: '"',
end: '"',
contains: [{
className: 'variable',
begin: '\\${',
end: '\\}'
}]
}, {
className: 'meta',
begin: '[A-Za-z_0-9]*' + '\\(',
end: '\\)'
}]
}]
},
'self']
}]
}]
};
return {
aliases: ['tf', 'hcl'],
keywords: 'resource variable provider output locals module data terraform|10',
literal: 'false true null',
contains: [
hljs.COMMENT('\\#', '$'),
NUMBERS,
STRINGS
]
}
}
hljs.registerLanguage('terraform', hljsDefineTerraform);

View File

@ -11,11 +11,11 @@ import FAttachment from "../entities/fattachment.js";
import imageContextMenuService from "../menus/image_context_menu.js";
import { applySingleBlockSyntaxHighlight, applySyntaxHighlight } from "./syntax_highlight.js";
import { loadElkIfNeeded, postprocessMermaidSvg } from "./mermaid.js";
import { normalizeMimeTypeForCKEditor } from "./mime_type_definitions.js";
import renderDoc from "./doc_renderer.js";
import { t } from "../services/i18n.js";
import WheelZoom from 'vanilla-js-wheel-zoom';
import { renderMathInElement } from "./math.js";
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
let idCounter = 1;

View File

@ -1,7 +1,3 @@
import mimeTypesService from "./mime_types.js";
import optionsService from "./options.js";
import { getStylesheetUrl } from "./syntax_highlight.js";
export interface Library {
js?: string[] | (() => string[]);
css?: string[];
@ -12,32 +8,6 @@ const KATEX: Library = {
css: ["node_modules/katex/dist/katex.min.css"]
};
const HIGHLIGHT_JS: Library = {
js: () => {
const mimeTypes = mimeTypesService.getMimeTypes();
const scriptsToLoad = new Set<string>();
scriptsToLoad.add("node_modules/@highlightjs/cdn-assets/highlight.min.js");
for (const mimeType of mimeTypes) {
const id = mimeType.highlightJs;
if (!mimeType.enabled || !id) {
continue;
}
if (mimeType.highlightJsSource === "libraries") {
scriptsToLoad.add(`libraries/highlightjs/${id}.js`);
} else {
// Built-in module.
scriptsToLoad.add(`node_modules/@highlightjs/cdn-assets/languages/${id}.min.js`);
}
}
const currentTheme = String(optionsService.get("codeBlockTheme"));
loadHighlightingTheme(currentTheme);
return Array.from(scriptsToLoad);
}
};
async function requireLibrary(library: Library) {
if (library.css) {
library.css.map((cssUrl) => requireCss(cssUrl));
@ -91,35 +61,7 @@ async function requireCss(url: string, prependAssetPath = true) {
}
}
let highlightingThemeEl: JQuery<HTMLElement> | null = null;
function loadHighlightingTheme(theme: string) {
if (!theme) {
return;
}
if (theme === "none") {
// Deactivate the theme.
if (highlightingThemeEl) {
highlightingThemeEl.remove();
highlightingThemeEl = null;
}
return;
}
if (!highlightingThemeEl) {
highlightingThemeEl = $(`<link rel="stylesheet" type="text/css" />`);
$("head").append(highlightingThemeEl);
}
const url = getStylesheetUrl(theme);
if (url) {
highlightingThemeEl.attr("href", url);
}
}
export default {
requireCss,
requireLibrary,
loadHighlightingTheme,
HIGHLIGHT_JS
requireLibrary
};

View File

@ -1,223 +0,0 @@
// TODO: deduplicate with /src/services/import/mime_type_definitions.ts
/**
* A pseudo-MIME type which is used in the editor to automatically determine the language used in code blocks via heuristics.
*/
export const MIME_TYPE_AUTO = "text-x-trilium-auto";
export interface MimeTypeDefinition {
default?: boolean;
title: string;
mime: string;
/** The name of the language/mime type as defined by highlight.js (or one of the aliases), in order to be used for syntax highlighting such as inside code blocks. */
highlightJs?: string;
/** If specified, will load the corresponding highlight.js file from the `libraries/highlightjs/${id}.js` instead of `node_modules/@highlightjs/cdn-assets/languages/${id}.min.js`. */
highlightJsSource?: "libraries";
/** If specified, will load the corresponding highlight file from the given path instead of `node_modules`. */
codeMirrorSource?: string;
}
/**
* For highlight.js-supported languages, see https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md.
*/
export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([
{ title: "Plain text", mime: "text/plain", highlightJs: "plaintext", default: true },
// Keep sorted alphabetically.
{ title: "APL", mime: "text/apl" },
{ title: "ASN.1", mime: "text/x-ttcn-asn" },
{ title: "ASP.NET", mime: "application/x-aspx" },
{ title: "Asterisk", mime: "text/x-asterisk" },
{ title: "Batch file (DOS)", mime: "application/x-bat", highlightJs: "dos", codeMirrorSource: "libraries/codemirror/batch.js" },
{ title: "Brainfuck", mime: "text/x-brainfuck", highlightJs: "brainfuck" },
{ title: "C", mime: "text/x-csrc", highlightJs: "c", default: true },
{ title: "C#", mime: "text/x-csharp", highlightJs: "csharp", default: true },
{ title: "C++", mime: "text/x-c++src", highlightJs: "cpp", default: true },
{ title: "Clojure", mime: "text/x-clojure", highlightJs: "clojure" },
{ title: "ClojureScript", mime: "text/x-clojurescript" },
{ title: "Closure Stylesheets (GSS)", mime: "text/x-gss" },
{ title: "CMake", mime: "text/x-cmake", highlightJs: "cmake" },
{ title: "Cobol", mime: "text/x-cobol" },
{ title: "CoffeeScript", mime: "text/coffeescript", highlightJs: "coffeescript" },
{ title: "Common Lisp", mime: "text/x-common-lisp", highlightJs: "lisp" },
{ title: "CQL", mime: "text/x-cassandra" },
{ title: "Crystal", mime: "text/x-crystal", highlightJs: "crystal" },
{ title: "CSS", mime: "text/css", highlightJs: "css", default: true },
{ title: "Cypher", mime: "application/x-cypher-query" },
{ title: "Cython", mime: "text/x-cython" },
{ title: "D", mime: "text/x-d", highlightJs: "d" },
{ title: "Dart", mime: "application/dart", highlightJs: "dart" },
{ title: "diff", mime: "text/x-diff", highlightJs: "diff" },
{ title: "Django", mime: "text/x-django", highlightJs: "django" },
{ title: "Dockerfile", mime: "text/x-dockerfile", highlightJs: "dockerfile" },
{ title: "DTD", mime: "application/xml-dtd" },
{ title: "Dylan", mime: "text/x-dylan" },
{ title: "EBNF", mime: "text/x-ebnf", highlightJs: "ebnf" },
{ title: "ECL", mime: "text/x-ecl" },
{ title: "edn", mime: "application/edn" },
{ title: "Eiffel", mime: "text/x-eiffel" },
{ title: "Elm", mime: "text/x-elm", highlightJs: "elm" },
{ title: "Embedded Javascript", mime: "application/x-ejs" },
{ title: "Embedded Ruby", mime: "application/x-erb", highlightJs: "erb" },
{ title: "Erlang", mime: "text/x-erlang", highlightJs: "erlang" },
{ title: "Esper", mime: "text/x-esper" },
{ title: "F#", mime: "text/x-fsharp", highlightJs: "fsharp" },
{ title: "Factor", mime: "text/x-factor" },
{ title: "FCL", mime: "text/x-fcl" },
{ title: "Forth", mime: "text/x-forth" },
{ title: "Fortran", mime: "text/x-fortran", highlightJs: "fortran" },
{ title: "Gas", mime: "text/x-gas" },
{ title: "GDScript (Godot)", mime: "text/x-gdscript" },
{ title: "Gherkin", mime: "text/x-feature", highlightJs: "gherkin" },
{ title: "GitHub Flavored Markdown", mime: "text/x-gfm", highlightJs: "markdown" },
{ title: "Go", mime: "text/x-go", highlightJs: "go", default: true },
{ title: "Groovy", mime: "text/x-groovy", highlightJs: "groovy", default: true },
{ title: "HAML", mime: "text/x-haml", highlightJs: "haml" },
{ title: "Haskell (Literate)", mime: "text/x-literate-haskell" },
{ title: "Haskell", mime: "text/x-haskell", highlightJs: "haskell", default: true },
{ title: "Haxe", mime: "text/x-haxe", highlightJs: "haxe" },
{ title: "HTML", mime: "text/html", highlightJs: "xml", default: true },
{ title: "HTTP", mime: "message/http", highlightJs: "http", default: true },
{ title: "HXML", mime: "text/x-hxml" },
{ title: "IDL", mime: "text/x-idl" },
{ title: "Java Server Pages", mime: "application/x-jsp", highlightJs: "java" },
{ title: "Java", mime: "text/x-java", highlightJs: "java", default: true },
{ title: "Jinja2", mime: "text/jinja2" },
{ title: "JS backend", mime: "application/javascript;env=backend", highlightJs: "javascript", default: true },
{ title: "JS frontend", mime: "application/javascript;env=frontend", highlightJs: "javascript", default: true },
{ title: "JSON-LD", mime: "application/ld+json", highlightJs: "json" },
{ title: "JSON", mime: "application/json", highlightJs: "json", default: true },
{ title: "JSX", mime: "text/jsx", highlightJs: "javascript" },
{ title: "Julia", mime: "text/x-julia", highlightJs: "julia" },
{ title: "Kotlin", mime: "text/x-kotlin", highlightJs: "kotlin", default: true },
{ title: "LaTeX", mime: "text/x-latex", highlightJs: "latex" },
{ title: "LESS", mime: "text/x-less", highlightJs: "less" },
{ title: "LiveScript", mime: "text/x-livescript", highlightJs: "livescript" },
{ title: "Lua", mime: "text/x-lua", highlightJs: "lua" },
{ title: "MariaDB SQL", mime: "text/x-mariadb", highlightJs: "sql" },
{ title: "Markdown", mime: "text/x-markdown", highlightJs: "markdown", default: true },
{ title: "Mathematica", mime: "text/x-mathematica", highlightJs: "mathematica" },
{ title: "mbox", mime: "application/mbox" },
{ title: "MIPS Assembler", mime: "text/x-asm-mips", highlightJs: "mipsasm" },
{ title: "mIRC", mime: "text/mirc" },
{ title: "Modelica", mime: "text/x-modelica" },
{ title: "MS SQL", mime: "text/x-mssql", highlightJs: "sql" },
{ title: "mscgen", mime: "text/x-mscgen" },
{ title: "msgenny", mime: "text/x-msgenny" },
{ title: "MUMPS", mime: "text/x-mumps" },
{ title: "MySQL", mime: "text/x-mysql", highlightJs: "sql" },
{ title: "Nix", mime: "text/x-nix", highlightJs: "nix" },
{ title: "Nginx", mime: "text/x-nginx-conf", highlightJs: "nginx" },
{ title: "NSIS", mime: "text/x-nsis", highlightJs: "nsis" },
{ title: "NTriples", mime: "application/n-triples" },
{ title: "Objective-C", mime: "text/x-objectivec", highlightJs: "objectivec" },
{ title: "OCaml", mime: "text/x-ocaml", highlightJs: "ocaml" },
{ title: "Octave", mime: "text/x-octave" },
{ title: "Oz", mime: "text/x-oz" },
{ title: "Pascal", mime: "text/x-pascal", highlightJs: "delphi" },
{ title: "PEG.js", mime: "null" },
{ title: "Perl", mime: "text/x-perl", default: true },
{ title: "PGP", mime: "application/pgp" },
{ title: "PHP", mime: "text/x-php", default: true, highlightJs: "php" },
{ title: "Pig", mime: "text/x-pig" },
{ title: "PLSQL", mime: "text/x-plsql", highlightJs: "sql" },
{ title: "PostgreSQL", mime: "text/x-pgsql", highlightJs: "pgsql" },
{ title: "PowerShell", mime: "application/x-powershell", highlightJs: "powershell" },
{ title: "Properties files", mime: "text/x-properties", highlightJs: "properties" },
{ title: "ProtoBuf", mime: "text/x-protobuf", highlightJs: "protobuf" },
{ title: "Pug", mime: "text/x-pug" },
{ title: "Puppet", mime: "text/x-puppet", highlightJs: "puppet" },
{ title: "Python", mime: "text/x-python", highlightJs: "python", default: true },
{ title: "Q", mime: "text/x-q", highlightJs: "q" },
{ title: "R", mime: "text/x-rsrc", highlightJs: "r" },
{ title: "reStructuredText", mime: "text/x-rst" },
{ title: "RPM Changes", mime: "text/x-rpm-changes" },
{ title: "RPM Spec", mime: "text/x-rpm-spec" },
{ title: "Ruby", mime: "text/x-ruby", highlightJs: "ruby", default: true },
{ title: "Rust", mime: "text/x-rustsrc", highlightJs: "rust" },
{ title: "SAS", mime: "text/x-sas", highlightJs: "sas" },
{ title: "Sass", mime: "text/x-sass", highlightJs: "scss" },
{ title: "Scala", mime: "text/x-scala" },
{ title: "Scheme", mime: "text/x-scheme" },
{ title: "SCSS", mime: "text/x-scss", highlightJs: "scss" },
{ title: "Shell (bash)", mime: "text/x-sh", highlightJs: "bash", default: true },
{ title: "Sieve", mime: "application/sieve" },
{ title: "Slim", mime: "text/x-slim" },
{ title: "Smalltalk", mime: "text/x-stsrc", highlightJs: "smalltalk" },
{ title: "Smarty", mime: "text/x-smarty" },
{ title: "SML", mime: "text/x-sml", highlightJs: "sml" },
{ title: "Solr", mime: "text/x-solr" },
{ title: "Soy", mime: "text/x-soy" },
{ title: "SPARQL", mime: "application/sparql-query" },
{ title: "Spreadsheet", mime: "text/x-spreadsheet" },
{ title: "SQL", mime: "text/x-sql", highlightJs: "sql", default: true },
{ title: "SQLite (Trilium)", mime: "text/x-sqlite;schema=trilium", highlightJs: "sql", default: true },
{ title: "SQLite", mime: "text/x-sqlite", highlightJs: "sql" },
{ title: "Squirrel", mime: "text/x-squirrel" },
{ title: "sTeX", mime: "text/x-stex" },
{ title: "Stylus", mime: "text/x-styl", highlightJs: "stylus" },
{ title: "Swift", mime: "text/x-swift", default: true },
{ title: "SystemVerilog", mime: "text/x-systemverilog" },
{ title: "Tcl", mime: "text/x-tcl", highlightJs: "tcl" },
{ title: "Terraform (HCL)", mime: "text/x-hcl", highlightJs: "terraform", highlightJsSource: "libraries", codeMirrorSource: "libraries/codemirror/hcl.js" },
{ title: "Textile", mime: "text/x-textile" },
{ title: "TiddlyWiki ", mime: "text/x-tiddlywiki" },
{ title: "Tiki wiki", mime: "text/tiki" },
{ title: "TOML", mime: "text/x-toml", highlightJs: "ini" },
{ title: "Tornado", mime: "text/x-tornado" },
{ title: "troff", mime: "text/troff" },
{ title: "TTCN_CFG", mime: "text/x-ttcn-cfg" },
{ title: "TTCN", mime: "text/x-ttcn" },
{ title: "Turtle", mime: "text/turtle" },
{ title: "Twig", mime: "text/x-twig", highlightJs: "twig" },
{ title: "TypeScript-JSX", mime: "text/typescript-jsx", highlightJs: "typescript" },
{ title: "TypeScript", mime: "application/typescript", highlightJs: "typescript" },
{ title: "VB.NET", mime: "text/x-vb", highlightJs: "vbnet" },
{ title: "VBScript", mime: "text/vbscript", highlightJs: "vbscript" },
{ title: "Velocity", mime: "text/velocity" },
{ title: "Verilog", mime: "text/x-verilog", highlightJs: "verilog" },
{ title: "VHDL", mime: "text/x-vhdl", highlightJs: "vhdl" },
{ title: "Vue.js Component", mime: "text/x-vue" },
{ title: "Web IDL", mime: "text/x-webidl" },
{ title: "XML", mime: "text/xml", highlightJs: "xml", default: true },
{ title: "XQuery", mime: "application/xquery", highlightJs: "xquery" },
{ title: "xu", mime: "text/x-xu" },
{ title: "Yacas", mime: "text/x-yacas" },
{ title: "YAML", mime: "text/x-yaml", highlightJs: "yaml", default: true },
{ title: "Z80", mime: "text/x-z80" }
]);
/**
* Given a MIME type in the usual format (e.g. `text/csrc`), it returns a MIME type that can be passed down to the CKEditor
* code plugin.
*
* @param mimeType The MIME type to normalize, in the usual format (e.g. `text/c-src`).
* @returns the normalized MIME type (e.g. `text-c-src`).
*/
export function normalizeMimeTypeForCKEditor(mimeType: string) {
return mimeType.toLowerCase().replace(/[\W_]+/g, "-");
}
let byHighlightJsNameMappings: Record<string, MimeTypeDefinition> | null = null;
/**
* Given a Highlight.js language tag (e.g. `css`), it returns a corresponding {@link MimeTypeDefinition} if found.
*
* If there are multiple {@link MimeTypeDefinition}s for the language tag, then only the first one is retrieved. For example for `javascript`, the "JS frontend" mime type is returned.
*
* @param highlightJsName a language tag.
* @returns the corresponding {@link MimeTypeDefinition} if found, or `undefined` otherwise.
*/
export function getMimeTypeFromHighlightJs(highlightJsName: string) {
if (!byHighlightJsNameMappings) {
byHighlightJsNameMappings = {};
for (const mimeType of MIME_TYPES_DICT) {
if (mimeType.highlightJs && !byHighlightJsNameMappings[mimeType.highlightJs]) {
byHighlightJsNameMappings[mimeType.highlightJs] = mimeType;
}
}
}
return byHighlightJsNameMappings[highlightJsName];
}

View File

@ -1,13 +1,6 @@
import { MIME_TYPE_AUTO, MIME_TYPES_DICT, normalizeMimeTypeForCKEditor, type MimeTypeDefinition } from "./mime_type_definitions.js";
import { normalizeMimeTypeForCKEditor, type MimeType, MIME_TYPE_AUTO, MIME_TYPES_DICT } from "@triliumnext/commons";
import options from "./options.js";
interface MimeType extends MimeTypeDefinition {
/**
* True if this mime type was enabled by the user in the "Available MIME types in the dropdown" option in the Code Notes settings.
*/
enabled: boolean;
}
let mimeTypes: MimeType[] | null = null;
function loadMimeTypes() {
@ -45,8 +38,8 @@ export function getHighlightJsNameForMime(mimeType: string) {
for (const mimeType of mimeTypes) {
// The mime stored by CKEditor is text-x-csrc instead of text/x-csrc so we keep this format for faster lookup.
const normalizedMime = normalizeMimeTypeForCKEditor(mimeType.mime);
if (mimeType.highlightJs) {
mimeToHighlightJsMapping[normalizedMime] = mimeType.highlightJs;
if (mimeType.mdLanguageCode) {
mimeToHighlightJsMapping[normalizedMime] = mimeType.mdLanguageCode;
}
}
}

View File

@ -1,19 +1,8 @@
import library_loader from "./library_loader.js";
import { ensureMimeTypes, highlight, highlightAuto, loadTheme, Themes } from "@triliumnext/highlightjs";
import mime_types from "./mime_types.js";
import options from "./options.js";
export function getStylesheetUrl(theme: string) {
if (!theme) {
return null;
}
const defaultPrefix = "default:";
if (theme.startsWith(defaultPrefix)) {
return `${window.glob.assetPath}/node_modules/@highlightjs/cdn-assets/styles/${theme.substr(defaultPrefix.length)}.min.css`;
}
return null;
}
let highlightingLoaded = false;
/**
* 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.
@ -25,6 +14,8 @@ export async function applySyntaxHighlight($container: JQuery<HTMLElement>) {
return;
}
await ensureMimeTypesForHighlighting();
const codeBlocks = $container.find("pre code");
for (const codeBlock of codeBlocks) {
const normalizedMimeType = extractLanguageFromClassList(codeBlock);
@ -43,20 +34,13 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
$codeBlock.parent().toggleClass("hljs");
const text = $codeBlock.text();
if (!window.hljs) {
await library_loader.requireLibrary(library_loader.HIGHLIGHT_JS);
}
let highlightedText = null;
if (normalizedMimeType === mime_types.MIME_TYPE_AUTO) {
highlightedText = hljs.highlightAuto(text);
await ensureMimeTypesForHighlighting();
highlightedText = highlightAuto(text);
} else if (normalizedMimeType) {
const language = mime_types.getHighlightJsNameForMime(normalizedMimeType);
if (language) {
highlightedText = hljs.highlight(text, { language });
} else {
console.warn(`Unknown mime type: ${normalizedMimeType}.`);
}
await ensureMimeTypesForHighlighting();
highlightedText = highlight(text, { language: normalizedMimeType });
}
if (highlightedText) {
@ -64,6 +48,35 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
}
}
export async function ensureMimeTypesForHighlighting() {
if (highlightingLoaded) {
return;
}
// Load theme.
const currentThemeName = String(options.get("codeBlockTheme"));
loadHighlightingTheme(currentThemeName);
// Load mime types.
const mimeTypes = mime_types.getMimeTypes();
await ensureMimeTypes(mimeTypes);
highlightingLoaded = true;
}
export function loadHighlightingTheme(themeName: string) {
const themePrefix = "default:";
let theme = null;
if (themeName.includes(themePrefix)) {
theme = Themes[themeName.substring(themePrefix.length)];
}
if (!theme) {
theme = Themes.default;
}
loadTheme(theme);
}
/**
* 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.

View File

@ -1621,7 +1621,10 @@
"color-scheme": "颜色方案"
},
"code_block": {
"word_wrapping": "自动换行"
"word_wrapping": "自动换行",
"theme_none": "无语法高亮",
"theme_group_light": "浅色主题",
"theme_group_dark": "深色主题"
},
"classic_editor_toolbar": {
"title": "格式化"

View File

@ -1573,7 +1573,10 @@
"color-scheme": "Farbschema"
},
"code_block": {
"word_wrapping": "Wortumbruch"
"word_wrapping": "Wortumbruch",
"theme_none": "Keine Syntax-Hervorhebung",
"theme_group_light": "Helle Themen",
"theme_group_dark": "Dunkle Themen"
},
"classic_editor_toolbar": {
"title": "Format"

View File

@ -1827,7 +1827,10 @@
"color-scheme": "Color Scheme"
},
"code_block": {
"word_wrapping": "Word wrapping"
"word_wrapping": "Word wrapping",
"theme_none": "No syntax highlighting",
"theme_group_light": "Light themes",
"theme_group_dark": "Dark themes"
},
"classic_editor_toolbar": {
"title": "Formatting"

View File

@ -1589,7 +1589,10 @@
"color-scheme": "Esquema de color"
},
"code_block": {
"word_wrapping": "Ajuste de palabras"
"word_wrapping": "Ajuste de palabras",
"theme_none": "Sin resaltado de sintaxis",
"theme_group_light": "Temas claros",
"theme_group_dark": "Temas oscuros"
},
"classic_editor_toolbar": {
"title": "Formato"

View File

@ -1579,7 +1579,10 @@
"color-scheme": "Jeu de couleurs"
},
"code_block": {
"word_wrapping": "Saut à la ligne automatique suivant la largeur"
"word_wrapping": "Saut à la ligne automatique suivant la largeur",
"theme_none": "Pas de coloration syntaxique",
"theme_group_light": "Thèmes clairs",
"theme_group_dark": "Thèmes sombres"
},
"classic_editor_toolbar": {
"title": "Mise en forme"

View File

@ -1,5 +1,10 @@
{
"revisions": {
"delete_button": ""
},
"code_block": {
"theme_none": "Sem destaque de sintaxe",
"theme_group_light": "Temas claros",
"theme_group_dark": "Temas escuros"
}
}

View File

@ -1585,7 +1585,10 @@
"description": "Controlează evidențierea de sintaxă pentru blocurile de cod în interiorul notițelor text, notițele de tip cod nu vor fi afectate de aceste setări."
},
"code_block": {
"word_wrapping": "Încadrare text"
"word_wrapping": "Încadrare text",
"theme_none": "Fără evidențiere de sintaxă",
"theme_group_dark": "Teme întunecate",
"theme_group_light": "Teme luminoase"
},
"classic_editor_toolbar": {
"title": "Formatare"

View File

@ -1519,7 +1519,10 @@
"color-scheme": "顏色方案"
},
"code_block": {
"word_wrapping": "自動換行"
"word_wrapping": "自動換行",
"theme_none": "無格式高亮",
"theme_group_light": "淺色主題",
"theme_group_dark": "深色主題"
},
"classic_editor_toolbar": {
"title": "格式化"

View File

@ -123,15 +123,6 @@ declare global {
var require: RequireMethod;
var __non_webpack_require__: RequireMethod | undefined;
// Libraries
// TODO: Replace once library loader is replaced with webpack.
var hljs: {
highlightAuto(text: string);
highlight(text: string, {
language: string
});
};
/*
* Panzoom
*/

View File

@ -3,12 +3,10 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import SpacedUpdate from "../services/spaced_update.js";
import server from "../services/server.js";
import libraryLoader from "../services/library_loader.js";
import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import noteCreateService from "../services/note_create.js";
import attributeService from "../services/attributes.js";
import attributeRenderer from "../services/attribute_renderer.js";
import EmptyTypeWidget from "./type_widgets/empty.js";
import EditableTextTypeWidget from "./type_widgets/editable_text.js";
@ -30,7 +28,6 @@ import ContentWidgetTypeWidget from "./type_widgets/content_widget.js";
import AttachmentListTypeWidget from "./type_widgets/attachment_list.js";
import AttachmentDetailTypeWidget from "./type_widgets/attachment_detail.js";
import MindMapWidget from "./type_widgets/mind_map.js";
import { getStylesheetUrl, isSyntaxHighlightEnabled } from "../services/syntax_highlight.js";
import GeoMapTypeWidget from "./type_widgets/geo_map.js";
import utils from "../services/utils.js";
import type { NoteType } from "../entities/fnote.js";

View File

@ -1,9 +1,8 @@
import library_loader from "../../../services/library_loader.js";
import { ALLOWED_PROTOCOLS } from "../../../services/link.js";
import { MIME_TYPE_AUTO } from "../../../services/mime_type_definitions.js";
import { MIME_TYPE_AUTO } from "@triliumnext/commons";
import { getHighlightJsNameForMime } from "../../../services/mime_types.js";
import options from "../../../services/options.js";
import { isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import utils from "../../../services/utils.js";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/emoji_definitions/en.json?url";
@ -104,9 +103,9 @@ export function buildConfig() {
definitionsUrl: new URL(import.meta.url).origin + emojiDefinitionsUrl
},
syntaxHighlighting: {
async loadHighlightJs() {
await library_loader.requireLibrary(library_loader.HIGHLIGHT_JS);
return hljs;
loadHighlightJs: async () => {
await ensureMimeTypesForHighlighting();
return await import("@triliumnext/highlightjs");
},
mapLanguageName: getHighlightJsNameForMime,
defaultMimeType: MIME_TYPE_AUTO,

View File

@ -12,13 +12,13 @@ import appContext, { type CommandListenerData, type EventData } from "../../comp
import dialogService from "../../services/dialog.js";
import options from "../../services/options.js";
import toast from "../../services/toast.js";
import { normalizeMimeTypeForCKEditor } from "../../services/mime_type_definitions.js";
import { buildSelectedBackgroundColor } from "../../components/touch_bar.js";
import { buildConfig, buildToolbarConfig } from "./ckeditor/config.js";
import type FNote from "../../entities/fnote.js";
import { getMermaidConfig } from "../../services/mermaid.js";
import { PopupEditor, ClassicEditor, EditorWatchdog, type CKTextEditor, type MentionFeed, type WatchdogConfig } from "@triliumnext/ckeditor5";
import "@triliumnext/ckeditor5/index.css";
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
const ENABLE_INSPECTOR = false;

View File

@ -1,10 +1,11 @@
import type { OptionMap } from "@triliumnext/commons";
import { normalizeMimeTypeForCKEditor, type OptionMap } from "@triliumnext/commons";
import { t } from "../../../../services/i18n.js";
import library_loader from "../../../../services/library_loader.js";
import server from "../../../../services/server.js";
import OptionsWidget from "../options_widget.js";
import { ensureMimeTypesForHighlighting, loadHighlightingTheme } from "../../../../services/syntax_highlight.js";
import { Themes, type Theme } from "@triliumnext/highlightjs";
const SAMPLE_LANGUAGE = "javascript";
const SAMPLE_LANGUAGE = normalizeMimeTypeForCKEditor("application/javascript;env=frontend");
const SAMPLE_CODE = `\
const n = 10;
greet(n); // Print "Hello World" for n times
@ -55,14 +56,6 @@ const TPL = /*html*/`
</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.
*/
@ -75,9 +68,31 @@ export default class CodeBlockOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
this.$themeSelect = this.$widget.find(".theme-select");
// Populate the list of themes.
const themeGroups = groupThemesByLightOrDark();
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.on("change", async () => {
const newTheme = String(this.$themeSelect.val());
library_loader.loadHighlightingTheme(newTheme);
loadHighlightingTheme(newTheme);
await server.put(`options/codeBlockTheme/${newTheme}`);
});
@ -91,11 +106,14 @@ export default class CodeBlockOptions extends OptionsWidget {
#setupPreview(shouldEnableSyntaxHighlight: boolean) {
const text = SAMPLE_CODE;
if (shouldEnableSyntaxHighlight) {
library_loader.requireLibrary(library_loader.HIGHLIGHT_JS).then(() => {
import("@triliumnext/highlightjs").then(async (hljs) => {
await ensureMimeTypesForHighlighting();
const highlightedText = hljs.highlight(text, {
language: SAMPLE_LANGUAGE
});
this.$sampleEl.html(highlightedText.value);
if (highlightedText) {
this.$sampleEl.html(highlightedText.value);
}
});
} else {
this.$sampleEl.text(text);
@ -103,25 +121,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");
@ -129,3 +128,38 @@ export default class CodeBlockOptions extends OptionsWidget {
this.#setupPreview(options.codeBlockTheme !== "none");
}
}
interface ThemeData {
val: string;
title: string;
}
function groupThemesByLightOrDark() {
const darkThemes: ThemeData[] = [];
const lightThemes: ThemeData[] = [];
for (const [ id, theme ] of Object.entries(Themes)) {
const data: ThemeData = {
val: "default:" + id,
title: theme.name
};
if (theme.name.includes("Dark")) {
darkThemes.push(data);
} else {
lightThemes.push(data);
}
}
const output: Record<string, ThemeData[]> = {
"": [
{
val: "none",
title: t("code_block.theme_none")
}
]
};
output[t("code_block.theme_group_light")] = lightThemes;
output[t("code_block.theme_group_dark")] = darkThemes;
return output;
}

View File

@ -34,6 +34,9 @@
"src/**/*.ts"
],
"references": [
{
"path": "../../packages/highlightjs/tsconfig.lib.json"
},
{
"path": "../../packages/codemirror/tsconfig.lib.json"
},

View File

@ -3,6 +3,9 @@
"files": [],
"include": [],
"references": [
{
"path": "../../packages/highlightjs"
},
{
"path": "../../packages/codemirror"
},

View File

@ -11,8 +11,7 @@
"electron-dl": "4.0.0",
"electron-squirrel-startup": "1.0.1",
"jquery.fancytree": "2.38.5",
"jquery-hotkeys": "0.2.2",
"@highlightjs/cdn-assets": "11.11.1"
"jquery-hotkeys": "0.2.2"
},
"devDependencies": {
"@types/electron-squirrel-startup": "1.0.2",

View File

@ -193,11 +193,6 @@
"special_notes": {
"search_prefix": "搜索:"
},
"code_block": {
"theme_none": "无语法高亮",
"theme_group_light": "浅色主题",
"theme_group_dark": "深色主题"
},
"test_sync": {
"not-configured": "同步服务器主机未配置。请先配置同步。",
"successful": "同步服务器握手成功,同步已开始。"

View File

@ -185,11 +185,6 @@
"special_notes": {
"search_prefix": "Suche:"
},
"code_block": {
"theme_none": "Keine Syntax-Hervorhebung",
"theme_group_light": "Helle Themen",
"theme_group_dark": "Dunkle Themen"
},
"test_sync": {
"not-configured": "Der Synchronisations-Server-Host ist nicht konfiguriert. Bitte konfiguriere zuerst die Synchronisation.",
"successful": "Die Server-Verbindung wurde erfolgreich hergestellt, die Synchronisation wurde gestartet."

View File

@ -193,11 +193,6 @@
"special_notes": {
"search_prefix": "Search:"
},
"code_block": {
"theme_none": "No syntax highlighting",
"theme_group_light": "Light themes",
"theme_group_dark": "Dark themes"
},
"test_sync": {
"not-configured": "Sync server host is not configured. Please configure sync first.",
"successful": "Sync server handshake has been successful, sync has been started."

View File

@ -189,11 +189,6 @@
"special_notes": {
"search_prefix": "Buscar:"
},
"code_block": {
"theme_none": "Sin resaltado de sintaxis",
"theme_group_light": "Temas claros",
"theme_group_dark": "Temas oscuros"
},
"test_sync": {
"not-configured": "El servidor de sincronización no está configurado. Por favor configure primero la sincronización.",
"successful": "El protocolo de enlace del servidor de sincronización ha sido exitoso, la sincronización ha comenzado."

View File

@ -189,11 +189,6 @@
"special_notes": {
"search_prefix": "Recherche :"
},
"code_block": {
"theme_none": "Pas de coloration syntaxique",
"theme_group_light": "Thèmes clairs",
"theme_group_dark": "Thèmes sombres"
},
"test_sync": {
"not-configured": "L'hôte du serveur de synchronisation n'est pas configuré. Veuillez d'abord configurer la synchronisation.",
"successful": "L'établissement de liaison du serveur de synchronisation a été réussi, la synchronisation a été démarrée."

View File

@ -186,11 +186,6 @@
"special_notes": {
"search_prefix": "Pesquisar:"
},
"code_block": {
"theme_none": "Sem destaque de sintaxe",
"theme_group_light": "Temas claros",
"theme_group_dark": "Temas escuros"
},
"test_sync": {
"not-configured": "O host do servidor de sincronização não está configurado. Por favor, configure a sincronização primeiro.",
"successful": "A comunicação com o servidor de sincronização foi bem-sucedida, a sincronização foi iniciada."

View File

@ -189,11 +189,6 @@
"special_notes": {
"search_prefix": "Căutare:"
},
"code_block": {
"theme_none": "Fără evidențiere de sintaxă",
"theme_group_dark": "Teme întunecate",
"theme_group_light": "Teme luminoase"
},
"test_sync": {
"not-configured": "Calea către serverul de sincronizare nu este configurată. Configurați sincronizarea înainte.",
"successful": "Comunicarea cu serverul de sincronizare a avut loc cu succes, s-a început sincronizarea."

View File

@ -185,11 +185,6 @@
"special_notes": {
"search_prefix": "搜尋:"
},
"code_block": {
"theme_none": "無格式高亮",
"theme_group_light": "淺色主題",
"theme_group_dark": "深色主題"
},
"test_sync": {
"not-configured": "並未設定同步伺服器主機,請先設定同步",
"successful": "成功與同步伺服器握手,現在開始同步"

View File

@ -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
};

View File

@ -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);

View File

@ -1,22 +0,0 @@
import { describe, expect, it } from "vitest";
import { readThemesFromFileSystem } from "./code_block_theme.js";
import themeNames from "./code_block_theme_names.json" with { type: "json" };
import path = require("path");
describe("Code block theme", () => {
it("all themes are mapped", () => {
const themes = readThemesFromFileSystem(path.join(__dirname, "../../node_modules/@highlightjs/cdn-assets/styles"));
const mappedThemeNames = new Set(Object.values(themeNames));
const unmappedThemeNames = new Set<string>();
for (const theme of themes) {
if (!mappedThemeNames.has(theme.title)) {
unmappedThemeNames.add(theme.title);
}
}
expect(unmappedThemeNames.size, `Unmapped themes: ${Array.from(unmappedThemeNames).join(", ")}`).toBe(0);
});
});

View File

@ -1,107 +0,0 @@
/**
* @module
*
* Manages the server-side functionality of the code blocks feature, mostly for obtaining the available themes for syntax highlighting.
*/
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";
/**
* Represents a color scheme for the code block syntax highlight.
*/
interface ColorTheme {
/** The ID of the color scheme which should be stored in the options. */
val: string;
/** A user-friendly name of the theme. The name is already localized. */
title: string;
}
/**
* Returns all the supported syntax highlighting themes for code blocks, in groups.
*
* The return value is an object where the keys represent groups in their human-readable name (e.g. "Light theme")
* and the values are an array containing the information about every theme. There is also a special group with no
* title (empty string) which should be displayed at the top of the listing pages, without a group.
*
* @returns the supported themes, grouped.
*/
export function listSyntaxHighlightingThemes() {
const path = getStylesDirectory();
const systemThemes = readThemesFromFileSystem(path);
return {
"": [
{
val: "none",
title: t("code_block.theme_none")
}
],
...groupThemesByLightOrDark(systemThemes)
};
}
export function getStylesDirectory() {
if (isElectron && !isDev) {
return join(getResourceDir(), "styles");
} else if (!isDev) {
return join(getResourceDir(), "node_modules/@highlightjs/cdn-assets/styles");
} else {
return join(__dirname, "../node_modules/@highlightjs/cdn-assets/styles");
}
}
/**
* Reads all the predefined themes by listing all minified CSSes from a given directory.
*
* The theme names are mapped against a known list in order to provide more descriptive names such as "Visual Studio 2015 (Dark)" instead of "vs2015".
*
* @param path the path to read from. Usually this is the highlight.js `styles` directory.
* @returns the list of themes.
*/
export function readThemesFromFileSystem(path: string): ColorTheme[] {
return fs
.readdirSync(path)
.filter((el) => el.endsWith(".min.css"))
.map((name) => {
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
};
});
}
/**
* Groups a list of themes by dark or light themes. This is done simply by checking whether "Dark" is present in the given theme, otherwise it's considered a light theme.
* This generally only works if the theme has a known human-readable name (see {@link #readThemesFromFileSystem()})
*
* @param listOfThemes the list of themes to be grouped.
* @returns the grouped themes by light or dark.
*/
function groupThemesByLightOrDark(listOfThemes: ColorTheme[]) {
const darkThemes = [];
const lightThemes = [];
for (const theme of listOfThemes) {
if (theme.title.includes("Dark")) {
darkThemes.push(theme);
} else {
lightThemes.push(theme);
}
}
const output: Record<string, ColorTheme[]> = {};
output[t("code_block.theme_group_light")] = lightThemes;
output[t("code_block.theme_group_dark")] = darkThemes;
return output;
}

View File

@ -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)"
}

View File

@ -1,6 +1,12 @@
"use strict";
import { parse, Renderer, type Tokens } from "marked";
import htmlSanitizer from "../html_sanitizer.js";
import importUtils from "./utils.js";
import { getMimeTypeFromMarkdownName, MIME_TYPE_AUTO } from "@triliumnext/commons";
import { ADMONITION_TYPE_MAPPINGS } from "../export/markdown.js";
import utils from "../utils.js";
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
/**
* Keep renderer code up to date with https://github.com/markedjs/marked/blob/master/src/Renderer.ts.
@ -123,14 +129,6 @@ class CustomMarkdownRenderer extends Renderer {
}
const renderer = new CustomMarkdownRenderer({ async: false });
import htmlSanitizer from "../html_sanitizer.js";
import importUtils from "./utils.js";
import { getMimeTypeFromHighlightJs, MIME_TYPE_AUTO, normalizeMimeTypeForCKEditor } from "./mime_type_definitions.js";
import { ADMONITION_TYPE_MAPPINGS } from "../export/markdown.js";
import utils from "../utils.js";
function renderToHtml(content: string, title: string) {
// Double-escape slashes in math expression because they are otherwise consumed by the parser somewhere.
content = content.replaceAll("\\$", "\\\\$");
@ -158,15 +156,17 @@ function renderToHtml(content: string, title: string) {
function getNormalizedMimeFromMarkdownLanguage(language: string | undefined) {
if (language) {
const highlightJsName = getMimeTypeFromHighlightJs(language);
if (highlightJsName) {
return normalizeMimeTypeForCKEditor(highlightJsName.mime);
const mimeDefinition = getMimeTypeFromMarkdownName(language);
if (mimeDefinition) {
return normalizeMimeTypeForCKEditor(mimeDefinition.mime);
}
}
return MIME_TYPE_AUTO;
}
const renderer = new CustomMarkdownRenderer({ async: false });
export default {
renderToHtml
};

View File

@ -1,223 +0,0 @@
// TODO: deduplicate with /src/public/app/services/mime_type_definitions.ts
/**
* A pseudo-MIME type which is used in the editor to automatically determine the language used in code blocks via heuristics.
*/
export const MIME_TYPE_AUTO = "text-x-trilium-auto";
export interface MimeTypeDefinition {
default?: boolean;
title: string;
mime: string;
/** The name of the language/mime type as defined by highlight.js (or one of the aliases), in order to be used for syntax highlighting such as inside code blocks. */
highlightJs?: string;
/** If specified, will load the corresponding highlight.js file from the `libraries/highlightjs/${id}.js` instead of `node_modules/@highlightjs/cdn-assets/languages/${id}.min.js`. */
highlightJsSource?: "libraries";
/** If specified, will load the corresponding highlight file from the given path instead of `node_modules`. */
codeMirrorSource?: string;
}
/**
* For highlight.js-supported languages, see https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md.
*/
export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([
{ title: "Plain text", mime: "text/plain", highlightJs: "plaintext", default: true },
// Keep sorted alphabetically.
{ title: "APL", mime: "text/apl" },
{ title: "ASN.1", mime: "text/x-ttcn-asn" },
{ title: "ASP.NET", mime: "application/x-aspx" },
{ title: "Asterisk", mime: "text/x-asterisk" },
{ title: "Batch file (DOS)", mime: "application/x-bat", highlightJs: "dos", codeMirrorSource: "libraries/codemirror/batch.js" },
{ title: "Brainfuck", mime: "text/x-brainfuck", highlightJs: "brainfuck" },
{ title: "C", mime: "text/x-csrc", highlightJs: "c", default: true },
{ title: "C#", mime: "text/x-csharp", highlightJs: "csharp", default: true },
{ title: "C++", mime: "text/x-c++src", highlightJs: "cpp", default: true },
{ title: "Clojure", mime: "text/x-clojure", highlightJs: "clojure" },
{ title: "ClojureScript", mime: "text/x-clojurescript" },
{ title: "Closure Stylesheets (GSS)", mime: "text/x-gss" },
{ title: "CMake", mime: "text/x-cmake", highlightJs: "cmake" },
{ title: "Cobol", mime: "text/x-cobol" },
{ title: "CoffeeScript", mime: "text/coffeescript", highlightJs: "coffeescript" },
{ title: "Common Lisp", mime: "text/x-common-lisp", highlightJs: "lisp" },
{ title: "CQL", mime: "text/x-cassandra" },
{ title: "Crystal", mime: "text/x-crystal", highlightJs: "crystal" },
{ title: "CSS", mime: "text/css", highlightJs: "css", default: true },
{ title: "Cypher", mime: "application/x-cypher-query" },
{ title: "Cython", mime: "text/x-cython" },
{ title: "D", mime: "text/x-d", highlightJs: "d" },
{ title: "Dart", mime: "application/dart", highlightJs: "dart" },
{ title: "diff", mime: "text/x-diff", highlightJs: "diff" },
{ title: "Django", mime: "text/x-django", highlightJs: "django" },
{ title: "Dockerfile", mime: "text/x-dockerfile", highlightJs: "dockerfile" },
{ title: "DTD", mime: "application/xml-dtd" },
{ title: "Dylan", mime: "text/x-dylan" },
{ title: "EBNF", mime: "text/x-ebnf", highlightJs: "ebnf" },
{ title: "ECL", mime: "text/x-ecl" },
{ title: "edn", mime: "application/edn" },
{ title: "Eiffel", mime: "text/x-eiffel" },
{ title: "Elm", mime: "text/x-elm", highlightJs: "elm" },
{ title: "Embedded Javascript", mime: "application/x-ejs" },
{ title: "Embedded Ruby", mime: "application/x-erb", highlightJs: "erb" },
{ title: "Erlang", mime: "text/x-erlang", highlightJs: "erlang" },
{ title: "Esper", mime: "text/x-esper" },
{ title: "F#", mime: "text/x-fsharp", highlightJs: "fsharp" },
{ title: "Factor", mime: "text/x-factor" },
{ title: "FCL", mime: "text/x-fcl" },
{ title: "Forth", mime: "text/x-forth" },
{ title: "Fortran", mime: "text/x-fortran", highlightJs: "fortran" },
{ title: "Gas", mime: "text/x-gas" },
{ title: "GDScript (Godot)", mime: "text/x-gdscript" },
{ title: "Gherkin", mime: "text/x-feature", highlightJs: "gherkin" },
{ title: "GitHub Flavored Markdown", mime: "text/x-gfm", highlightJs: "markdown" },
{ title: "Go", mime: "text/x-go", highlightJs: "go", default: true },
{ title: "Groovy", mime: "text/x-groovy", highlightJs: "groovy", default: true },
{ title: "HAML", mime: "text/x-haml", highlightJs: "haml" },
{ title: "Haskell (Literate)", mime: "text/x-literate-haskell" },
{ title: "Haskell", mime: "text/x-haskell", highlightJs: "haskell", default: true },
{ title: "Haxe", mime: "text/x-haxe", highlightJs: "haxe" },
{ title: "HTML", mime: "text/html", highlightJs: "xml", default: true },
{ title: "HTTP", mime: "message/http", highlightJs: "http", default: true },
{ title: "HXML", mime: "text/x-hxml" },
{ title: "IDL", mime: "text/x-idl" },
{ title: "Java Server Pages", mime: "application/x-jsp", highlightJs: "java" },
{ title: "Java", mime: "text/x-java", highlightJs: "java", default: true },
{ title: "Jinja2", mime: "text/jinja2" },
{ title: "JS backend", mime: "application/javascript;env=backend", highlightJs: "javascript", default: true },
{ title: "JS frontend", mime: "application/javascript;env=frontend", highlightJs: "javascript", default: true },
{ title: "JSON-LD", mime: "application/ld+json", highlightJs: "json" },
{ title: "JSON", mime: "application/json", highlightJs: "json", default: true },
{ title: "JSX", mime: "text/jsx", highlightJs: "javascript" },
{ title: "Julia", mime: "text/x-julia", highlightJs: "julia" },
{ title: "Kotlin", mime: "text/x-kotlin", highlightJs: "kotlin", default: true },
{ title: "LaTeX", mime: "text/x-latex", highlightJs: "latex" },
{ title: "LESS", mime: "text/x-less", highlightJs: "less" },
{ title: "LiveScript", mime: "text/x-livescript", highlightJs: "livescript" },
{ title: "Lua", mime: "text/x-lua", highlightJs: "lua" },
{ title: "MariaDB SQL", mime: "text/x-mariadb", highlightJs: "sql" },
{ title: "Markdown", mime: "text/x-markdown", highlightJs: "markdown", default: true },
{ title: "Mathematica", mime: "text/x-mathematica", highlightJs: "mathematica" },
{ title: "mbox", mime: "application/mbox" },
{ title: "MIPS Assembler", mime: "text/x-asm-mips", highlightJs: "mips" },
{ title: "mIRC", mime: "text/mirc" },
{ title: "Modelica", mime: "text/x-modelica" },
{ title: "MS SQL", mime: "text/x-mssql", highlightJs: "sql" },
{ title: "mscgen", mime: "text/x-mscgen" },
{ title: "msgenny", mime: "text/x-msgenny" },
{ title: "MUMPS", mime: "text/x-mumps" },
{ title: "MySQL", mime: "text/x-mysql", highlightJs: "sql" },
{ title: "Nix", mime: "text/x-nix", highlightJs: "nix" },
{ title: "Nginx", mime: "text/x-nginx-conf", highlightJs: "nginx" },
{ title: "NSIS", mime: "text/x-nsis", highlightJs: "nsis" },
{ title: "NTriples", mime: "application/n-triples" },
{ title: "Objective-C", mime: "text/x-objectivec", highlightJs: "objectivec" },
{ title: "OCaml", mime: "text/x-ocaml", highlightJs: "ocaml" },
{ title: "Octave", mime: "text/x-octave" },
{ title: "Oz", mime: "text/x-oz" },
{ title: "Pascal", mime: "text/x-pascal", highlightJs: "delphi" },
{ title: "PEG.js", mime: "null" },
{ title: "Perl", mime: "text/x-perl", default: true },
{ title: "PGP", mime: "application/pgp" },
{ title: "PHP", mime: "text/x-php", default: true },
{ title: "Pig", mime: "text/x-pig" },
{ title: "PLSQL", mime: "text/x-plsql", highlightJs: "sql" },
{ title: "PostgreSQL", mime: "text/x-pgsql", highlightJs: "pgsql" },
{ title: "PowerShell", mime: "application/x-powershell", highlightJs: "powershell" },
{ title: "Properties files", mime: "text/x-properties", highlightJs: "properties" },
{ title: "ProtoBuf", mime: "text/x-protobuf", highlightJs: "protobuf" },
{ title: "Pug", mime: "text/x-pug" },
{ title: "Puppet", mime: "text/x-puppet", highlightJs: "puppet" },
{ title: "Python", mime: "text/x-python", highlightJs: "python", default: true },
{ title: "Q", mime: "text/x-q", highlightJs: "q" },
{ title: "R", mime: "text/x-rsrc", highlightJs: "r" },
{ title: "reStructuredText", mime: "text/x-rst" },
{ title: "RPM Changes", mime: "text/x-rpm-changes" },
{ title: "RPM Spec", mime: "text/x-rpm-spec" },
{ title: "Ruby", mime: "text/x-ruby", highlightJs: "ruby", default: true },
{ title: "Rust", mime: "text/x-rustsrc", highlightJs: "rust" },
{ title: "SAS", mime: "text/x-sas", highlightJs: "sas" },
{ title: "Sass", mime: "text/x-sass" },
{ title: "Scala", mime: "text/x-scala" },
{ title: "Scheme", mime: "text/x-scheme" },
{ title: "SCSS", mime: "text/x-scss", highlightJs: "scss" },
{ title: "Shell (bash)", mime: "text/x-sh", highlightJs: "bash", default: true },
{ title: "Sieve", mime: "application/sieve" },
{ title: "Slim", mime: "text/x-slim" },
{ title: "Smalltalk", mime: "text/x-stsrc", highlightJs: "smalltalk" },
{ title: "Smarty", mime: "text/x-smarty" },
{ title: "SML", mime: "text/x-sml", highlightJs: "sml" },
{ title: "Solr", mime: "text/x-solr" },
{ title: "Soy", mime: "text/x-soy" },
{ title: "SPARQL", mime: "application/sparql-query" },
{ title: "Spreadsheet", mime: "text/x-spreadsheet" },
{ title: "SQL", mime: "text/x-sql", highlightJs: "sql", default: true },
{ title: "SQLite (Trilium)", mime: "text/x-sqlite;schema=trilium", highlightJs: "sql", default: true },
{ title: "SQLite", mime: "text/x-sqlite", highlightJs: "sql" },
{ title: "Squirrel", mime: "text/x-squirrel" },
{ title: "sTeX", mime: "text/x-stex" },
{ title: "Stylus", mime: "text/x-styl", highlightJs: "stylus" },
{ title: "Swift", mime: "text/x-swift", default: true },
{ title: "SystemVerilog", mime: "text/x-systemverilog" },
{ title: "Tcl", mime: "text/x-tcl", highlightJs: "tcl" },
{ title: "Terraform (HCL)", mime: "text/x-hcl", highlightJs: "terraform", highlightJsSource: "libraries", codeMirrorSource: "libraries/codemirror/hcl.js" },
{ title: "Textile", mime: "text/x-textile" },
{ title: "TiddlyWiki ", mime: "text/x-tiddlywiki" },
{ title: "Tiki wiki", mime: "text/tiki" },
{ title: "TOML", mime: "text/x-toml", highlightJs: "ini" },
{ title: "Tornado", mime: "text/x-tornado" },
{ title: "troff", mime: "text/troff" },
{ title: "TTCN_CFG", mime: "text/x-ttcn-cfg" },
{ title: "TTCN", mime: "text/x-ttcn" },
{ title: "Turtle", mime: "text/turtle" },
{ title: "Twig", mime: "text/x-twig", highlightJs: "twig" },
{ title: "TypeScript-JSX", mime: "text/typescript-jsx" },
{ title: "TypeScript", mime: "application/typescript", highlightJs: "typescript" },
{ title: "VB.NET", mime: "text/x-vb", highlightJs: "vbnet" },
{ title: "VBScript", mime: "text/vbscript", highlightJs: "vbscript" },
{ title: "Velocity", mime: "text/velocity" },
{ title: "Verilog", mime: "text/x-verilog", highlightJs: "verilog" },
{ title: "VHDL", mime: "text/x-vhdl", highlightJs: "vhdl" },
{ title: "Vue.js Component", mime: "text/x-vue" },
{ title: "Web IDL", mime: "text/x-webidl" },
{ title: "XML", mime: "text/xml", highlightJs: "xml", default: true },
{ title: "XQuery", mime: "application/xquery", highlightJs: "xquery" },
{ title: "xu", mime: "text/x-xu" },
{ title: "Yacas", mime: "text/x-yacas" },
{ title: "YAML", mime: "text/x-yaml", highlightJs: "yaml", default: true },
{ title: "Z80", mime: "text/x-z80" }
]);
/**
* Given a MIME type in the usual format (e.g. `text/csrc`), it returns a MIME type that can be passed down to the CKEditor
* code plugin.
*
* @param mimeType The MIME type to normalize, in the usual format (e.g. `text/c-src`).
* @returns the normalized MIME type (e.g. `text-c-src`).
*/
export function normalizeMimeTypeForCKEditor(mimeType: string) {
return mimeType.toLowerCase().replace(/[\W_]+/g, "-");
}
let byHighlightJsNameMappings: Record<string, MimeTypeDefinition> | null = null;
/**
* Given a Highlight.js language tag (e.g. `css`), it returns a corresponding {@link MimeTypeDefinition} if found.
*
* If there are multiple {@link MimeTypeDefinition}s for the language tag, then only the first one is retrieved. For example for `javascript`, the "JS frontend" mime type is returned.
*
* @param highlightJsName a language tag.
* @returns the corresponding {@link MimeTypeDefinition} if found, or `undefined` otherwise.
*/
export function getMimeTypeFromHighlightJs(highlightJsName: string) {
if (!byHighlightJsNameMappings) {
byHighlightJsNameMappings = {};
for (const mimeType of MIME_TYPES_DICT) {
if (mimeType.highlightJs && !byHighlightJsNameMappings[mimeType.highlightJs]) {
byHighlightJsNameMappings[mimeType.highlightJs] = mimeType;
}
}
}
return byHighlightJsNameMappings[highlightJsName];
}

View File

@ -32,10 +32,25 @@
* [Make it show which node triggered the event when right-clicking on tree](https://github.com/TriliumNext/Notes/pull/1861) by @SiriusXT
* [Only expand/collapse the left pane of the focused window](https://github.com/TriliumNext/Notes/pull/1905) by @SiriusXT
* Code notes:
* Added the GDScript (Godot) language.
* Added the GDScript (Godot) language for both code notes and code blocks in text notes.
* Added the Nix language (and also in code blocks for text notes).
* Added an indentation marker.
* Note: syntax highlighting for some languages (mostly HTML-template languages such as EJS, JSP) is no longer supported due to lack of upstream support. If this is a problem, feel free to report an issue and we can see what can be done about it.
* Syntax highlighting in code blocks for text notes:
* Added support for Cypher.
* Added support for XML-DTD.
* Added support for Jinja2.
* Added support for ClojureScript.
* Added support for Perl.
* Added support for Scala.
* Added support for Scheme.
* Added support for Swift.
* Added support for SystemVerilog.
* Added support for mIRC.
* Added support for Cobol.
* Added support for Dylan.
* Added support for RPM Specfile.
* Added support for TCCN3.
* Mermaid diagrams: basic syntax highlight (not all diagram types are supported) and code folding.
* Slight organization in Appearance settings: code block themes are now in "Text Notes", added a "Related settings" section in Appearance.
* [Added support for opening and activating a note in a new tab using Ctrl+Shift+click on notes in the launcher pane, note tree, or note images](https://github.com/TriliumNext/Notes/pull/1854) by @SiriusXT

View File

@ -173,14 +173,6 @@ export default class SyntaxHighlighting extends Plugin {
return;
}
// Find the corresponding language for the given mimetype.
const highlightJsLanguage = this.config.mapLanguageName(mimeType);
if (mimeType !== this.config.defaultMimeType && !highlightJsLanguage) {
console.warn(`Unsupported highlight.js for mime type ${mimeType}.`);
return;
}
// Don't highlight if the code is too big, as the typing performance will be highly degraded.
if (codeBlock.childCount >= HIGHLIGHT_MAX_BLOCK_COUNT) {
return;
@ -230,8 +222,13 @@ export default class SyntaxHighlighting extends Plugin {
if (mimeType === this.config.defaultMimeType) {
highlightRes = this.hljs.highlightAuto(text);
} else {
highlightRes = this.hljs.highlight(text, { language: highlightJsLanguage });
highlightRes = this.hljs.highlight(text, { language: mimeType });
}
if (!highlightRes) {
return;
}
dbg("text\n" + text);
dbg("html\n" + highlightRes.value);

View File

@ -3,4 +3,5 @@ export * from "./lib/options_interface.js";
export * from "./lib/keyboard_actions_interface.js";
export * from "./lib/hidden_subtree.js";
export * from "./lib/rows.js";
export * from "./lib/test-utils.js"
export * from "./lib/test-utils.js";
export * from "./lib/mime_type.js";

View File

@ -0,0 +1,226 @@
/**
* A pseudo-MIME type which is used in the editor to automatically determine the language used in code blocks via heuristics.
*/
export const MIME_TYPE_AUTO = "text-x-trilium-auto";
export interface MimeTypeDefinition {
default?: boolean;
title: string;
mime: string;
/** The name of the language/mime type as defined by highlight.js (or one of the aliases), in order to be used for syntax highlighting such as inside code blocks. */
mdLanguageCode?: string;
/** If specified, will load the corresponding highlight file from the given path instead of `node_modules`. */
codeMirrorSource?: string;
}
export interface MimeType extends MimeTypeDefinition {
/**
* True if this mime type was enabled by the user in the "Available MIME types in the dropdown" option in the Code Notes settings.
*/
enabled: boolean;
}
/**
* Given a MIME type in the usual format (e.g. `text/csrc`), it returns a MIME type that can be passed down to the CKEditor
* code plugin.
*
* @param mimeType The MIME type to normalize, in the usual format (e.g. `text/c-src`).
* @returns the normalized MIME type (e.g. `text-c-src`).
*/
export function normalizeMimeTypeForCKEditor(mimeType: string) {
return mimeType.toLowerCase().replace(/[\W_]+/g, "-");
}
/**
* For highlight.js-supported languages, see https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md.
*/
export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([
{ title: "Plain text", mime: "text/plain", mdLanguageCode: "plaintext", default: true },
// Keep sorted alphabetically.
{ title: "APL", mime: "text/apl" },
{ title: "ASN.1", mime: "text/x-ttcn-asn" },
{ title: "ASP.NET", mime: "application/x-aspx" },
{ title: "Asterisk", mime: "text/x-asterisk" },
{ title: "Batch file (DOS)", mime: "application/x-bat", highlightJs: "dos", codeMirrorSource: "libraries/codemirror/batch.js" },
{ title: "Brainfuck", mime: "text/x-brainfuck", mdLanguageCode: "brainfuck" },
{ title: "C", mime: "text/x-csrc", mdLanguageCode: "c", default: true },
{ title: "C#", mime: "text/x-csharp", mdLanguageCode: "csharp", default: true },
{ title: "C++", mime: "text/x-c++src", mdLanguageCode: "cpp", default: true },
{ title: "Clojure", mime: "text/x-clojure", mdLanguageCode: "clojure" },
{ title: "ClojureScript", mime: "text/x-clojurescript" },
{ title: "Closure Stylesheets (GSS)", mime: "text/x-gss" },
{ title: "CMake", mime: "text/x-cmake", mdLanguageCode: "cmake" },
{ title: "Cobol", mime: "text/x-cobol" },
{ title: "CoffeeScript", mime: "text/coffeescript", mdLanguageCode: "coffeescript" },
{ title: "Common Lisp", mime: "text/x-common-lisp", mdLanguageCode: "lisp" },
{ title: "CQL", mime: "text/x-cassandra" },
{ title: "Crystal", mime: "text/x-crystal", mdLanguageCode: "crystal" },
{ title: "CSS", mime: "text/css", mdLanguageCode: "css", default: true },
{ title: "Cypher", mime: "application/x-cypher-query" },
{ title: "Cython", mime: "text/x-cython" },
{ title: "D", mime: "text/x-d", mdLanguageCode: "d" },
{ title: "Dart", mime: "application/dart", mdLanguageCode: "dart" },
{ title: "diff", mime: "text/x-diff", mdLanguageCode: "diff" },
{ title: "Django", mime: "text/x-django", mdLanguageCode: "django" },
{ title: "Dockerfile", mime: "text/x-dockerfile", mdLanguageCode: "dockerfile" },
{ title: "DTD", mime: "application/xml-dtd" },
{ title: "Dylan", mime: "text/x-dylan" },
{ title: "EBNF", mime: "text/x-ebnf", mdLanguageCode: "ebnf" },
{ title: "ECL", mime: "text/x-ecl" },
{ title: "edn", mime: "application/edn" },
{ title: "Eiffel", mime: "text/x-eiffel" },
{ title: "Elm", mime: "text/x-elm", mdLanguageCode: "elm" },
{ title: "Embedded Javascript", mime: "application/x-ejs" },
{ title: "Embedded Ruby", mime: "application/x-erb", mdLanguageCode: "erb" },
{ title: "Erlang", mime: "text/x-erlang", mdLanguageCode: "erlang" },
{ title: "Esper", mime: "text/x-esper" },
{ title: "F#", mime: "text/x-fsharp", mdLanguageCode: "fsharp" },
{ title: "Factor", mime: "text/x-factor" },
{ title: "FCL", mime: "text/x-fcl" },
{ title: "Forth", mime: "text/x-forth" },
{ title: "Fortran", mime: "text/x-fortran", mdLanguageCode: "fortran" },
{ title: "Gas", mime: "text/x-gas" },
{ title: "GDScript (Godot)", mime: "text/x-gdscript" },
{ title: "Gherkin", mime: "text/x-feature", mdLanguageCode: "gherkin" },
{ title: "GitHub Flavored Markdown", mime: "text/x-gfm", mdLanguageCode: "markdown" },
{ title: "Go", mime: "text/x-go", mdLanguageCode: "go", default: true },
{ title: "Groovy", mime: "text/x-groovy", mdLanguageCode: "groovy", default: true },
{ title: "HAML", mime: "text/x-haml", mdLanguageCode: "haml" },
{ title: "Haskell (Literate)", mime: "text/x-literate-haskell" },
{ title: "Haskell", mime: "text/x-haskell", mdLanguageCode: "haskell", default: true },
{ title: "Haxe", mime: "text/x-haxe", mdLanguageCode: "haxe" },
{ title: "HTML", mime: "text/html", mdLanguageCode: "xml", default: true },
{ title: "HTTP", mime: "message/http", mdLanguageCode: "http", default: true },
{ title: "HXML", mime: "text/x-hxml" },
{ title: "IDL", mime: "text/x-idl" },
{ title: "Java Server Pages", mime: "application/x-jsp", mdLanguageCode: "java" },
{ title: "Java", mime: "text/x-java", mdLanguageCode: "java", default: true },
{ title: "Jinja2", mime: "text/jinja2" },
{ title: "JS backend", mime: "application/javascript;env=backend", mdLanguageCode: "javascript", default: true },
{ title: "JS frontend", mime: "application/javascript;env=frontend", mdLanguageCode: "javascript", default: true },
{ title: "JSON-LD", mime: "application/ld+json", mdLanguageCode: "json" },
{ title: "JSON", mime: "application/json", mdLanguageCode: "json", default: true },
{ title: "JSX", mime: "text/jsx", mdLanguageCode: "javascript" },
{ title: "Julia", mime: "text/x-julia", mdLanguageCode: "julia" },
{ title: "Kotlin", mime: "text/x-kotlin", mdLanguageCode: "kotlin", default: true },
{ title: "LaTeX", mime: "text/x-latex", mdLanguageCode: "latex" },
{ title: "LESS", mime: "text/x-less", mdLanguageCode: "less" },
{ title: "LiveScript", mime: "text/x-livescript", mdLanguageCode: "livescript" },
{ title: "Lua", mime: "text/x-lua", mdLanguageCode: "lua" },
{ title: "MariaDB SQL", mime: "text/x-mariadb", mdLanguageCode: "sql" },
{ title: "Markdown", mime: "text/x-markdown", mdLanguageCode: "markdown", default: true },
{ title: "Mathematica", mime: "text/x-mathematica", mdLanguageCode: "mathematica" },
{ title: "mbox", mime: "application/mbox" },
{ title: "MIPS Assembler", mime: "text/x-asm-mips", mdLanguageCode: "mips" },
{ title: "mIRC", mime: "text/mirc" },
{ title: "Modelica", mime: "text/x-modelica" },
{ title: "MS SQL", mime: "text/x-mssql", mdLanguageCode: "sql" },
{ title: "mscgen", mime: "text/x-mscgen" },
{ title: "msgenny", mime: "text/x-msgenny" },
{ title: "MUMPS", mime: "text/x-mumps" },
{ title: "MySQL", mime: "text/x-mysql", mdLanguageCode: "sql" },
{ title: "Nix", mime: "text/x-nix", mdLanguageCode: "nix" },
{ title: "Nginx", mime: "text/x-nginx-conf", mdLanguageCode: "nginx" },
{ title: "NSIS", mime: "text/x-nsis", mdLanguageCode: "nsis" },
{ title: "NTriples", mime: "application/n-triples" },
{ title: "Objective-C", mime: "text/x-objectivec", mdLanguageCode: "objectivec" },
{ title: "OCaml", mime: "text/x-ocaml", mdLanguageCode: "ocaml" },
{ title: "Octave", mime: "text/x-octave" },
{ title: "Oz", mime: "text/x-oz" },
{ title: "Pascal", mime: "text/x-pascal", mdLanguageCode: "delphi" },
{ title: "PEG.js", mime: "null" },
{ title: "Perl", mime: "text/x-perl", default: true },
{ title: "PGP", mime: "application/pgp" },
{ title: "PHP", mime: "text/x-php", default: true },
{ title: "Pig", mime: "text/x-pig" },
{ title: "PLSQL", mime: "text/x-plsql", mdLanguageCode: "sql" },
{ title: "PostgreSQL", mime: "text/x-pgsql", mdLanguageCode: "pgsql" },
{ title: "PowerShell", mime: "application/x-powershell", mdLanguageCode: "powershell" },
{ title: "Properties files", mime: "text/x-properties", mdLanguageCode: "properties" },
{ title: "ProtoBuf", mime: "text/x-protobuf", mdLanguageCode: "protobuf" },
{ title: "Pug", mime: "text/x-pug" },
{ title: "Puppet", mime: "text/x-puppet", mdLanguageCode: "puppet" },
{ title: "Python", mime: "text/x-python", mdLanguageCode: "python", default: true },
{ title: "Q", mime: "text/x-q", mdLanguageCode: "q" },
{ title: "R", mime: "text/x-rsrc", mdLanguageCode: "r" },
{ title: "reStructuredText", mime: "text/x-rst" },
{ title: "RPM Changes", mime: "text/x-rpm-changes" },
{ title: "RPM Spec", mime: "text/x-rpm-spec" },
{ title: "Ruby", mime: "text/x-ruby", mdLanguageCode: "ruby", default: true },
{ title: "Rust", mime: "text/x-rustsrc", mdLanguageCode: "rust" },
{ title: "SAS", mime: "text/x-sas", mdLanguageCode: "sas" },
{ title: "Sass", mime: "text/x-sass" },
{ title: "Scala", mime: "text/x-scala" },
{ title: "Scheme", mime: "text/x-scheme" },
{ title: "SCSS", mime: "text/x-scss", mdLanguageCode: "scss" },
{ title: "Shell (bash)", mime: "text/x-sh", mdLanguageCode: "bash", default: true },
{ title: "Sieve", mime: "application/sieve" },
{ title: "Slim", mime: "text/x-slim" },
{ title: "Smalltalk", mime: "text/x-stsrc", mdLanguageCode: "smalltalk" },
{ title: "Smarty", mime: "text/x-smarty" },
{ title: "SML", mime: "text/x-sml", mdLanguageCode: "sml" },
{ title: "Solr", mime: "text/x-solr" },
{ title: "Soy", mime: "text/x-soy" },
{ title: "SPARQL", mime: "application/sparql-query" },
{ title: "Spreadsheet", mime: "text/x-spreadsheet" },
{ title: "SQL", mime: "text/x-sql", mdLanguageCode: "sql", default: true },
{ title: "SQLite (Trilium)", mime: "text/x-sqlite;schema=trilium", mdLanguageCode: "sql", default: true },
{ title: "SQLite", mime: "text/x-sqlite", mdLanguageCode: "sql" },
{ title: "Squirrel", mime: "text/x-squirrel" },
{ title: "sTeX", mime: "text/x-stex" },
{ title: "Stylus", mime: "text/x-styl", mdLanguageCode: "stylus" },
{ title: "Swift", mime: "text/x-swift", default: true },
{ title: "SystemVerilog", mime: "text/x-systemverilog" },
{ title: "Tcl", mime: "text/x-tcl", mdLanguageCode: "tcl" },
{ title: "Terraform (HCL)", mime: "text/x-hcl", highlightJs: "terraform", highlightJsSource: "libraries", codeMirrorSource: "libraries/codemirror/hcl.js" },
{ title: "Textile", mime: "text/x-textile" },
{ title: "TiddlyWiki ", mime: "text/x-tiddlywiki" },
{ title: "Tiki wiki", mime: "text/tiki" },
{ title: "TOML", mime: "text/x-toml", mdLanguageCode: "ini" },
{ title: "Tornado", mime: "text/x-tornado" },
{ title: "troff", mime: "text/troff" },
{ title: "TTCN_CFG", mime: "text/x-ttcn-cfg" },
{ title: "TTCN", mime: "text/x-ttcn" },
{ title: "Turtle", mime: "text/turtle" },
{ title: "Twig", mime: "text/x-twig", mdLanguageCode: "twig" },
{ title: "TypeScript-JSX", mime: "text/typescript-jsx" },
{ title: "TypeScript", mime: "application/typescript", mdLanguageCode: "typescript" },
{ title: "VB.NET", mime: "text/x-vb", mdLanguageCode: "vbnet" },
{ title: "VBScript", mime: "text/vbscript", mdLanguageCode: "vbscript" },
{ title: "Velocity", mime: "text/velocity" },
{ title: "Verilog", mime: "text/x-verilog", mdLanguageCode: "verilog" },
{ title: "VHDL", mime: "text/x-vhdl", mdLanguageCode: "vhdl" },
{ title: "Vue.js Component", mime: "text/x-vue" },
{ title: "Web IDL", mime: "text/x-webidl" },
{ title: "XML", mime: "text/xml", mdLanguageCode: "xml", default: true },
{ title: "XQuery", mime: "application/xquery", mdLanguageCode: "xquery" },
{ title: "xu", mime: "text/x-xu" },
{ title: "Yacas", mime: "text/x-yacas" },
{ title: "YAML", mime: "text/x-yaml", mdLanguageCode: "yaml", default: true },
{ title: "Z80", mime: "text/x-z80" }
]);
let byMarkdownNameMappings: Record<string, MimeTypeDefinition> | null = null;
/**
* Given a Markdown language tag (e.g. `css`), it returns a corresponding {@link MimeTypeDefinition} if found.
*
* If there are multiple {@link MimeTypeDefinition}s for the language tag, then only the first one is retrieved. For example for `javascript`, the "JS frontend" mime type is returned.
*
* @param mdLanguageCode a language tag.
* @returns the corresponding {@link MimeTypeDefinition} if found, or `undefined` otherwise.
*/
export function getMimeTypeFromMarkdownName(mdLanguageCode: string) {
if (!byMarkdownNameMappings) {
byMarkdownNameMappings = {};
for (const mimeType of MIME_TYPES_DICT) {
if (mimeType.mdLanguageCode && !byMarkdownNameMappings[mimeType.mdLanguageCode]) {
byMarkdownNameMappings[mimeType.mdLanguageCode] = mimeType;
}
}
}
return byMarkdownNameMappings[mdLanguageCode];
}

View File

@ -2,22 +2,18 @@
import { defineConfig } from 'vite';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../node_modules/.vite/packages/commons',
plugins: [],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
test: {
'watch': false,
'globals': true,
'environment': "node",
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
'reporters': ["default"],
'coverage': {
'reportsDirectory': './test-output/vitest/coverage',
'provider': 'v8' as const,
}
},
root: __dirname,
cacheDir: '../../node_modules/.vite/packages/commons',
plugins: [],
test: {
'watch': false,
'globals': true,
'environment': "node",
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
'reporters': ["default"],
'coverage': {
'reportsDirectory': './test-output/vitest/coverage',
'provider': 'v8' as const,
}
},
}));

View File

@ -0,0 +1,11 @@
# highlightjs
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build highlightjs` to build the library.
## Running unit tests
Run `nx test highlightjs` to execute the unit tests via [Vitest](https://vitest.dev/).

View File

@ -0,0 +1,24 @@
import baseConfig from "../../eslint.config.mjs";
export default [
...baseConfig,
{
"files": [
"**/*.json"
],
"rules": {
"@nx/dependency-checks": [
"error",
{
"ignoredFiles": [
"{projectRoot}/eslint.config.{js,cjs,mjs}",
"{projectRoot}/vite.config.{js,ts,mjs,mts}"
]
}
]
},
"languageOptions": {
"parser": (await import('jsonc-eslint-parser'))
}
}
];

View File

@ -0,0 +1,28 @@
{
"name": "@triliumnext/highlightjs",
"version": "0.0.1",
"private": true,
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"nx": {
"name": "highlightjs"
},
"dependencies": {
"@exercism/highlightjs-gdscript": "0.0.1",
"@triliumnext/commons": "workspace:*",
"highlight.js": "11.11.1",
"highlightjs-cobol": "0.3.3",
"highlightjs-cypher": "1.2.0"
}
}

View File

@ -0,0 +1,67 @@
import hljs from "../node_modules/highlight.js/es/core.js";
import { normalizeMimeTypeForCKEditor, type MimeType } from "@triliumnext/commons";
import syntaxDefinitions from "./syntax_highlighting.js";
import { type Theme } from "./themes.js";
import { type HighlightOptions } from "highlight.js";
export { default as Themes, type Theme } from "./themes.js";
const registeredMimeTypes = new Set<string>();
const unsupportedMimeTypes = new Set<string>();
let highlightingThemeEl: HTMLStyleElement | null = null;
export async function ensureMimeTypes(mimeTypes: MimeType[]) {
for (const mimeType of mimeTypes) {
if (!mimeType.enabled) {
continue;
}
const mime = normalizeMimeTypeForCKEditor(mimeType.mime);
if (registeredMimeTypes.has(mime)) {
continue;
}
registeredMimeTypes.add(mime);
const loader = syntaxDefinitions[mime];
if (!loader) {
unsupportedMimeTypes.add(mime);
continue;
}
const language = (await loader()).default;
hljs.registerLanguage(mime, language);
}
}
export function highlight(code: string, options: HighlightOptions) {
if (unsupportedMimeTypes.has(options.language)) {
return null;
}
if (!registeredMimeTypes.has(options.language)) {
console.warn(`Unable to find highlighting for ${options.language}.`);
return null;
}
return hljs.highlight(code, options);
}
export async function loadTheme(theme: "none" | Theme) {
if (theme === "none") {
if (highlightingThemeEl) {
highlightingThemeEl.remove();
highlightingThemeEl = null;
}
return;
}
if (!highlightingThemeEl) {
highlightingThemeEl = document.createElement("style");
document.querySelector("head")?.append(highlightingThemeEl);
}
const themeCss = (await theme.load()).default as string;
highlightingThemeEl.textContent = themeCss;
}
export const { highlightAuto } = hljs;

View File

@ -0,0 +1,76 @@
import type { HLJSApi, Language, Mode } from "highlight.js";
/*
* highlight.js Dylan syntax highlighting definition
*
* Source: https://github.com/highlightjs/highlightjs-dylan/blob/master/src/dylan.js
*
* @see https://github.com/highlightjs/highlight.js
* @see https://opendylan.org/
*
* :TODO:
*
* @package: highlightjs-dylan
* @author: Peter Hull <peterhull90@gmail.com>
* @since: 2019-04-08
*
* Description: Dylan language definition
* Category: functional
*/
export default function(hljs: HLJSApi): Language {
const DYLAN_CORE_WORDS = ["define", "end", "handler", "let", "local", "macro", "otherwise"];
const DYLAN_BEGIN_WORDS = ["begin", "block", "case", "for", "if", "method",
"select", "unless", "until", "while"
];
const DYLAN_FUNCTION_WORDS: string[] = [];
const DYLAN_DEFINE_BODY_WORDS = ["class", "library", "method", "module"];
const DYLAN_DEFINE_LIST_WORDS = ["constant", "variable", "domain"];
const DYLAN_RESERVED_WORDS = ([] as string[]).concat(DYLAN_CORE_WORDS,
DYLAN_BEGIN_WORDS,
DYLAN_FUNCTION_WORDS,
DYLAN_DEFINE_BODY_WORDS.map(function(word) {
return word + '|2';
}),
DYLAN_DEFINE_LIST_WORDS
);
const DYLAN_HASH_WORDS = ["#t", "#f", "#next", "#rest", "#key", "#all-keys", "#include"];
const DYLAN_WORD = '[a-z\-+\*/^=#!%$_><@\?~][a-z0-9\-+\*/^=#!%$_><@\?~]*';
const KEYWORDS = {
$pattern: DYLAN_WORD,
literal: DYLAN_HASH_WORDS.join(" "),
keyword: DYLAN_RESERVED_WORDS.join(" ")
};
const DYLAN_CODE = {
case_insensitive: true,
className: 'dylan',
keywords: KEYWORDS,
contains: [{
className: 'class',
begin: '<' + DYLAN_WORD + '>',
relevance: 0
},
{
className: 'symbol',
begin: '#' + DYLAN_WORD
},
{
className: 'symbol',
begin: DYLAN_WORD + ':',
relevance: 0
},
{
className: 'string',
begin: '\'\\\\?.',
end: '\'',
illegal: '.'
},
hljs.C_NUMBER_MODE,
hljs.QUOTE_STRING_MODE,
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE
]
};
return DYLAN_CODE;
};

View File

@ -0,0 +1,253 @@
import type { HLJSApi, Language, Mode } from "highlight.js";
/**
* highlight.js mIRC Scripting Language syntax highlighting definition
*
* Source: https://github.com/highlightjs/highlightjs-mirc/blob/master/mirc.js
*
* @see https://github.com/isagalaev/highlight.js
*
* @package: highlightjs-mirc
* @author: Kedyn Macedonio <mkedyn@gmail.com>
* @author: Sven Roelse <acvxqs@icloud.com>
*/
export default function hljsDefineMIRC(hljs: HLJSApi): Language {
const COMMENT_DOC = {
className: 'comment',
begin: /^\x20*\/\*\*\s+/,
end: /^\x20*\*\//,
contains: [
{
className: 'doctag',
begin: /@\w+/
}
]
};
const COMMENT_BLOCK = {
className: 'comment',
begin: /^\x20*\/\*/,
end: /^\x20*\*\//
};
const COMMENT_LINE = {
className: 'comment',
begin: /(^\x20*|}\x20+|\x20+\|\x20+);/,
end: /(\x20+\|\x20+.+|$)/,
excludeEnd: true
};
const VARIABLES = {
className: 'variable',
begin: /%[^\s,\)]+/
};
const IDENTIFIERS = [
{
className: 'literal',
begin: /\$\$?(true|false|null)\b/,
},
{
className: 'built_in',
begin: /\$\$?(\!|0|(?:[1-9](?:\d+)?-?(?:\d+)?|\?\d+)|\+|\?|(?:abook|abs|acos|active(cid|wid)?|adate|address|addtok(cs)?|agent(name|stat|ver)?|alias|and|anick|ansi2mirc|aop|appactive|appstate|asc(time)?|asin|atan2?|auto|avoice|away(msg|time)?|banmask|banlist|base|beta|bfind|bindip|bitoff|biton|bits|bnick|bvar|bytes|calc|caller|cancel|cb|cd|ceil|chan(modes|nel|types)?|chat|chr|cid|clevel|click|cmdbox|cmdline|cnick|color|com(call|chan|char|err|pact|press|val)?|cosh?|count(cs)?|crc?|creq|crlf|ctimer?|ctrlenter|date|day(light)?|dbuh|dbuw|dcc(ignore|port)|dde(name)?|debug|decode|decompress|deltok|devent|dialog|did(reg|tok|wm)?|dir=|disk|dlevel|dll(call)?|dname|dns|dqwindow|duration|ebeeps|editbox|email(addr)?|encode|envvar|error|eval(next)?|event(id|params)?|exist(s|ing)|feof|ferr|fgetc|file(=|name)?|filtered|finddirn?|findfilen?|findtok(cs)?|fline|floor|font|fopen|fread|fromeditbox|fserve|full(address|date|name|screen)|get(dir|dot|tok)?|gmt|group|halted|hash|height|hfile=?|hfind|hget|highlight|hmac|hmatch|hnick|host|hotline(pos)?|hotlink|hotp|hregex|hypot|iaddress|ial(chan)?|ibl|idle|iel|ifmatch2?|ignore|iif|iil|inellipse|ini(topic)?|in(midi|mode|mp3|paste|poly|put|(round)rect|song|stok|t(ersect)?|wave|who)|ip(type)?|iql|is(alias|bit|dde|dir|file|id|lower|tok(cs)?|upper|utf)|key(char|rpt|val)|knick|lactive(cid|wid)?|left(win|wincid|winwid)?|len|level|lf|lines?|link|lock(ed)?|lof|log(10|dir|stamp(fmt)?)?|long(fn|ip)|lower|ltimer|maddress|mask|match(key|tok(cs)?)|maxlen(s|m|l)|md5|menu(bar|context|type)?|me|mid(idir)?|mircdir|mircexe|mircini|mk(log)?fn|mknickfn|mnick|mode(first|last|spl)?|mouse|mp3|msfile|msgstamp|msgtags|naddress|network|newnick|nhnick|nick(mode)?|no(file|path|pnick|qt|tags|tify|t)?|numeric|numtok|nvnick|ok|online(server|total)?|onpoly|opnick|ord?|os|parms|parse(line|type|utf)|passivedcc|pic?|play|pnick|portable|portfree|pos(cs)?|prefix|prop|protect|puttok|qt|query|r(address|ands?)?|raw(bytes|msg)|read(ini|n)?|reg(br|errstr|ex|ml(ex)?|sub(ex)?)|rem(ote|move(cs)?|tok(cs)?)|replace(cs|xcs|x)?|reptok(cs)?|result|rgb|right|rnick|round|samepath|scid|scon|script(dir([^\s\(),><:"|?*]+)?|line)?|sdir|send|server(ip|target)?|sfile|sha1|sha(256|384|512)|shortfn|show|signal|sinh?|site|sline|snick(s)?|snotify|sock(br|err|name)?|sorttok(cs)?|sound|speak|sqrt|sreq|ssl(certsha1|certsha256)?|ssl((lib)?dll)?|ssl(ready|version)|starting|status|str(ipped|ip)?|style|submenu|switchbar|sysdir|tanh?|target|tempfn|ticks|time(out|stamp(fmt)?r|zone)?|tips?|titlebar|token|toolbar|topic|totp|treebar|trust|ulevel|ulist|unsafe|upper|uptime|url|usermode|utf(de|en)code|v1|v2|var|vc|vcmd(stat|ver)?|version|vnick|vol|wavdir|wid(th)?|wild(site|tok(cs)?)|window|wrap|xor|yes|zip)\b)/
}
];
const COMMANDS = {
className: 'built_in',
begin: /\b(\/)?([!.]{1,2})?(abook|ajinvite|alias|aline|ame|amsg|anick|aop|auser|autojoin|avoice|away|background|ban|bcopy|beep|bindip|bread|breplace|bset|btrunc|bunset|bwrite|channel|clear(all)?|cline|clipboard|close|cnick|color|colour|com(close|list|open|reg)|copy|creq|ctcp(reply|s)?|dcc(server)?|dde(server)?|debug|dec|describe|dialog|did(tok)?|disable|disconnect|dlevel|dline|dll|dns|dqwindow|draw(copy|dot|fill|line|pic|rect|replace|rot|save|scroll|size|text)|ebeeps|echo|editbox|emailaddr|enable|events|exit|fclose|filter|findtext|finger|firewall|flash|flist|flood|flush|flushini|fnord|font|fopen|fseek|fsend|fserve|fullname|fupdate|fwrite|ghide|gload|gmove|gopts|gplay|gpoint|gqreq|groups|gshow|gsize|gstop|gtalk|gunload|guser|hadd|hdec|hdel|help|hfree|hinc|hload|hmake|hop|hotlink|hsave|ial(clear|mark)?|identd|ignore|iline|inc|iuser|join|leave|linesep|links|list|load(buf)?|localinfo|log|logview|mdi|me|menubar|mkdir|mnick|mode|msg|noop|notice|notify|omsg|onotice|parseline|part|partall|pdcc|perform|play|playctrl|pop|privmsg|protect|proxy|pvoice|qme|qmsg|query|queryrn|quit|raw|registration|reload|remini|remote|remove|rename|renwin|reseterror|resetidle|rlevel|rline|rmdir|run|ruser|save(buf|ini)?|say|scid|scon|server|set(layer)?|showmirc|signal|sline|sock(accept|close|list|listen|mark|open|pause|read|rename|udp|write)|sound|speak|splay|sreq|strip|switchbar|timer([^\x20]+)?|timestamp|tips?|titlebar|tnick|tokenize|toolbar|tray|treebar|ulist|unload|unset(all)?|updatenl|url|uwho|var|vc(add|md|rem)|vmsg|vnotice|vol|wall(chops|voices)|window|winhelp|write(ini)?|xyzzy)\b/,
}
const ALIAS_DECLARATION = {
className: 'function',
begin: /^alias(\x20+-l)?\x20+[^\s]+/,
returnBegin: true,
contains: [
{
className: 'type',
begin: /^alias/
},
{
className: 'symbol',
begin: /\x20+-l/
},
{
className: 'title',
begin: /\x20+[^\s]+/,
endsParent: true
}
]
};
const DIALOG = {
className: 'code',
begin: /^dialog(\x20+-l)?\x20+[^\x20]+\x20+{$/,
end: /^}$/,
returnBegin: true,
contains: [
{
className: 'built_in',
begin: /^dialog(\x20+-l)?\x20+[^\x20]+\x20+/,
end: /{$/,
excludeEnd: true,
returnBegin: true,
contains: [
{
className: 'symbol',
begin: /\x20+-l/,
},
{
className: 'title',
begin: /\x20+[^\x20]+\x20+/,
end: /{$/,
excludeEnd: true,
endsParent: true,
}
]
},
{
className: 'keyword',
begin: /^\x20+(title|icon|size|option|text|edit|button|check|radio|box|scroll|list|combo|link|tab|menu|item)\x20+/
},
hljs.QUOTE_STRING_MODE,
hljs.NUMBER_MODE,
COMMENT_BLOCK,
COMMENT_LINE,
VARIABLES,
IDENTIFIERS[0],
IDENTIFIERS[1]
]
};
const MENU = {
className: 'code',
begin: /^menu\x20+[^\x20]+\x20*/,
end: /{/,
returnBegin: true,
excludeEnd: true,
contains: [
{
className: 'built_in',
begin: /^menu\b/,
end: /\x20+/,
excludeEnd: true
},
{
className: 'title',
begin: /[^\s]+\x20*/,
endsParent: true
}
]
};
const GROUPS = {
className: 'symbol',
begin: /^#[^\s]+\x20+(on|off|end)$/
}
const EVENTS1 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:(action|notice|text):[^:]+:(\?|#[^:]*|\*):/
};
const EVENTS2 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:(active|input|tabcomp):(\*|#[^:]*|\?|=|!|@[^:]*):/
};
const EVENTS3 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:(agent|appactive|(dis)?connect(fail)?|dns|exit|(un)?load|(midi|mp3|play|wave)end|nick|nosound|u?notify|ping|pong|quit|start|usermode):/
};
const EVENTS4 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:((un)?ban|(de)?help|(de|server)?op|(de)?owner|(de)?voice|invite|join|kick|(server)?mode|part|rawmode|topic):(?:\*|#[^:]*):/
};
const EVENTS5 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:(chat|ctcpreply|error|file(rcvd|sent)|(get|send)fail|logon|serv|signal|snotice|sock(close|listen|open|read|write)|udpread|vcmd|wallops):[^:]+:/
};
const EVENTS6 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:close:(\*|\?|=|!|@[^:]*):/
};
const EVENTS7 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:dccserver:(chat|send|fserve):/
};
const EVENTS8 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:dialog:[^:]+:(init|close|edit|sclick|dclick|menu|scroll|mouse|rclick|drop|\*):[\d\-,\*]+:/
};
const EVENTS9 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:hotlink:[^:]+:(?:\*|#[^:]*|\?|=|!|@[^:]*):/
};
const EVENTS10 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:key(down|up):(\*|@[^:]*):(\*|\d+(,\d+)*):/
};
const EVENTS11 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:open:(\*|\?|=|!|@[^:]*):[^:]+:/
};
const EVENTS12 = {
className: 'built_in',
begin: /^on\x20+(me:)?[^:\x20]+:parseline:(\*|in|out):[^:]+:/
};
const EVENTS13 = {
className: 'built_in',
begin: /^raw\x20+(me:)?[^:\x20]+:[^:]+:/
};
const EVENTS14 = {
className: 'built_in',
begin: /^ctcp\x20+(me:)?[^:\x20]+:[^:]+:(\*|#.*|\?):/
};
return {
aliases: ['mrc'],
keywords: 'if elseif else while break continue halt haltdef goto return returnex',
case_insensitive: true,
contains: [
COMMENT_DOC,
COMMENT_BLOCK,
COMMENT_LINE,
hljs.NUMBER_MODE,
ALIAS_DECLARATION,
DIALOG,
MENU,
GROUPS,
EVENTS1,
EVENTS2,
EVENTS3,
EVENTS4,
EVENTS5,
EVENTS6,
EVENTS7,
EVENTS8,
EVENTS9,
EVENTS10,
EVENTS11,
EVENTS12,
EVENTS13,
EVENTS14,
VARIABLES,
IDENTIFIERS[0],
IDENTIFIERS[1],
COMMANDS
]
};
}

View File

@ -0,0 +1,71 @@
import type { HLJSApi, Language, Mode } from "highlight.js";
/**
* highlight.js RPM spec file syntax highlighting definition
*
* Source: https://github.com/highlightjs/highlightjs-rpm-specfile
*
* @see https://github.com/highlightjs/highlight.js
*
* @package highlightjs-rpm-specfile
* @author Ryan Lerch <rlerch@redhat.com>, Neal Gompa <ngompa13@gmail.com>
* @since 2019-07-08
* @license magnet:?xt=urn:btih:c80d50af7d3db9be66a4d0a86db0286e4fd33292&dn=bsd-3-clause.txt BSD-3-Clause
*
* Language: rpm-specfile
* Description: RPM Specfile
* Author: Ryan Lerch <rlerch@redhat.com>
* Contributors: Neal Gompa <ngompa13@gmail.com>
* Category: config
* Requires: bash.js
* Website: https://rpm.org/
**/
export default function hljsDefineRpmSpecfile(hljs: HLJSApi): Language {
return {
aliases: ['rpm', 'spec', 'rpm-spec', 'specfile'],
contains: [
hljs.COMMENT('%dnl', '$'),
hljs.HASH_COMMENT_MODE,
hljs.APOS_STRING_MODE,
hljs.QUOTE_STRING_MODE,
{
className: "type",
begin: /^(Name|BuildRequires|Version|Release|Epoch|Summary|Group|License|Packager|Vendor|Icon|URL|Distribution|Prefix|Patch[0-9]*|Source[0-9]*|Requires\(?[a-z]*\)?|[a-z]+Req|Obsoletes|Recommends|Suggests|Supplements|Enhances|Provides|Conflicts|RemovePathPostfixes|Build[a-z]+|[a-z]+Arch|Auto[a-z]+)(:)/,
},
{
className: "keyword",
begin: /(%)(?:package|prep|generate_buildrequires|sourcelist|patchlist|build|description|install|verifyscript|clean|changelog|check|pre[a-z]*|post[a-z]*|trigger[a-z]*|files)/,
},
{
className: "link",
begin: /(%)(if|ifarch|ifnarch|ifos|ifnos|elif|elifarch|elifos|else|endif)/,
},
{
className: "link",
begin: /%\{_/,
end: /}/,
},
{
className: "symbol",
begin: /%\{\?/,
end: /}/,
},
{
className: "link font-weight-bold",
begin: /%\{/,
end: /}/,
},
{
className: "link font-weight-bold",
begin: /%/,
end: /[ \t\n]/
},
{
className: "symbol font-weight-bold",
begin: /^\* (Mon|Tue|Wed|Thu|Fri|Sat|Sun)/,
end: /$/,
},
]
};
}

View File

@ -0,0 +1,96 @@
/*
* highlight.js terraform syntax highlighting definition
*
* @see https://github.com/highlightjs/highlight.js
*
* :TODO:
*
* @package: highlightjs-terraform
* @author: Nikos Tsirmirakis <nikos.tsirmirakis@winopsdba.com>
* @since: 2019-03-20
*
* Description: Terraform (HCL) language definition
* Category: scripting
*/
import type { HLJSApi, Language, Mode } from "highlight.js";
export default function hljsDefineTerraform(hljs: HLJSApi): Language {
const NUMBERS: Mode = {
className: 'number',
begin: '\\b\\d+(\\.\\d+)?',
relevance: 0
};
const STRINGS: Mode = {
className: 'string',
begin: '"',
end: '"',
contains: [{
className: 'variable',
begin: '\\${',
end: '\\}',
relevance: 9,
contains: [{
className: 'string',
begin: '"',
end: '"'
}, {
className: 'meta',
begin: '[A-Za-z_0-9]*' + '\\(',
end: '\\)',
contains: [
NUMBERS, {
className: 'string',
begin: '"',
end: '"',
contains: [{
className: 'variable',
begin: '\\${',
end: '\\}',
contains: [{
className: 'string',
begin: '"',
end: '"',
contains: [{
className: 'variable',
begin: '\\${',
end: '\\}'
}]
}, {
className: 'meta',
begin: '[A-Za-z_0-9]*' + '\\(',
end: '\\)'
}]
}]
},
'self' as const]
}]
}]
};
return {
aliases: ['tf', 'hcl'],
keywords: {
keyword: [
"resource",
"variable",
"provider",
"output",
"locals",
"module",
"data",
"terraform|10"
],
literal: [
"false",
"true",
"null"
]
},
contains: [
hljs.COMMENT('\\#', '$'),
NUMBERS,
STRINGS
]
}
}

View File

@ -0,0 +1,343 @@
import type { HLJSApi, Language, Mode } from "highlight.js";
/* vim:set ts=2 sw=2 et: */
/*
Source: https://gitea.osmocom.org/ttcn3/highlightjs-ttcn3/src/branch/master/ttcn3.js
Language: TTCN-3
Description: TTCN-3 is a domain specific programming language used particularly (but not only) in the telecom domain.
Website: http://www.ttcn-3.org/
Category: common, protocols
Spec: ETSI ES 201 873-1 V4.15.1
Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
*/
export default function(hljs: HLJSApi): Language {
const RESERVED_WORDS = [ /* table A.3 */
'action',
'activate',
'address',
'alive',
'all',
'alt',
'altstep',
'and',
'and4b',
'any',
'anytype',
'bitstring',
'boolean',
'break',
'case',
'call',
'catch',
'char',
'charstring',
'check',
'clear',
'complement',
'component',
'connect',
'const',
'continue',
'control',
'create',
'deactivate',
'decmatch',
'default',
'disconnect',
'display',
'do',
'done',
'else',
'encode',
'enumerated',
'error',
'except',
'exception',
'execute',
'extends',
'extension',
'external',
'fail',
'false',
'float',
'for',
'friend',
'from',
'function',
'getverdict',
'getcall',
'getreply',
'goto',
'group',
'halt',
'hexstring',
'if',
'ifpresent',
'import',
'in',
'inconc',
'infinity',
'inout',
'integer',
'interleave',
'isbound',
'ischosen',
'ispresent',
'isvalue',
'kill',
'killed',
'label',
'language',
'length',
'log',
'map',
'match',
'message',
'mixed',
'mod',
'modifies',
'module',
'modulepar',
'mtc',
'noblock',
'none',
'not',
'not_a_number',
'not4b',
'nowait',
'null',
'octetstring',
'of',
'omit',
'on',
'optional',
'or',
'or4b',
'out',
'override',
'param',
'pass',
'pattern',
'permutation',
'port',
'present',
'private',
'procedure',
'public',
'raise',
'read',
'receive',
'record',
'recursive',
'rem',
'repeat',
'reply',
'return',
'running',
'runs',
'select',
'self',
'send',
'sender',
'set',
'setencode',
'setverdict',
'signature',
'start',
'stop',
'subset',
'superset',
'system',
'template',
'testcase',
'timeout',
'timer',
'to',
'trigger',
'true',
'type',
'union',
'universal',
'unmap',
'value',
'valueof',
'var',
'variant',
'verdicttype',
'while',
'with',
'xor',
'xor4b',
];
const BUILT_INS = [
'action',
'activate',
'any2unistr',
'bit2hex',
'bit2int',
'bit2oct',
'bit2str',
'call',
'catch',
'char2int',
'char2oct',
'check',
'clear',
'complement',
'connect',
'create',
'deactivate',
'decmatch',
'decvalue',
'decvalue_o',
'decvalue_unichar',
'disconnect',
'encode',
'encvalue',
'encvalue_o',
'encvalue_unichar',
'enum2int',
'execute',
'float2int',
'get_stringencoding',
'getcall',
'getreply',
'getverdict',
'halt',
'hex2bit',
'hex2int',
'hex2oct',
'hex2str',
'hostid',
'int2bit',
'int2char',
'int2enum',
'int2float',
'int2hex',
'int2oct',
'int2str',
'int2unichar',
'isbound',
'ischosen',
'ispresent',
'istemplatekind',
'isvalue',
'kill',
'killed',
'length',
'lengthof',
'log',
'map',
'match',
'oct2bit',
'oct2char',
'oct2hex',
'oct2int',
'oct2str',
'oct2unichar',
'raise',
'receive',
'record',
'regexp',
'remove_bom',
'replace',
'reply',
'rnd',
'running',
'send',
'setencode',
'setverdict',
'sizeof',
'start',
'stop',
'str2float',
'str2hex',
'str2int',
'str2oct',
'substr',
'testcasename',
'timeout',
'trigger',
'unichar2int',
'unichar2oct',
'unmap',
'value',
'valueof',
];
const LITERALS = [
'error',
'fail',
'false',
'inconc',
'infinity',
'none',
'null',
'omit',
'pass',
'true',
];
const TYPES = [
'address',
'anytype',
'bitstring',
'boolean',
'charstring',
'default',
'float',
'hexstring',
'integer',
'octetstring',
'universal',
'universal charstring',
'verdicttype',
];
const KEYWORDS = {
keyword: RESERVED_WORDS,
built_in: BUILT_INS,
literal: LITERALS,
type: TYPES,
};
const STRING = {
className: 'string',
variants: [
{ /* octstring */
match: /'([a-fA-F0-9]{2}|\?|\*)*'O/,
relevance: 10,
},
{ /* hexstring */
match: /'[a-fA-F0-9\?\*]*'H/,
relevance: 10,
},
{ /* bitstring */
match: /'[01\?\*]*'B/,
relevance: 10,
},
hljs.APOS_STRING_MODE,
hljs.QUOTE_STRING_MODE,
],
};
return {
name: 'TTCN-3',
aliases: [
'ttcn',
'ttcn3',
'ttcnpp',
],
keywords: KEYWORDS,
illegal: '(\\*=|\\+=|-=)',
contains: [
hljs.C_BLOCK_COMMENT_MODE,
hljs.C_LINE_COMMENT_MODE,
STRING,
]
};
}

View File

@ -0,0 +1,20 @@
import { describe, it } from "vitest";
import definitions from "./syntax_highlighting.js";
import hljs from "highlight.js";
describe("Syntax highlighting definitions", () => {
it("every entry is readable", async () => {
for (const [ mime, loader ] of Object.entries(definitions)) {
if (loader === null) {
continue;
}
const language = (await loader()).default;
hljs.registerLanguage(mime, language);
hljs.highlight("Hello world", {
language: mime
});
}
});
});

View File

@ -0,0 +1,178 @@
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
import type { LanguageFn } from "highlight.js";
type MimeRecord = Record<string, (() => Promise<{ default: LanguageFn}>) | null>;
const byMimeType: MimeRecord = {
"text/plain": () => import("highlight.js/lib/languages/plaintext"),
"application/dart": () => import("highlight.js/lib/languages/dart"),
"application/edn": () => import("highlight.js/lib/languages/clojure"),
"application/javascript;env=backend": () => import("highlight.js/lib/languages/javascript"),
"application/javascript;env=frontend": () => import("highlight.js/lib/languages/javascript"),
"application/json": () => import("highlight.js/lib/languages/json"),
"application/ld+json": () => import("highlight.js/lib/languages/json"),
"application/mbox": null,
"application/n-triples": null,
"application/pgp": null,
"application/sieve": null,
"application/sparql-query": null,
"application/typescript": () => import("highlight.js/lib/languages/typescript"),
"application/x-aspx": null,
"application/x-bat": () => import("highlight.js/lib/languages/dos"),
"application/x-cypher-query": () => import("highlightjs-cypher"),
"application/x-ejs": null,
"application/x-erb": () => import("highlight.js/lib/languages/erb"),
"application/x-jsp": () => import("highlight.js/lib/languages/java"),
"application/x-powershell": () => import("highlight.js/lib/languages/powershell"),
"application/xml-dtd": () => import("highlight.js/lib/languages/xml"),
"application/xquery": () => import("highlight.js/lib/languages/xquery"),
"message/http": () => import("highlight.js/lib/languages/http"),
"text/apl": null,
"text/coffeescript": () => import("highlight.js/lib/languages/coffeescript"),
"text/css": () => import("highlight.js/lib/languages/css"),
"text/html": () => import("highlight.js/lib/languages/xml"),
"text/jinja2": () => import("highlight.js/lib/languages/django"),
"text/jsx": () => import("highlight.js/lib/languages/javascript"),
"text/mirc": () => import("./languages/mirc.js"),
"text/tiki": null,
"text/troff": null,
"text/turtle": null,
"text/typescript-jsx": () => import("highlight.js/lib/languages/typescript"),
"text/vbscript": () => import("highlight.js/lib/languages/vbscript"),
"text/velocity": null,
"text/vnd.mermaid": null,
"text/mermaid": null,
"text/x-asm-mips": () => import("highlight.js/lib/languages/mipsasm"),
"text/x-asterisk": null,
"text/x-brainfuck": () => import("highlight.js/lib/languages/brainfuck"),
"text/x-c++src": () => import("highlight.js/lib/languages/cpp"),
"text/x-cassandra": null,
"text/x-clojure": () => import("highlight.js/lib/languages/clojure"),
"text/x-clojurescript": () => import("highlight.js/lib/languages/clojure"),
"text/x-cmake": () => import("highlight.js/lib/languages/cmake"),
"text/x-cobol": () => import("highlightjs-cobol"),
"text/x-common-lisp": () => import("highlight.js/lib/languages/lisp"),
"text/x-crystal": () => import("highlight.js/lib/languages/crystal"),
"text/x-csharp": () => import("highlight.js/lib/languages/csharp"),
"text/x-csrc": () => import("highlight.js/lib/languages/c"),
"text/x-cython": null,
"text/x-d": () => import("highlight.js/lib/languages/d"),
"text/x-diff": () => import("highlight.js/lib/languages/diff"),
"text/x-django": () => import("highlight.js/lib/languages/django"),
"text/x-dockerfile": () => import("highlight.js/lib/languages/dockerfile"),
"text/x-dylan": () => import("./languages/dylan.js"),
"text/x-ebnf": () => import("highlight.js/lib/languages/ebnf"),
"text/x-ecl": null,
"text/x-eiffel": null,
"text/x-elm": () => import("highlight.js/lib/languages/elm"),
"text/x-erlang": () => import("highlight.js/lib/languages/erlang"),
"text/x-esper": null,
"text/x-factor": null,
"text/x-fcl": null,
"text/x-feature": () => import("highlight.js/lib/languages/gherkin"),
"text/x-forth": null,
"text/x-fortran": () => import("highlight.js/lib/languages/fortran"),
"text/x-fsharp": () => import("highlight.js/lib/languages/fsharp"),
"text/x-gas": null,
"text/x-gdscript": () => import("@exercism/highlightjs-gdscript"),
"text/x-gfm": () => import("highlight.js/lib/languages/markdown"),
"text/x-go": () => import("highlight.js/lib/languages/go"),
"text/x-groovy": () => import("highlight.js/lib/languages/groovy"),
"text/x-gss": null,
"text/x-haml": () => import("highlight.js/lib/languages/haml"),
"text/x-haskell": () => import("highlight.js/lib/languages/haskell"),
"text/x-haxe": () => import("highlight.js/lib/languages/haxe"),
"text/x-hcl": () => import("./languages/terraform.js"),
"text/x-hxml": null,
"text/x-idl": null,
"text/x-java": () => import("highlight.js/lib/languages/java"),
"text/x-julia": () => import("highlight.js/lib/languages/julia"),
"text/x-kotlin": () => import("highlight.js/lib/languages/kotlin"),
"text/x-latex": () => import("highlight.js/lib/languages/latex"),
"text/x-less": () => import("highlight.js/lib/languages/less"),
"text/x-literate-haskell": null,
"text/x-livescript": () => import("highlight.js/lib/languages/livescript"),
"text/x-lua": () => import("highlight.js/lib/languages/lua"),
"text/x-mariadb": () => import("highlight.js/lib/languages/sql"),
"text/x-markdown": () => import("highlight.js/lib/languages/markdown"),
"text/x-mathematica": () => import("highlight.js/lib/languages/mathematica"),
"text/x-modelica": null,
"text/x-mscgen": null,
"text/x-msgenny": null,
"text/x-mssql": () => import("highlight.js/lib/languages/sql"),
"text/x-mumps": null,
"text/x-mysql": () => import("highlight.js/lib/languages/sql"),
"text/x-nix": () => import("highlight.js/lib/languages/nix"),
"text/x-nginx-conf": () => import("highlight.js/lib/languages/nginx"),
"text/x-nsis": () => import("highlight.js/lib/languages/nsis"),
"text/x-objectivec": () => import("highlight.js/lib/languages/objectivec"),
"text/x-ocaml": () => import("highlight.js/lib/languages/ocaml"),
"text/x-octave": null,
"text/x-oz": null,
"text/x-pascal": () => import("highlight.js/lib/languages/delphi"),
"text/x-perl": () => import("highlight.js/lib/languages/perl"),
"text/x-pgsql": () => import("highlight.js/lib/languages/sql"),
"text/x-php": () => import("highlight.js/lib/languages/php"),
"text/x-pig": null,
"text/x-plsql": () => import("highlight.js/lib/languages/sql"),
"text/x-properties": () => import("highlight.js/lib/languages/properties"),
"text/x-protobuf": () => import("highlight.js/lib/languages/protobuf"),
"text/x-pug": null,
"text/x-puppet": () => import("highlight.js/lib/languages/puppet"),
"text/x-python": () => import("highlight.js/lib/languages/python"),
"text/x-q": () => import("highlight.js/lib/languages/q"),
"text/x-rpm-changes": null,
"text/x-rpm-spec": () => import("./languages/rpm-specfile.js"),
"text/x-rsrc": () => import("highlight.js/lib/languages/r"),
"text/x-rst": null,
"text/x-ruby": () => import("highlight.js/lib/languages/ruby"),
"text/x-rustsrc": () => import("highlight.js/lib/languages/rust"),
"text/x-sas": () => import("highlight.js/lib/languages/sas"),
"text/x-sass": () => import("highlight.js/lib/languages/scss"),
"text/x-scala": () => import("highlight.js/lib/languages/scala"),
"text/x-scheme": () => import("highlight.js/lib/languages/scheme"),
"text/x-scss": () => import("highlight.js/lib/languages/scss"),
"text/x-sh": () => import("highlight.js/lib/languages/bash"),
"text/x-slim": null,
"text/x-smarty": null,
"text/x-sml": () => import("highlight.js/lib/languages/sml"),
"text/x-solr": null,
"text/x-soy": null,
"text/x-spreadsheet": null,
"text/x-sql": () => import("highlight.js/lib/languages/sql"),
"text/x-sqlite;schema=trilium": () => import("highlight.js/lib/languages/sql"),
"text/x-sqlite": () => import("highlight.js/lib/languages/sql"),
"text/x-squirrel": null,
"text/x-stex": null,
"text/x-stsrc": () => import("highlight.js/lib/languages/smalltalk"),
"text/x-styl": () => import("highlight.js/lib/languages/stylus"),
"text/x-swift": () => import("highlight.js/lib/languages/swift"),
"text/x-systemverilog": () => import("highlight.js/lib/languages/verilog"),
"text/x-tcl": () => import("highlight.js/lib/languages/tcl"),
"text/x-textile": null,
"text/x-tiddlywiki": null,
"text/x-toml": () => import("highlight.js/lib/languages/ini"),
"text/x-tornado": null,
"text/x-ttcn-asn": null,
"text/x-ttcn-cfg": null,
"text/x-ttcn": () => import("./languages/ttcn3.js"),
"text/x-twig": () => import("highlight.js/lib/languages/twig"),
"text/x-vb": () => import("highlight.js/lib/languages/vbnet"),
"text/x-verilog": () => import("highlight.js/lib/languages/verilog"),
"text/x-vhdl": () => import("highlight.js/lib/languages/vhdl"),
"text/x-vue": null,
"text/x-webidl": null,
"text/x-xu": null,
"text/x-yacas": null,
"text/x-yaml": () => import("highlight.js/lib/languages/yaml"),
"text/x-z80": null,
"text/xml": () => import("highlight.js/lib/languages/xml"),
}
const normalizedByMimeType: MimeRecord = {};
for (const [mimeType, loader] of Object.entries(byMimeType)) {
const normalizedMimeType = normalizeMimeTypeForCKEditor(mimeType);
normalizedByMimeType[normalizedMimeType] = loader;
}
export default normalizedByMimeType;

View File

@ -0,0 +1,10 @@
import themeDefinitions from "./themes.js";
import { describe, expect, it } from "vitest";
describe("Themes", () => {
it("all IDs don't contain spaces", () => {
for (const id of Object.keys(themeDefinitions)) {
expect(id).not.toMatch(/\s/);
}
});
});

View File

@ -0,0 +1,329 @@
export interface Theme {
name: string;
load: () => Promise<{ default: typeof import("*.css", { with: { "resolution-mode": "import" } }); }>;
}
const themeDefinitions: Record<string, Theme> = {
"1c-light": {
name: "1C (Light)",
load: () => import("../node_modules/highlight.js/styles/1c-light.css?raw")
},
"a11y-dark": {
name: "a11y (Dark)",
load: () => import("../node_modules/highlight.js/styles/a11y-dark.css?raw")
},
"a11y-light": {
name: "a11y (Light)",
load: () => import("../node_modules/highlight.js/styles/a11y-light.css?raw")
},
"agate": {
name: "Agate (Dark)",
load: () => import("../node_modules/highlight.js/styles/agate.css?raw")
},
"an-old-hope": {
name: "An Old Hope (Dark)",
load: () => import("../node_modules/highlight.js/styles/an-old-hope.css?raw")
},
"androidstudio": {
name: "Android Studio (Dark)",
load: () => import("../node_modules/highlight.js/styles/androidstudio.css?raw")
},
"arduino-light": {
name: "Arduino (Light)",
load: () => import("../node_modules/highlight.js/styles/arduino-light.css?raw")
},
"arta": {
name: "Arta (Dark)",
load: () => import("../node_modules/highlight.js/styles/arta.css?raw")
},
"ascetic": {
name: "Ascetic (Light)",
load: () => import("../node_modules/highlight.js/styles/ascetic.css?raw")
},
"atom-one-dark-reasonable": {
name: "Atom One with ReasonML support (Dark)",
load: () => import("../node_modules/highlight.js/styles/atom-one-dark-reasonable.css?raw")
},
"atom-one-dark": {
name: "Atom One (Dark)",
load: () => import("../node_modules/highlight.js/styles/atom-one-dark.css?raw")
},
"atom-one-light": {
name: "Atom One (Light)",
load: () => import("../node_modules/highlight.js/styles/atom-one-light.css?raw")
},
"brown-paper": {
name: "Brown Paper (Light)",
load: () => import("../node_modules/highlight.js/styles/brown-paper.css?raw")
},
"codepen-embed": {
name: "CodePen Embed (Dark)",
load: () => import("../node_modules/highlight.js/styles/codepen-embed.css?raw")
},
"color-brewer": {
name: "Color Brewer (Light)",
load: () => import("../node_modules/highlight.js/styles/color-brewer.css?raw")
},
"cybertopia-cherry": {
name: "Cybertopia Cherry (Dark)",
load: () => import("../node_modules/highlight.js/styles/cybertopia-cherry.css?raw")
},
"cybertopia-dimmer": {
name: "Cybertopia Dimmer (Dark)",
load: () => import("../node_modules/highlight.js/styles/cybertopia-dimmer.css?raw")
},
"cybertopia-icecap": {
name: "Cybertopia Icecap (Dark)",
load: () => import("../node_modules/highlight.js/styles/cybertopia-icecap.css?raw")
},
"cybertopia-saturated": {
name: "Cybertopia Saturated (Dark)",
load: () => import("../node_modules/highlight.js/styles/cybertopia-saturated.css?raw")
},
"dark": {
name: "Dark",
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;

11
packages/highlightjs/src/types.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
declare module '@exercism/highlightjs-gdscript' {
import { LanguageFn } from "highlight.js";
const defineLanguage: LanguageFn;
export default defineLanguage;
}
declare module 'highlightjs-cypher' {
import { LanguageFn } from "highlight.js";
const defineLanguage: LanguageFn;
export default defineLanguage;
}

View File

@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "../commons"
},
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,39 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"rootDir": "src",
"outDir": "dist",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
"emitDeclarationOnly": true,
"forceConsistentCasingInFileNames": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"types": [
"node",
"vite/client"
]
},
"include": [
"src/**/*.ts"
],
"references": [
{
"path": "../commons/tsconfig.lib.json"
}
],
"exclude": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
]
}

View File

@ -0,0 +1,36 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"forceConsistentCasingInFileNames": true,
"noImplicitOverride": true,
"noImplicitReturns": true
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@ -0,0 +1,42 @@
import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../node_modules/.vite/packages/highlightjs',
plugins: [dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') }),],
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'highlightjs',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: []
},
},
test: {
'watch': false,
'globals': true,
'environment': "happy-dom",
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
'reporters': ["default"],
'coverage': {
'reportsDirectory': './test-output/vitest/coverage',
'provider': 'v8' as const,
}
},
}));

84
pnpm-lock.yaml generated
View File

@ -364,9 +364,6 @@ importers:
'@electron/remote':
specifier: 2.1.2
version: 2.1.2(electron@36.2.1)
'@highlightjs/cdn-assets':
specifier: 11.11.1
version: 11.11.1
better-sqlite3:
specifier: ^11.9.1
version: 11.10.0
@ -1284,6 +1281,24 @@ importers:
specifier: ^2.3.0
version: 2.8.1
packages/highlightjs:
dependencies:
'@exercism/highlightjs-gdscript':
specifier: 0.0.1
version: 0.0.1
'@triliumnext/commons':
specifier: workspace:*
version: link:../commons
highlight.js:
specifier: 11.11.1
version: 11.11.1
highlightjs-cobol:
specifier: 0.3.3
version: 0.3.3
highlightjs-cypher:
specifier: 1.2.0
version: 1.2.0
packages/turndown-plugin-gfm:
dependencies:
'@swc/helpers':
@ -3127,6 +3142,9 @@ packages:
resolution: {integrity: sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA==}
engines: {node: '>=10'}
'@exercism/highlightjs-gdscript@0.0.1':
resolution: {integrity: sha512-LiCFDhXCr3iIEGESHEsSCpCI7qNa2suHcrBWeOYSEtEwCXc+IQpEh5i4K8qPcOMJB9ckVOgLgbSNML8TyvPCVg==}
'@file-type/xml@0.4.3':
resolution: {integrity: sha512-pGRmkHf+NofNy/52r06HOTsEwdNnBsFEhN6U95s33P+ezuoxZEyBTV9lOB1/Zr0So6/9vDVfWZXLpgd0fy8cOQ==}
@ -3366,10 +3384,6 @@ packages:
'@hapi/topo@5.1.0':
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
'@highlightjs/cdn-assets@11.11.1':
resolution: {integrity: sha512-VEPdHzwelZ12hEX18BHduqxMZGolcUsrbeokHYxOUIm8X2+M7nx5QPtPeQgRxR9XjhdLv4/7DD5BWOlSrJ3k7Q==}
engines: {node: '>=12.0.0'}
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@ -8755,6 +8769,16 @@ packages:
resolution: {integrity: sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==}
engines: {node: '>=18.0.0'}
highlight.js@11.11.1:
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
engines: {node: '>=12.0.0'}
highlightjs-cobol@0.3.3:
resolution: {integrity: sha512-sdEHzA1UQM9Fjx6wMkWLq8VN70SHascq84aFJJzenOF2TwHE4nwtKCbhHGzOWQKN0AUnn0yAHfXQqaH8i2C8YA==}
highlightjs-cypher@1.2.0:
resolution: {integrity: sha512-mOY/g6R1MgXiYx07icl8nwtXCRDSy4Y9EAlDZKia8Thqe766v6cjnrD6/xWak9UXoLQfWqbHhmRmYuw0SiO+CA==}
history@4.10.1:
resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==}
@ -16061,7 +16085,7 @@ snapshots:
find-up: 5.0.0
fs-extra: 10.1.0
log-symbols: 4.1.0
semver: 7.7.1
semver: 7.7.2
transitivePeerDependencies:
- bluebird
- supports-color
@ -16098,7 +16122,7 @@ snapshots:
log-symbols: 4.1.0
node-fetch: 2.7.0(encoding@0.1.13)
rechoir: 0.8.0
semver: 7.7.1
semver: 7.7.2
source-map-support: 0.5.21
sudo-prompt: 9.2.1
username: 5.1.0
@ -16825,6 +16849,8 @@ snapshots:
'@excalidraw/random-username@1.1.0': {}
'@exercism/highlightjs-gdscript@0.0.1': {}
'@file-type/xml@0.4.3':
dependencies:
sax: 1.4.1
@ -17042,8 +17068,6 @@ snapshots:
dependencies:
'@hapi/hoek': 9.3.0
'@highlightjs/cdn-assets@11.11.1': {}
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.6':
@ -17566,7 +17590,7 @@ snapshots:
debug: 4.4.1(supports-color@8.1.1)
electron-installer-common: 0.10.4
lodash: 4.17.21
semver: 7.7.1
semver: 7.7.2
yargs: 16.2.0
transitivePeerDependencies:
- supports-color
@ -17888,7 +17912,7 @@ snapshots:
minimatch: 9.0.3
picocolors: 1.1.1
resolve.exports: 2.0.3
semver: 7.7.1
semver: 7.7.2
tslib: 2.8.1
yargs-parser: 21.1.1
transitivePeerDependencies:
@ -19568,7 +19592,7 @@ snapshots:
graphemer: 1.4.0
ignore: 5.3.2
natural-compare-lite: 1.4.0
semver: 7.7.1
semver: 7.7.2
tsutils: 3.21.0(typescript@4.9.5)
optionalDependencies:
typescript: 4.9.5
@ -21477,7 +21501,7 @@ snapshots:
postcss-modules-scope: 3.2.1(postcss@8.5.3)
postcss-modules-values: 4.0.0(postcss@8.5.3)
postcss-value-parser: 4.2.0
semver: 7.7.1
semver: 7.7.2
optionalDependencies:
webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(webpack-cli@6.0.1)
@ -23218,7 +23242,7 @@ snapshots:
minimatch: 3.1.2
node-abort-controller: 3.1.1
schema-utils: 3.3.0
semver: 7.7.1
semver: 7.7.2
tapable: 2.2.1
typescript: 5.8.3
webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(webpack-cli@6.0.1)
@ -23711,6 +23735,18 @@ snapshots:
helmet@8.1.0: {}
highlight.js@11.11.1: {}
highlightjs-cobol@0.3.3:
dependencies:
minimist: 1.2.8
mkdirp: 1.0.4
highlightjs-cypher@1.2.0:
dependencies:
minimist: 1.2.8
mkdirp: 1.0.4
history@4.10.1:
dependencies:
'@babel/runtime': 7.27.1
@ -24578,7 +24614,7 @@ snapshots:
jest-util: 29.7.0
natural-compare: 1.4.0
pretty-format: 29.7.0
semver: 7.7.1
semver: 7.7.2
transitivePeerDependencies:
- supports-color
@ -25792,7 +25828,7 @@ snapshots:
node-abi@4.8.0:
dependencies:
semver: 7.7.1
semver: 7.7.2
node-abort-controller@3.1.1: {}
@ -25800,7 +25836,7 @@ snapshots:
node-api-version@0.2.1:
dependencies:
semver: 7.7.1
semver: 7.7.2
node-domexception@1.0.0: {}
@ -25834,7 +25870,7 @@ snapshots:
make-fetch-happen: 14.0.3
nopt: 8.1.0
proc-log: 5.0.0
semver: 7.7.1
semver: 7.7.2
tar: 7.4.3
tinyglobby: 0.2.13
which: 5.0.0
@ -25902,7 +25938,7 @@ snapshots:
dependencies:
hosted-git-info: 7.0.2
proc-log: 3.0.0
semver: 7.7.1
semver: 7.7.2
validate-npm-package-name: 5.0.1
npm-run-path@2.0.2:
@ -26620,7 +26656,7 @@ snapshots:
cosmiconfig: 7.1.0
klona: 2.0.6
postcss: 8.5.3
semver: 7.7.1
semver: 7.7.2
webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(webpack-cli@6.0.1)
postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.0.4)(webpack@5.99.8(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(webpack-cli@6.0.1)):
@ -28918,7 +28954,7 @@ snapshots:
chalk: 4.1.2
enhanced-resolve: 5.18.1
micromatch: 4.0.8
semver: 7.7.1
semver: 7.7.2
source-map: 0.7.4
typescript: 5.0.4
webpack: 5.99.8(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(webpack-cli@6.0.1)
@ -28928,7 +28964,7 @@ snapshots:
chalk: 4.1.2
enhanced-resolve: 5.18.1
micromatch: 4.0.8
semver: 7.7.1
semver: 7.7.2
source-map: 0.7.4
typescript: 5.8.3
webpack: 5.98.0(@swc/core@1.11.24(@swc/helpers@0.5.17))(esbuild@0.25.4)(webpack-cli@6.0.1)

View File

@ -53,6 +53,9 @@
},
{
"path": "./packages/codemirror"
},
{
"path": "./packages/highlightjs"
}
]
}