mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08:00 
			
		
		
		
	refactor(client): use webpack for mermaid
This commit is contained in:
		
							parent
							
								
									f4d5b9fc29
								
							
						
					
					
						commit
						28c51cb38a
					
				@ -76,7 +76,6 @@ try {
 | 
			
		||||
        "node_modules/dayjs/",
 | 
			
		||||
        "node_modules/boxicons/css/",
 | 
			
		||||
        "node_modules/boxicons/fonts/",
 | 
			
		||||
        "node_modules/mermaid/dist/",
 | 
			
		||||
        "node_modules/jquery/dist/",
 | 
			
		||||
        "node_modules/jquery-hotkeys/",
 | 
			
		||||
        "node_modules/split.js/dist/",
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,6 @@ import RelationMapButtons from "../widgets/floating_buttons/relation_map_buttons
 | 
			
		||||
import SvgExportButton from "../widgets/floating_buttons/svg_export_button.js";
 | 
			
		||||
import BacklinksWidget from "../widgets/floating_buttons/zpetne_odkazy.js";
 | 
			
		||||
import HideFloatingButtonsButton from "../widgets/floating_buttons/hide_floating_buttons_button.js";
 | 
			
		||||
import MermaidWidget from "../widgets/mermaid.js";
 | 
			
		||||
import NoteListWidget from "../widgets/note_list.js";
 | 
			
		||||
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
 | 
			
		||||
import LauncherContainer from "../widgets/containers/launcher_container.js";
 | 
			
		||||
@ -165,7 +164,6 @@ export default class MobileLayout {
 | 
			
		||||
                                    .child(new BacklinksWidget())
 | 
			
		||||
                                    .child(new HideFloatingButtonsButton())
 | 
			
		||||
                            )
 | 
			
		||||
                            .child(new MermaidWidget())
 | 
			
		||||
                            .child(new PromotedAttributesWidget())
 | 
			
		||||
                            .child(
 | 
			
		||||
                                new ScrollingContainer()
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ import { loadElkIfNeeded, postprocessMermaidSvg } from "./mermaid.js";
 | 
			
		||||
import { normalizeMimeTypeForCKEditor } from "./mime_type_definitions.js";
 | 
			
		||||
import renderDoc from "./doc_renderer.js";
 | 
			
		||||
import { t } from "i18next";
 | 
			
		||||
import type { Mermaid } from "mermaid";
 | 
			
		||||
 | 
			
		||||
let idCounter = 1;
 | 
			
		||||
 | 
			
		||||
@ -226,7 +227,7 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function renderMermaid(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>) {
 | 
			
		||||
    await libraryLoader.requireLibrary(libraryLoader.MERMAID);
 | 
			
		||||
    const mermaid = (await import("mermaid")).default;
 | 
			
		||||
 | 
			
		||||
    const blob = await note.getBlob();
 | 
			
		||||
    const content = blob?.content || "";
 | 
			
		||||
@ -236,10 +237,10 @@ async function renderMermaid(note: FNote | FAttachment, $renderedContent: JQuery
 | 
			
		||||
    const documentStyle = window.getComputedStyle(document.documentElement);
 | 
			
		||||
    const mermaidTheme = documentStyle.getPropertyValue("--mermaid-theme");
 | 
			
		||||
 | 
			
		||||
    mermaid.mermaidAPI.initialize({ startOnLoad: false, theme: mermaidTheme.trim(), securityLevel: "antiscript" });
 | 
			
		||||
    mermaid.mermaidAPI.initialize({ startOnLoad: false, theme: mermaidTheme.trim() as "default", securityLevel: "antiscript" });
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        await loadElkIfNeeded(content);
 | 
			
		||||
        await loadElkIfNeeded(mermaid, content);
 | 
			
		||||
        const { svg } = await mermaid.mermaidAPI.render("in-mermaid-graph-" + idCounter++, content);
 | 
			
		||||
 | 
			
		||||
        $renderedContent.append($(postprocessMermaidSvg(svg)));
 | 
			
		||||
 | 
			
		||||
@ -55,10 +55,6 @@ const WHEEL_ZOOM: Library = {
 | 
			
		||||
    js: ["node_modules/vanilla-js-wheel-zoom/dist/wheel-zoom.min.js"]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const MERMAID: Library = {
 | 
			
		||||
    js: ["node_modules/mermaid/dist/mermaid.min.js"]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const MARKJS: Library = {
 | 
			
		||||
    js: ["node_modules/mark.js/dist/jquery.mark.es6.min.js"]
 | 
			
		||||
};
 | 
			
		||||
@ -181,7 +177,6 @@ export default {
 | 
			
		||||
    CALENDAR_WIDGET,
 | 
			
		||||
    KATEX,
 | 
			
		||||
    WHEEL_ZOOM,
 | 
			
		||||
    MERMAID,
 | 
			
		||||
    MARKJS,
 | 
			
		||||
    HIGHLIGHT_JS,
 | 
			
		||||
    LEAFLET
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
import type { Mermaid } from "mermaid";
 | 
			
		||||
 | 
			
		||||
let elkLoaded = false;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -9,7 +11,7 @@ let elkLoaded = false;
 | 
			
		||||
 *
 | 
			
		||||
 * @param mermaidContent the plain text of the mermaid diagram, potentially including a frontmatter.
 | 
			
		||||
 */
 | 
			
		||||
export async function loadElkIfNeeded(mermaidContent: string) {
 | 
			
		||||
export async function loadElkIfNeeded(mermaid: Mermaid, mermaidContent: string) {
 | 
			
		||||
    if (elkLoaded) {
 | 
			
		||||
        // Exit immediately since the ELK library is already loaded.
 | 
			
		||||
        return;
 | 
			
		||||
@ -18,7 +20,7 @@ export async function loadElkIfNeeded(mermaidContent: string) {
 | 
			
		||||
    const parsedContent = await mermaid.parse(mermaidContent, {
 | 
			
		||||
        suppressErrors: true
 | 
			
		||||
    });
 | 
			
		||||
    if (parsedContent?.config?.layout === "elk") {
 | 
			
		||||
    if (parsedContent && parsedContent.config?.layout === "elk") {
 | 
			
		||||
        elkLoaded = true;
 | 
			
		||||
        mermaid.registerLayoutLoaders((await import("@mermaid-js/layout-elk")).default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								src/public/app/types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								src/public/app/types.d.ts
									
									
									
									
										vendored
									
									
								
							@ -8,6 +8,7 @@ import library_loader, { Library } from "./services/library_loader.ts";
 | 
			
		||||
import type { init } from "i18next";
 | 
			
		||||
import type { lint } from "./services/eslint.ts";
 | 
			
		||||
import type { RelationType } from "./widgets/type_widgets/relation_map.ts";
 | 
			
		||||
import type { Mermaid } from "mermaid";
 | 
			
		||||
 | 
			
		||||
interface ElectronProcess {
 | 
			
		||||
    type: string;
 | 
			
		||||
@ -138,45 +139,6 @@ declare global {
 | 
			
		||||
            zoomOnClick: boolean
 | 
			
		||||
        })
 | 
			
		||||
    };
 | 
			
		||||
    interface MermaidApi {
 | 
			
		||||
        initialize(opts: {
 | 
			
		||||
            startOnLoad: boolean,
 | 
			
		||||
            theme: string,
 | 
			
		||||
            securityLevel: "antiscript"
 | 
			
		||||
        }): void;
 | 
			
		||||
        render(selector: string, data: string);
 | 
			
		||||
    }
 | 
			
		||||
    interface MermaidLoader {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    interface MermaidChartConfig {
 | 
			
		||||
        useMaxWidth: boolean;
 | 
			
		||||
    }
 | 
			
		||||
    interface MermaidConfig {
 | 
			
		||||
        theme: string;
 | 
			
		||||
        securityLevel: "antiscript",
 | 
			
		||||
        flow: MermaidChartConfig;
 | 
			
		||||
        sequence: MermaidChartConfig;
 | 
			
		||||
        gantt: MermaidChartConfig;
 | 
			
		||||
        class: MermaidChartConfig;
 | 
			
		||||
        state: MermaidChartConfig;
 | 
			
		||||
        pie: MermaidChartConfig;
 | 
			
		||||
        journey: MermaidChartConfig;
 | 
			
		||||
        git: MermaidChartConfig;
 | 
			
		||||
    }
 | 
			
		||||
    var mermaid: {
 | 
			
		||||
        mermaidAPI: MermaidApi;
 | 
			
		||||
        registerLayoutLoaders(loader: MermaidLoader);
 | 
			
		||||
        init(config: MermaidConfig, el: HTMLElement | JQuery<HTMLElement>);
 | 
			
		||||
        parse(content: string, opts: {
 | 
			
		||||
            suppressErrors: true
 | 
			
		||||
        }): Promise<{
 | 
			
		||||
            config: {
 | 
			
		||||
                layout: string;
 | 
			
		||||
            }
 | 
			
		||||
        }>
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    interface CKCodeBlockLanguage {
 | 
			
		||||
        language: string;
 | 
			
		||||
        label: string;
 | 
			
		||||
@ -207,7 +169,7 @@ declare global {
 | 
			
		||||
                enablePreview: boolean
 | 
			
		||||
            },
 | 
			
		||||
            mermaid: {
 | 
			
		||||
                lazyLoad: () => Promise<void>,
 | 
			
		||||
                lazyLoad: () => Promise<Mermaid>,
 | 
			
		||||
                config: MermaidConfig
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import AbstractSplitTypeWidget from "./abstract_split_type_widget.js";
 | 
			
		||||
 * This adds the following functionality:
 | 
			
		||||
 *
 | 
			
		||||
 * - Automatic handling of the preview when content or the note changes.
 | 
			
		||||
 * - Built-in pan and zoom functionality with automatic re-centering.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
export default abstract class AbstractSvgSplitTypeWidget extends AbstractSplitTypeWidget {
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,10 @@ import dialogService from "../../services/dialog.js";
 | 
			
		||||
import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js";
 | 
			
		||||
import options from "../../services/options.js";
 | 
			
		||||
import toast from "../../services/toast.js";
 | 
			
		||||
import { getMermaidConfig } from "../mermaid.js";
 | 
			
		||||
import { normalizeMimeTypeForCKEditor } from "../../services/mime_type_definitions.js";
 | 
			
		||||
import { buildConfig, buildToolbarConfig } from "./ckeditor/config.js";
 | 
			
		||||
import type FNote from "../../entities/fnote.js";
 | 
			
		||||
import { getMermaidConfig } from "./mermaid.js";
 | 
			
		||||
 | 
			
		||||
const ENABLE_INSPECTOR = false;
 | 
			
		||||
 | 
			
		||||
@ -279,7 +279,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
 | 
			
		||||
                enablePreview: true // Enable preview view
 | 
			
		||||
            },
 | 
			
		||||
            mermaid: {
 | 
			
		||||
                lazyLoad: async () => await libraryLoader.requireLibrary(libraryLoader.MERMAID),
 | 
			
		||||
                lazyLoad: async () => (await import("mermaid")).default, // FIXME
 | 
			
		||||
                config: getMermaidConfig()
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
import type { MermaidConfig } from "mermaid";
 | 
			
		||||
import library_loader from "../../services/library_loader.js";
 | 
			
		||||
import { loadElkIfNeeded, postprocessMermaidSvg } from "../../services/mermaid.js";
 | 
			
		||||
import AbstractSvgSplitTypeWidget from "./abstract_svg_split_type_widget.js";
 | 
			
		||||
@ -11,8 +12,8 @@ export class MermaidTypeWidget extends AbstractSvgSplitTypeWidget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async renderSvg(content: string) {
 | 
			
		||||
        await library_loader.requireLibrary(library_loader.MERMAID);
 | 
			
		||||
        await loadElkIfNeeded(content);
 | 
			
		||||
        const mermaid = (await import("mermaid")).default;
 | 
			
		||||
        await loadElkIfNeeded(mermaid, content);
 | 
			
		||||
 | 
			
		||||
        mermaid.mermaidAPI.initialize({
 | 
			
		||||
            startOnLoad: false,
 | 
			
		||||
@ -28,19 +29,18 @@ export class MermaidTypeWidget extends AbstractSvgSplitTypeWidget {
 | 
			
		||||
 | 
			
		||||
export function getMermaidConfig(): MermaidConfig {
 | 
			
		||||
    const documentStyle = window.getComputedStyle(document.documentElement);
 | 
			
		||||
    const mermaidTheme = documentStyle.getPropertyValue("--mermaid-theme");
 | 
			
		||||
    const mermaidTheme = documentStyle.getPropertyValue("--mermaid-theme") as "default";
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        theme: mermaidTheme.trim(),
 | 
			
		||||
        theme: mermaidTheme.trim() as "default",
 | 
			
		||||
        securityLevel: "antiscript",
 | 
			
		||||
        // TODO: Are all these options correct?
 | 
			
		||||
        flow: { useMaxWidth: false },
 | 
			
		||||
        flowchart: { useMaxWidth: false },
 | 
			
		||||
        sequence: { useMaxWidth: false },
 | 
			
		||||
        gantt: { useMaxWidth: false },
 | 
			
		||||
        class: { useMaxWidth: false },
 | 
			
		||||
        state: { useMaxWidth: false },
 | 
			
		||||
        pie: { useMaxWidth: true },
 | 
			
		||||
        journey: { useMaxWidth: false },
 | 
			
		||||
        git: { useMaxWidth: false }
 | 
			
		||||
        gitGraph: { useMaxWidth: false }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
 | 
			
		||||
import libraryLoader from "../../services/library_loader.js";
 | 
			
		||||
import { applySyntaxHighlight } from "../../services/syntax_highlight.js";
 | 
			
		||||
import { getMermaidConfig } from "../mermaid.js";
 | 
			
		||||
import type FNote from "../../entities/fnote.js";
 | 
			
		||||
import type { EventData } from "../../components/app_context.js";
 | 
			
		||||
import { getLocaleById } from "../../services/i18n.js";
 | 
			
		||||
import { getMermaidConfig } from "./mermaid.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="note-detail-readonly-text note-detail-printable">
 | 
			
		||||
@ -141,8 +141,8 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Initialize mermaid
 | 
			
		||||
        await libraryLoader.requireLibrary(libraryLoader.MERMAID);
 | 
			
		||||
        mermaid.init(getMermaidConfig(), this.$content.find(".mermaid-diagram"));
 | 
			
		||||
        const mermaid = (await import("mermaid")).default;
 | 
			
		||||
        mermaid.init(getMermaidConfig(), this.$content.find(".mermaid-diagram")[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async refreshIncludedNoteEvent({ noteId }: EventData<"refreshIncludedNote">) {
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,6 @@ async function register(app: express.Application) {
 | 
			
		||||
    app.use(`/${assetPath}/node_modules/boxicons/css/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/boxicons/css/")));
 | 
			
		||||
    app.use(`/${assetPath}/node_modules/boxicons/fonts/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/boxicons/fonts/")));
 | 
			
		||||
 | 
			
		||||
    app.use(`/${assetPath}/node_modules/mermaid/dist/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/mermaid/dist/")));
 | 
			
		||||
 | 
			
		||||
    app.use(`/${assetPath}/node_modules/jquery/dist/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/jquery/dist/")));
 | 
			
		||||
 | 
			
		||||
    app.use(`/${assetPath}/node_modules/jquery-hotkeys/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/jquery-hotkeys/")));
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user