From 3729c16fd685dbffdc4959cdda4ad995a3ad1596 Mon Sep 17 00:00:00 2001 From: Tron Date: Mon, 24 Nov 2025 22:56:40 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/protyle/render/mindmapRender.ts | 220 ++++++++++++------------ 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/app/src/protyle/render/mindmapRender.ts b/app/src/protyle/render/mindmapRender.ts index 3db651463..451c9d513 100644 --- a/app/src/protyle/render/mindmapRender.ts +++ b/app/src/protyle/render/mindmapRender.ts @@ -1,7 +1,7 @@ -import {addScript} from "../util/addScript"; -import {Constants} from "../../constants"; -import {hasClosestByClassName} from "../util/hasClosest"; -import {genIconHTML} from "./util"; +import { addScript } from "../util/addScript"; +import { Constants } from "../../constants"; +import { hasClosestByClassName } from "../util/hasClosest"; +import { genIconHTML } from "./util"; export const mindmapRender = (element: Element, cdn = Constants.PROTYLE_CDN) => { let mindmapElements: Element[] = []; @@ -19,122 +19,122 @@ export const mindmapRender = (element: Element, cdn = Constants.PROTYLE_CDN) => .then(() => addScript(`${cdn}/js/markmap/markmap-lib.min.js`, "protyleMarkmapLibScript")) .then(() => addScript(`${cdn}/js/markmap/markmap-view.min.js`, "protyleMarkmapScript")) .then(() => { - const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true); - let width: number = undefined; - if (wysiswgElement && wysiswgElement.clientWidth > 0 && mindmapElements[0].firstElementChild.clientWidth === 0 && wysiswgElement.firstElementChild) { - width = wysiswgElement.firstElementChild.clientWidth; - } - mindmapElements.forEach((e: HTMLDivElement) => { - if (e.getAttribute("data-render") === "true") { - return; + const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true); + let width: number = undefined; + if (wysiswgElement && wysiswgElement.clientWidth > 0 && mindmapElements[0].firstElementChild.clientWidth === 0 && wysiswgElement.firstElementChild) { + width = wysiswgElement.firstElementChild.clientWidth; } - if (!e.firstElementChild.classList.contains("protyle-icons")) { - e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement)); - } - const renderElement = e.firstElementChild.nextElementSibling as HTMLElement; - if (!e.getAttribute("data-content")) { - renderElement.innerHTML = `${Constants.ZWSP}`; - return; - } - try { - // create or reuse container for markmap - if (!renderElement.lastElementChild || renderElement.childElementCount === 1) { - renderElement.innerHTML = `${Constants.ZWSP}
`; - } else { - renderElement.lastElementChild.classList.remove("ft__error"); + mindmapElements.forEach((e: HTMLDivElement) => { + if (e.getAttribute("data-render") === "true") { + return; } + if (!e.firstElementChild.classList.contains("protyle-icons")) { + e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement)); + } + const renderElement = e.firstElementChild.nextElementSibling as HTMLElement; + if (!e.getAttribute("data-content")) { + renderElement.innerHTML = `${Constants.ZWSP}`; + return; + } + try { + // create or reuse container for markmap + if (!renderElement.lastElementChild || renderElement.childElementCount === 1) { + renderElement.innerHTML = `${Constants.ZWSP}
`; + } else { + renderElement.lastElementChild.classList.remove("ft__error"); + } - // Convert stored content to markdown using Lute (prefer existing instance), then transform/render with markmap - const raw = Lute.UnEscapeHTMLStr(e.getAttribute("data-content")); - let md: string = raw; - // prefer protyle's lute instance if available - if ((window as any).protyle && (window as any).protyle.lute && typeof (window as any).protyle.lute.BlockDOM2Md === "function") { - md = (window as any).protyle.lute.BlockDOM2Md(raw); - } else if (typeof Lute === "function" && typeof Lute.New === "function") { + // Convert stored content to markdown using Lute (prefer existing instance), then transform/render with markmap + const raw = Lute.UnEscapeHTMLStr(e.getAttribute("data-content")); + let md: string = raw; + // prefer protyle's lute instance if available + if ((window as any).protyle && (window as any).protyle.lute && typeof (window as any).protyle.lute.BlockDOM2Md === "function") { + md = (window as any).protyle.lute.BlockDOM2Md(raw); + } else if (typeof Lute === "function" && typeof Lute.New === "function") { + try { + const luteInst = Lute.New(); + if (luteInst && typeof luteInst.BlockDOM2Md === "function") { + md = luteInst.BlockDOM2Md(raw); + } else if (luteInst && typeof luteInst.BlockDOM2HTML === "function") { + md = luteInst.BlockDOM2HTML(raw); + } + } catch (e) { + // fallback to raw + md = raw; + } + } + + // Try to obtain markmap entry from loaded bundles (single unified reference) + const mm: any = (window as any).markmap; + + // Prefer the new markmap Transformer API when available + let data: any = null; + let rootData: any = null; try { - const luteInst = Lute.New(); - if (luteInst && typeof luteInst.BlockDOM2Md === "function") { - md = luteInst.BlockDOM2Md(raw); - } else if (luteInst && typeof luteInst.BlockDOM2HTML === "function") { - md = luteInst.BlockDOM2HTML(raw); + if (mm && typeof mm.Transformer === "function") { + const transformer = new mm.Transformer(); + const tx = transformer.transform(md); + // tx contains { root, features } + rootData = tx && tx.root; + + // load assets required by used features + const assetsGetter = typeof transformer.getUsedAssets === "function" ? "getUsedAssets" : (typeof transformer.getAssets === "function" ? "getAssets" : null); + if (assetsGetter) { + const assets = (transformer as any)[assetsGetter](tx.features); + const styles = assets && assets.styles; + const scripts = assets && assets.scripts; + if (styles && typeof mm.loadCSS === "function") { + try { mm.loadCSS(styles); } catch (err) { /* ignore */ } + } + if (scripts && typeof mm.loadJS === "function") { + try { mm.loadJS(scripts, { getMarkmap: () => (window as any).markmap }); } catch (err) { /* ignore */ } + } + } + } else if (mm && typeof mm.transform === "function") { + data = mm.transform(md); + } else if ((window as any).markmap && typeof (window as any).markmap.transform === "function") { + data = (window as any).markmap.transform(md); } } catch (e) { - // fallback to raw - md = raw; + // fallback, leave data/rootData null and let downstream handle it + data = null; + rootData = null; } - } - // Try to obtain markmap entry from loaded bundles (single unified reference) - const mm: any = (window as any).markmap; - - // Prefer the new markmap Transformer API when available - let data: any = null; - let rootData: any = null; - try { - if (mm && typeof mm.Transformer === "function") { - const transformer = new mm.Transformer(); - const tx = transformer.transform(md); - // tx contains { root, features } - rootData = tx && tx.root; - - // load assets required by used features - const assetsGetter = typeof transformer.getUsedAssets === "function" ? "getUsedAssets" : (typeof transformer.getAssets === "function" ? "getAssets" : null); - if (assetsGetter) { - const assets = (transformer as any)[assetsGetter](tx.features); - const styles = assets && assets.styles; - const scripts = assets && assets.scripts; - if (styles && typeof mm.loadCSS === "function") { - try { mm.loadCSS(styles); } catch (err) { /* ignore */ } - } - if (scripts && typeof mm.loadJS === "function") { - try { mm.loadJS(scripts, { getMarkmap: () => (window as any).markmap }); } catch (err) { /* ignore */ } - } - } - } else if (mm && typeof mm.transform === "function") { - data = mm.transform(md); - } else if ((window as any).markmap && typeof (window as any).markmap.transform === "function") { - data = (window as any).markmap.transform(md); - } - } catch (e) { - // fallback, leave data/rootData null and let downstream handle it - data = null; - rootData = null; - } - - // container for svg - const container = renderElement.lastElementChild as HTMLElement; - // clear existing content and append an svg for markmap - container.innerHTML = ""; - const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - // use width if calculated earlier - if (typeof width === "number" && width > 0) { - svg.setAttribute("width", String(width)); - } else { - svg.setAttribute("width", "100%"); - } - svg.setAttribute("height", "100%"); - container.appendChild(svg); - - // prefer Markmap.create if available - const MarkmapCtor = (mm && (mm.Markmap || mm.default || mm)) || (window as any).Markmap; - if (MarkmapCtor && typeof MarkmapCtor.create === "function") { - if (rootData) { - // When Transformer was used we have a `root` structure - MarkmapCtor.create(svg, null, rootData); + // container for svg + const container = renderElement.lastElementChild as HTMLElement; + // clear existing content and append an svg for markmap + container.innerHTML = ""; + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + // use width if calculated earlier + if (typeof width === "number" && width > 0) { + svg.setAttribute("width", String(width)); } else { - if (!data && typeof MarkmapCtor.transform === "function") { - try { data = MarkmapCtor.transform(md); } catch (err) { data = null; } - } - MarkmapCtor.create(svg, data || { root: { children: [] } }, { embedCSS: true }); + svg.setAttribute("width", "100%"); } - } else { - throw new Error("Markmap not available"); - } - } catch (error) { + svg.setAttribute("height", "100%"); + container.appendChild(svg); - renderElement.innerHTML = `${Constants.ZWSP}
Mindmap render error:
${error}
`; - } - e.setAttribute("data-render", "true"); + // prefer Markmap.create if available + const MarkmapCtor = (mm && (mm.Markmap || mm.default || mm)) || (window as any).Markmap; + if (MarkmapCtor && typeof MarkmapCtor.create === "function") { + if (rootData) { + // When Transformer was used we have a `root` structure + MarkmapCtor.create(svg, null, rootData); + } else { + if (!data && typeof MarkmapCtor.transform === "function") { + try { data = MarkmapCtor.transform(md); } catch (err) { data = null; } + } + MarkmapCtor.create(svg, data || { root: { children: [] } }, { embedCSS: true }); + } + } else { + throw new Error("Markmap not available"); + } + } catch (error) { + + renderElement.innerHTML = `${Constants.ZWSP}
Mindmap render error:
${error}
`; + } + e.setAttribute("data-render", "true"); + }); }); - }); };