fix: make code block height content-aware
Engine CI / test (push) Waiting to run

This commit is contained in:
2026-08-31 20:08:32 +08:00
parent e23fa413be
commit 924b1a15f3
8 changed files with 130 additions and 40 deletions
@@ -927,7 +927,8 @@ function hasExplicitCodeHeight(code: HTMLPreElement) {
function availableCodeHeight(code: HTMLPreElement, region: HTMLElement) {
const layout = code.closest<HTMLElement>('.slidev-layout')
if (!layout || layout.clientHeight <= 0)
const host = code.closest<HTMLElement>('.easy-content-code-host')
if (!layout || !host || layout.clientHeight <= 0)
return 0
const layoutRect = layout.getBoundingClientRect()
const regionRect = region.getBoundingClientRect()
@@ -941,7 +942,33 @@ function availableCodeHeight(code: HTMLPreElement, region: HTMLElement) {
const layoutPaddingBottom = Number.parseFloat(getComputedStyle(layout).paddingBottom) || 0
const regionBottom = regionRect.bottom - regionPaddingBottom * scale
const layoutBottom = layoutRect.bottom - layoutPaddingBottom * scale
return Math.max(0, Math.floor((Math.min(regionBottom, layoutBottom) - codeRect.top) / scale))
const contentBottom = Math.min(regionBottom, layoutBottom)
let trailingBottom = codeRect.bottom
region.querySelectorAll<HTMLElement>('*').forEach((element) => {
if (host.contains(element) || !(host.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_FOLLOWING))
return
const style = getComputedStyle(element)
if (style.display === 'none' || style.position === 'absolute' || style.position === 'fixed')
return
const rect = element.getBoundingClientRect()
if (rect.width <= 0 || rect.height <= 0)
return
const marginBottom = Number.parseFloat(style.marginBottom) || 0
trailingBottom = Math.max(trailingBottom, rect.bottom + marginBottom * scale)
})
const trailingHeight = Math.max(0, trailingBottom - codeRect.bottom)
const codeStyle = getComputedStyle(code)
const minimumHeight = (
(Number.parseFloat(codeStyle.lineHeight) || 0)
+ (Number.parseFloat(codeStyle.paddingTop) || 0)
+ (Number.parseFloat(codeStyle.paddingBottom) || 0)
+ (Number.parseFloat(codeStyle.borderTopWidth) || 0)
+ (Number.parseFloat(codeStyle.borderBottomWidth) || 0)
)
const available = (contentBottom - codeRect.top - trailingHeight) / scale
return Math.max(1, Math.floor(Math.max(minimumHeight, available)))
}
function setHostLength(host: HTMLElement, property: string, value?: number) {
@@ -961,7 +988,6 @@ function fitCodeHeights() {
if (!host)
return
if (hasExplicitCodeHeight(code)) {
setHostLength(host, '--easy-code-auto-height')
setHostLength(host, '--easy-code-auto-max-height')
return
}
@@ -974,7 +1000,6 @@ function fitCodeHeights() {
})
groups.forEach((codes, region) => {
const single = codes.length === 1
codes.forEach((code) => {
const host = code.closest<HTMLElement>('.easy-content-code-host')
if (!host)
@@ -982,7 +1007,6 @@ function fitCodeHeights() {
const available = availableCodeHeight(code, region)
if (!available)
return
setHostLength(host, '--easy-code-auto-height', single ? available : undefined)
setHostLength(host, '--easy-code-auto-max-height', available)
})
})
@@ -1048,7 +1072,6 @@ function cleanupCodeHosts() {
const base = code && codeStyles.get(code)
host.querySelector(':scope > .easy-content-scale-toolbar')?.remove()
host.style.removeProperty('--easy-code-scaled-font-size')
host.style.removeProperty('--easy-code-auto-height')
host.style.removeProperty('--easy-code-auto-max-height')
host.classList.remove('easy-content-scale-host', 'easy-content-code-host')
delete host.dataset.easyScaleKey