UNPKG

vditor

Version:

♏ 易于使用的 Markdown 编辑器,为适配不同的应用场景而生

111 lines (109 loc) 5.28 kB
import {hasClosestByHeadings} from "../util/hasClosestByHeadings"; import {mathRender} from "./mathRender"; export const outlineRender = (contentElement: HTMLElement, targetElement: Element, vditor?: IVditor) => { let tocHTML = ""; const ids: string[] = []; Array.from(contentElement.children).forEach((item: HTMLElement, index: number) => { if (hasClosestByHeadings(item)) { if (vditor) { const lastIndex = item.id.lastIndexOf("_"); item.id = item.id.substring(0, lastIndex === -1 ? undefined : lastIndex) + "_" + index; } ids.push(item.id); tocHTML += item.outerHTML.replace("<wbr>", ""); } }); if (tocHTML === "") { targetElement.innerHTML = ""; return ""; } const tempElement = document.createElement("div"); if (vditor) { vditor.lute.SetToC(true); if (vditor.currentMode === "wysiwyg" && !vditor.preview.element.contains(contentElement)) { tempElement.innerHTML = vditor.lute.SpinVditorDOM("<p>[ToC]</p>" + tocHTML); } else if (vditor.currentMode === "ir" && !vditor.preview.element.contains(contentElement)) { tempElement.innerHTML = vditor.lute.SpinVditorIRDOM("<p>[ToC]</p>" + tocHTML); } else { tempElement.innerHTML = vditor.lute.HTML2VditorDOM("<p>[ToC]</p>" + tocHTML); } vditor.lute.SetToC(vditor.options.preview.markdown.toc); } else { targetElement.classList.add("vditor-outline"); const lute = Lute.New(); lute.SetToC(true); tempElement.innerHTML = lute.HTML2VditorDOM("<p>[ToC]</p>" + tocHTML); } const headingsElement = tempElement.firstElementChild.querySelectorAll("li > span[data-target-id]"); headingsElement.forEach((item, index) => { if (item.nextElementSibling && item.nextElementSibling.tagName === "UL") { let iconHTML = "<svg class='vditor-outline__action'><use xlink:href='#vditor-icon-down'></use></svg>"; if (!document.getElementById("vditorIconScript")) { iconHTML = '<svg class="vditor-outline__action" viewBox="0 0 32 32"><path d="M3.76 6.12l12.24 12.213 12.24-12.213 3.76 3.76-16 16-16-16 3.76-3.76z"></path></svg>'; } item.innerHTML = `${iconHTML}<span>${item.innerHTML}</span>`; } else { item.innerHTML = `<svg></svg><span>${item.innerHTML}</span>`; } item.setAttribute("data-target-id", ids[index]); }); tocHTML = tempElement.firstElementChild.innerHTML; if (headingsElement.length === 0) { targetElement.innerHTML = ""; return tocHTML; } targetElement.innerHTML = tocHTML; if (vditor) { mathRender(targetElement as HTMLElement, { cdn: vditor.options.cdn, math: vditor.options.preview.math, }); } targetElement.firstElementChild.addEventListener("click", (event: Event) => { let target = event.target as HTMLElement; while (target && !target.isEqualNode(targetElement)) { if (target.classList.contains("vditor-outline__action")) { if (target.classList.contains("vditor-outline__action--close")) { target.classList.remove("vditor-outline__action--close"); target.parentElement.nextElementSibling.setAttribute("style", "display:block"); } else { target.classList.add("vditor-outline__action--close"); target.parentElement.nextElementSibling.setAttribute("style", "display:none"); } event.preventDefault(); event.stopPropagation(); break; } else if (target.getAttribute("data-target-id")) { event.preventDefault(); event.stopPropagation(); const idElement = document.getElementById(target.getAttribute("data-target-id")); if (!idElement) { return; } if (vditor) { if (vditor.options.height === "auto") { let windowScrollY = idElement.offsetTop + vditor.element.offsetTop; if (!vditor.options.toolbarConfig.pin) { windowScrollY += vditor.toolbar.element.offsetHeight; } window.scrollTo(window.scrollX, windowScrollY); } else { if (vditor.element.offsetTop < window.scrollY) { window.scrollTo(window.scrollX, vditor.element.offsetTop); } if (vditor.preview.element.contains(contentElement)) { contentElement.parentElement.scrollTop = idElement.offsetTop; } else { contentElement.scrollTop = idElement.offsetTop; } } } else { window.scrollTo(window.scrollX, idElement.offsetTop); } break; } target = target.parentElement; } }); return tocHTML; };