From a2976d9ad5e2bfd8a9dae6f31aad9a7d43a29609 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 24 Nov 2025 18:58:21 +0200 Subject: [PATCH] refactor(mime): proper typechecking of supported MIME types --- packages/codemirror/src/syntax_highlighting.ts | 4 +++- packages/commons/src/lib/mime_type.ts | 12 ++++++++---- packages/highlightjs/src/syntax_highlighting.ts | 9 +++++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/codemirror/src/syntax_highlighting.ts b/packages/codemirror/src/syntax_highlighting.ts index 52fe83ce9..518c84732 100644 --- a/packages/codemirror/src/syntax_highlighting.ts +++ b/packages/codemirror/src/syntax_highlighting.ts @@ -1,6 +1,7 @@ import { LanguageSupport, type StreamParser } from "@codemirror/language"; import {linter as linterExtension, lintGutter } from "@codemirror/lint"; import type { Extension } from "@codemirror/state"; +import { SupportedMimeTypes } from "@triliumnext/commons"; async function buildJavaScript(mimeType: string) { const { javascript, esLint } = await import('@codemirror/lang-javascript'); @@ -22,7 +23,7 @@ async function buildMermaid() { return [ mermaid(), foldByIndent() ]; } -const byMimeType: Record Promise | LanguageSupport | Extension[]>) | null> = { +const byMimeType: Record Promise | LanguageSupport | Extension[]>) | null> = { "text/plain": null, "application/dart": async () => (await import('@codemirror/legacy-modes/mode/clike')).dart, @@ -115,6 +116,7 @@ const byMimeType: Record Promise | Language "text/x-idl": async () => (await import('@codemirror/legacy-modes/mode/idl')).idl, "text/x-java": async () => (await import('@codemirror/legacy-modes/mode/clike')).java, "text/x-julia": async () => (await import('@codemirror/legacy-modes/mode/julia')).julia, + "text/x-pegjs": null, "text/x-kotlin": async () => (await import('@codemirror/legacy-modes/mode/clike')).kotlin, "text/x-latex": async () => (await import('@codemirror/legacy-modes/mode/stex')).stex, "text/x-less": async () => (await import('@codemirror/legacy-modes/mode/css')).less, diff --git a/packages/commons/src/lib/mime_type.ts b/packages/commons/src/lib/mime_type.ts index b594641a1..67100b325 100644 --- a/packages/commons/src/lib/mime_type.ts +++ b/packages/commons/src/lib/mime_type.ts @@ -33,7 +33,7 @@ export function normalizeMimeTypeForCKEditor(mimeType: 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([ +const MIME_TYPES_DICT_RAW = [ { title: "Plain text", mime: "text/plain", mdLanguageCode: "plaintext", default: true }, // Keep sorted alphabetically. @@ -131,7 +131,7 @@ export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([ { 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: "PEG.js", mime: "text/x-pegjs" }, { title: "Perl", mime: "text/x-perl", default: true }, { title: "PGP", mime: "application/pgp" }, { title: "PHP", mime: "text/x-php", default: true }, @@ -175,7 +175,7 @@ export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([ { 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" }, + { title: "Terraform (HCL)", mime: "text/x-hcl", mdLanguageCode: "terraform" }, { title: "Textile", mime: "text/x-textile" }, { title: "TiddlyWiki ", mime: "text/x-tiddlywiki" }, { title: "Tiki wiki", mime: "text/tiki" }, @@ -201,10 +201,14 @@ export const MIME_TYPES_DICT: readonly MimeTypeDefinition[] = Object.freeze([ { title: "Yacas", mime: "text/x-yacas" }, { title: "YAML", mime: "text/x-yaml", mdLanguageCode: "yaml", default: true }, { title: "Z80", mime: "text/x-z80" } -]); +] as const satisfies readonly MimeTypeDefinition[]; +export const MIME_TYPES_DICT = Object.freeze(MIME_TYPES_DICT_RAW as readonly MimeTypeDefinition[]); let byMarkdownNameMappings: Record | null = null; +export type MermaidMimeType = "text/vnd.mermaid" | "text/mermaid"; +export type SupportedMimeTypes = typeof MIME_TYPES_DICT_RAW[number]["mime"] | MermaidMimeType; + /** * Given a Markdown language tag (e.g. `css`), it returns a corresponding {@link MimeTypeDefinition} if found. * diff --git a/packages/highlightjs/src/syntax_highlighting.ts b/packages/highlightjs/src/syntax_highlighting.ts index 57fd439db..7de6b0781 100644 --- a/packages/highlightjs/src/syntax_highlighting.ts +++ b/packages/highlightjs/src/syntax_highlighting.ts @@ -1,7 +1,7 @@ -import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons"; +import { normalizeMimeTypeForCKEditor, SupportedMimeTypes } from "@triliumnext/commons"; import type { LanguageFn } from "highlight.js"; -type MimeRecord = Record Promise<{ default: LanguageFn}>) | null>; +type MimeRecord = Record Promise<{ default: LanguageFn}>) | null>; export const byMimeType: MimeRecord = { "text/plain": () => import("highlight.js/lib/languages/plaintext"), @@ -90,6 +90,7 @@ export const byMimeType: MimeRecord = { "text/x-idl": null, "text/x-java": () => import("highlight.js/lib/languages/java"), "text/x-julia": () => import("highlight.js/lib/languages/julia"), + "text/x-pegjs": null, "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"), @@ -172,10 +173,10 @@ export const byMimeType: MimeRecord = { "text/xml": () => import("highlight.js/lib/languages/xml"), } -const normalizedByMimeType: MimeRecord = {}; +const normalizedByMimeType: Partial = {}; for (const [mimeType, loader] of Object.entries(byMimeType)) { const normalizedMimeType = normalizeMimeTypeForCKEditor(mimeType); normalizedByMimeType[normalizedMimeType] = loader; } -export default normalizedByMimeType; +export default normalizedByMimeType as MimeRecord;