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) {