feat(lineNumbers): enhance element metrics by adding marginTop and marginBottom
这个提交包含在:
+15
-4
@@ -20,6 +20,8 @@ interface LineSpanOptions {
|
|||||||
interface ElementMetrics {
|
interface ElementMetrics {
|
||||||
top: number;
|
top: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
marginTop: number;
|
||||||
|
marginBottom: number;
|
||||||
paddingTop: number;
|
paddingTop: number;
|
||||||
lineHeight: number;
|
lineHeight: number;
|
||||||
lines: number;
|
lines: number;
|
||||||
@@ -56,7 +58,7 @@ const isEmptyElement = (element: HTMLElement): boolean => {
|
|||||||
return !element.textContent?.trim();
|
return !element.textContent?.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyleValue = (style: CSSStyleDeclaration, prop: 'paddingTop' | 'paddingBottom' | 'lineHeight' | 'fontSize'): number =>
|
const getStyleValue = (style: CSSStyleDeclaration, prop: 'paddingTop' | 'paddingBottom' | 'lineHeight' | 'fontSize' | 'marginTop' | 'marginBottom'): number =>
|
||||||
parseFloat(style[prop]) || 0;
|
parseFloat(style[prop]) || 0;
|
||||||
|
|
||||||
const getDefaultLineHeight = (element: HTMLElement): number => {
|
const getDefaultLineHeight = (element: HTMLElement): number => {
|
||||||
@@ -70,6 +72,8 @@ const getElementMetrics = (element: HTMLElement, containerRect: DOMRect, default
|
|||||||
const style = getComputedStyle(element);
|
const style = getComputedStyle(element);
|
||||||
const paddingTop = getStyleValue(style, 'paddingTop');
|
const paddingTop = getStyleValue(style, 'paddingTop');
|
||||||
const paddingBottom = getStyleValue(style, 'paddingBottom');
|
const paddingBottom = getStyleValue(style, 'paddingBottom');
|
||||||
|
const marginTop = getStyleValue(style, 'marginTop');
|
||||||
|
const marginBottom = getStyleValue(style, 'marginBottom');
|
||||||
const height = element.offsetHeight;
|
const height = element.offsetHeight;
|
||||||
const contentHeight = height - paddingTop - paddingBottom;
|
const contentHeight = height - paddingTop - paddingBottom;
|
||||||
const isNonText = isNonTextElement(tagName);
|
const isNonText = isNonTextElement(tagName);
|
||||||
@@ -80,6 +84,8 @@ const getElementMetrics = (element: HTMLElement, containerRect: DOMRect, default
|
|||||||
return {
|
return {
|
||||||
top: element.getBoundingClientRect().top - containerRect.top,
|
top: element.getBoundingClientRect().top - containerRect.top,
|
||||||
height,
|
height,
|
||||||
|
marginTop,
|
||||||
|
marginBottom,
|
||||||
paddingTop,
|
paddingTop,
|
||||||
lineHeight: contentHeight / lines,
|
lineHeight: contentHeight / lines,
|
||||||
lines,
|
lines,
|
||||||
@@ -222,18 +228,23 @@ export const postLineNum = (): LineNumbersState => ({
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastBottom > 0 && metrics.top > lastBottom) {
|
// 计算实际的内容起始位置(考虑 margin-top)
|
||||||
|
const contentStart = metrics.top - metrics.marginTop;
|
||||||
|
|
||||||
|
// 只有当间隙足够大时才填充行号
|
||||||
|
if (lastBottom > 0 && contentStart > lastBottom) {
|
||||||
currentLine = appendGapLines({
|
currentLine = appendGapLines({
|
||||||
fragment,
|
fragment,
|
||||||
gapStart: lastBottom,
|
gapStart: lastBottom,
|
||||||
gapEnd: metrics.top,
|
gapEnd: contentStart,
|
||||||
lineHeight: defaultLineHeight,
|
lineHeight: defaultLineHeight,
|
||||||
startLine: currentLine
|
startLine: currentLine
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
currentLine = appendElementLines(fragment, metrics, currentLine);
|
currentLine = appendElementLines(fragment, metrics, currentLine);
|
||||||
lastBottom = metrics.top + metrics.height;
|
// 更新 lastBottom,包含 margin-bottom
|
||||||
|
lastBottom = metrics.top + metrics.height + metrics.marginBottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 派发初始化滚动高亮事件
|
// 派发初始化滚动高亮事件
|
||||||
|
|||||||
在新议题中引用
屏蔽一个用户