A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 140 lines 6.5 kB view raw
1import {hasClosestByAttribute} from "../util/hasClosest"; 2import {fetchPost, fetchSyncPost} from "../../util/fetch"; 3import {processRender} from "../util/processCode"; 4import {highlightRender} from "./highlightRender"; 5import {genBreadcrumb, improveBreadcrumbAppearance} from "../wysiwyg/renderBacklink"; 6import {avRender} from "./av/render"; 7import {genRenderFrame} from "./util"; 8 9export const blockRender = (protyle: IProtyle, element: Element, top?: number) => { 10 let blockElements: Element[] = []; 11 if (element.getAttribute("data-type") === "NodeBlockQueryEmbed") { 12 // 编辑器内代码块编辑渲染 13 blockElements = [element]; 14 } else { 15 blockElements = Array.from(element.querySelectorAll('[data-type="NodeBlockQueryEmbed"]')); 16 } 17 if (blockElements.length === 0) { 18 return; 19 } 20 blockElements.forEach((item: HTMLElement) => { 21 if (item.getAttribute("data-render") === "true") { 22 return; 23 } 24 // 需置于请求返回前,否则快速滚动会导致重复加载 https://ld246.com/article/1666857862494?r=88250 25 item.setAttribute("data-render", "true"); 26 genRenderFrame(item); 27 if (item.childElementCount > 3) { 28 item.style.height = (item.clientHeight - 4) + "px"; // 减少抖动 https://ld246.com/article/1668669380171 29 for (let i = 1; i < item.children.length - 1; i++) { 30 if (!item.children[i].classList.contains("protyle-cursor")) { 31 item.children[i].remove(); 32 i--; 33 } 34 } 35 } 36 const content = Lute.UnEscapeHTMLStr(item.getAttribute("data-content")); 37 let breadcrumb: boolean | string = item.getAttribute("breadcrumb"); 38 if (breadcrumb) { 39 breadcrumb = breadcrumb === "true"; 40 } else { 41 breadcrumb = window.siyuan.config.editor.embedBlockBreadcrumb; 42 } 43 44 if (content.startsWith("//!js")) { 45 try { 46 const includeIDs = new Function( 47 "fetchSyncPost", 48 "item", 49 "protyle", 50 "top", 51 content)(fetchSyncPost, item, protyle, top); 52 if (includeIDs instanceof Promise) { 53 includeIDs.then((promiseIds) => { 54 if (Array.isArray(promiseIds)) { 55 fetchPost("/api/search/getEmbedBlock", { 56 embedBlockID: item.getAttribute("data-node-id"), 57 includeIDs: promiseIds, 58 headingMode: ["0", "1", "2"].includes(item.getAttribute("custom-heading-mode")) ? parseInt(item.getAttribute("custom-heading-mode")) : window.siyuan.config.editor.headingEmbedMode, 59 breadcrumb 60 }, (response) => { 61 renderEmbed(response.data.blocks || [], protyle, item, top); 62 }); 63 } else { 64 return; 65 } 66 }).catch((e) => { 67 renderEmbed([], protyle, item, top, e); 68 }); 69 } else if (Array.isArray(includeIDs)) { 70 fetchPost("/api/search/getEmbedBlock", { 71 embedBlockID: item.getAttribute("data-node-id"), 72 includeIDs, 73 headingMode: ["0", "1", "2"].includes(item.getAttribute("custom-heading-mode")) ? parseInt(item.getAttribute("custom-heading-mode")) : window.siyuan.config.editor.headingEmbedMode, 74 breadcrumb 75 }, (response) => { 76 renderEmbed(response.data.blocks || [], protyle, item, top); 77 }); 78 } else { 79 return; 80 } 81 } catch (e) { 82 renderEmbed([], protyle, item, top, e); 83 } 84 } else { 85 fetchPost("/api/search/searchEmbedBlock", { 86 embedBlockID: item.getAttribute("data-node-id"), 87 stmt: content, 88 headingMode: ["0", "1", "2"].includes(item.getAttribute("custom-heading-mode")) ? parseInt(item.getAttribute("custom-heading-mode")) : window.siyuan.config.editor.headingEmbedMode, 89 excludeIDs: [item.getAttribute("data-node-id"), protyle.block.rootID], 90 breadcrumb 91 }, (response) => { 92 renderEmbed(response.data.blocks, protyle, item, top); 93 }); 94 } 95 }); 96}; 97 98const renderEmbed = (blocks: { 99 block: IBlock, 100 blockPaths: IBreadcrumb[] 101}[], protyle: IProtyle, item: HTMLElement, top?: number, errorTip?: string) => { 102 const rotateElement = item.querySelector(".fn__rotate"); 103 if (rotateElement) { 104 rotateElement.classList.remove("fn__rotate"); 105 } 106 let html = ""; 107 blocks.forEach((blocksItem) => { 108 let breadcrumbHTML = ""; 109 if (blocksItem.blockPaths.length !== 0) { 110 breadcrumbHTML = genBreadcrumb(blocksItem.blockPaths, true); 111 } 112 html += `<div class="protyle-wysiwyg__embed" data-id="${blocksItem.block.id}">${breadcrumbHTML}${blocksItem.block.content}</div>`; 113 }); 114 if (blocks.length > 0) { 115 item.firstElementChild.insertAdjacentHTML("afterend", html); 116 improveBreadcrumbAppearance(item.querySelector(".protyle-wysiwyg__embed")); 117 } else { 118 item.firstElementChild.insertAdjacentHTML("afterend", `<div class="protyle-wysiwyg__embed ft__smaller ft__secondary b3-form__space--small" contenteditable="false">${errorTip || window.siyuan.languages.refExpired}</div>`); 119 } 120 121 processRender(item); 122 highlightRender(item); 123 avRender(item, protyle); 124 if (top) { 125 // 前进后退定位 https://ld246.com/article/1667652729995 126 protyle.contentElement.scrollTop = top; 127 } 128 let maxDeep = 0; 129 let deepEmbedElement: false | HTMLElement = item; 130 while (maxDeep < 4 && deepEmbedElement) { 131 deepEmbedElement = hasClosestByAttribute(deepEmbedElement.parentElement, "data-type", "NodeBlockQueryEmbed"); 132 maxDeep++; 133 } 134 if (maxDeep < 4) { 135 item.querySelectorAll('[data-type="NodeBlockQueryEmbed"]').forEach(embedElement => { 136 blockRender(protyle, embedElement); 137 }); 138 } 139 item.style.height = ""; 140};