From 69987028ae46e5247682301b5f899b5c4a20ccb5 Mon Sep 17 00:00:00 2001 From: Jeffrey Chen <78434827+TCOTC@users.noreply.github.com> Date: Wed, 23 Jul 2025 11:48:09 +0800 Subject: [PATCH] Improve code block line number rendering performance (#15324) * :zap: Improve code block line number rendering performance fix https://github.com/siyuan-note/siyuan/issues/12715 * :zap: Improve code block line number rendering performance * :zap: Improve code block line number rendering performance * Revert ":zap: Improve code block line number rendering performance" This reverts commit 603518f521efd533a2df889922c433f47b433d2e. * Revert ":zap: Improve code block line number rendering performance" This reverts commit b69cef5f8396a07c07f01d29f2a3b665faa6da4f. * :zap: Improve code block line number rendering performance --- app/src/protyle/render/highlightRender.ts | 50 +++++++++++++---------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/app/src/protyle/render/highlightRender.ts b/app/src/protyle/render/highlightRender.ts index dfd3ba675..2b7206e1b 100644 --- a/app/src/protyle/render/highlightRender.ts +++ b/app/src/protyle/render/highlightRender.ts @@ -128,43 +128,51 @@ export const lineNumberRender = (block: HTMLElement, zoom = 1) => { block.parentElement.style.lineHeight = `${((parseInt(block.parentElement.style.fontSize) || window.siyuan.config.editor.fontSize) * 1.625 * 0.85).toFixed(0)}px`; const codeElement = block.lastElementChild as HTMLElement; - let lineNumberHTML = ""; const lineList = codeElement.textContent.split(/\r\n|\r|\n|\u2028|\u2029/g); if (lineList[lineList.length - 1] === "" && lineList.length > 1) { lineList.pop(); } - block.firstElementChild.innerHTML = `${lineList.length}`; - codeElement.style.paddingLeft = `${block.firstElementChild.clientWidth + 16}px`; - const lineNumberTemp = document.createElement("div"); - lineNumberTemp.className = "hljs"; - // 不能使用 codeElement.clientWidth,被忽略小数点导致宽度不一致 - lineNumberTemp.setAttribute("style", `padding-left:${codeElement.style.paddingLeft}; + let lineNumberHTML = ""; + if (codeElement.style.wordBreak === "break-word") { + // 代码块开启了换行 + const codeElementStyle = window.getComputedStyle(codeElement); + const lineNumberTemp = document.createElement("div"); + lineNumberTemp.className = "hljs"; + // 不能使用 codeElement.clientWidth,被忽略小数点导致宽度不一致 + lineNumberTemp.setAttribute("style", `padding-left:${codeElement.style.paddingLeft}; width: ${codeElement.getBoundingClientRect().width / zoom}px; -white-space:${codeElement.style.whiteSpace}; -word-break:${codeElement.style.wordBreak}; -font-variant-ligatures:${codeElement.style.fontVariantLigatures}; +white-space:${codeElementStyle.whiteSpace}; +word-break:${codeElementStyle.wordBreak}; +font-variant-ligatures:${codeElementStyle.fontVariantLigatures}; padding-right:0;max-height: none;box-sizing: border-box;position: absolute;padding-top:0 !important;padding-bottom:0 !important;min-height:auto !important;`); - lineNumberTemp.setAttribute("contenteditable", "true"); - block.insertAdjacentElement("afterend", lineNumberTemp); + lineNumberTemp.setAttribute("contenteditable", "true"); + block.insertAdjacentElement("afterend", lineNumberTemp); - const isWrap = codeElement.style.wordBreak === "break-word"; - lineList.map((line) => { - let lineHeight = ""; - if (isWrap) { + lineList.map((line) => { // windows 下空格高度为 0 https://github.com/siyuan-note/siyuan/issues/12346 lineNumberTemp.textContent = line.trim() ? line : "
"; // 不能使用 lineNumberTemp.getBoundingClientRect().height.toFixed(1) 否则 // windows 需等待字体下载完成再计算,否则导致不换行,高度计算错误 // https://github.com/siyuan-note/siyuan/issues/9029 // https://github.com/siyuan-note/siyuan/issues/9140 - lineHeight = ` style="height:${lineNumberTemp.clientHeight}px;"`; - } - lineNumberHTML += ``; - }); + lineNumberHTML += ``; + }); + lineNumberTemp.remove(); + } else { + lineNumberHTML = "".repeat(lineList.length); + } - lineNumberTemp.remove(); block.firstElementChild.innerHTML = lineNumberHTML; + + // 用最后一个行号元素计算宽度 + const lastLineNumberElement = block.firstElementChild.lastElementChild as HTMLElement; + if (lastLineNumberElement) { + lastLineNumberElement.textContent = lineList.length.toString(); + codeElement.style.paddingLeft = `${lastLineNumberElement.offsetWidth + 16}px`; + lastLineNumberElement.textContent = ""; + } + // https://github.com/siyuan-note/siyuan/issues/12726 if (block.scrollHeight > block.clientHeight) { if (getSelection().rangeCount > 0) {