✨ feat: 新增 WYSIWYG 编辑器功能和相关工具栏事件处理
This commit is contained in:
110
web/include/vditor/src/ts/markdown/outlineRender.ts
Normal file
110
web/include/vditor/src/ts/markdown/outlineRender.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
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;
|
||||
};
|
||||
Reference in New Issue
Block a user