Fix mermaid diagram height when initially hidden (#32457) (#32464)

Backport #32457 by @silverwind

In a hidden iframe, `document.body.clientHeight` is not reliable. Use
`IntersectionObserver` to detect the visibility change and update the
height there.

Fixes: https://github.com/go-gitea/gitea/issues/32392

<img width="885" alt="image"
src="https://github.com/user-attachments/assets/a95ef6aa-27e7-443f-9d06-400ef27919ae">

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
Giteabot 2024-11-11 04:05:42 +08:00 committed by GitHub
parent 22a93c1cdc
commit 62d8433194
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -56,10 +56,21 @@ export async function renderMermaid() {
btn.setAttribute('data-clipboard-text', source); btn.setAttribute('data-clipboard-text', source);
mermaidBlock.append(btn); mermaidBlock.append(btn);
const updateIframeHeight = () => {
iframe.style.height = `${iframe.contentWindow.document.body.clientHeight}px`;
};
// update height when element's visibility state changes, for example when the diagram is inside
// a <details> + <summary> block and the <details> block becomes visible upon user interaction, it
// would initially set a incorrect height and the correct height is set during this callback.
(new IntersectionObserver(() => {
updateIframeHeight();
}, {root: document.documentElement})).observe(iframe);
iframe.addEventListener('load', () => { iframe.addEventListener('load', () => {
pre.replaceWith(mermaidBlock); pre.replaceWith(mermaidBlock);
mermaidBlock.classList.remove('tw-hidden'); mermaidBlock.classList.remove('tw-hidden');
iframe.style.height = `${iframe.contentWindow.document.body.clientHeight}px`; updateIframeHeight();
setTimeout(() => { // avoid flash of iframe background setTimeout(() => { // avoid flash of iframe background
mermaidBlock.classList.remove('is-loading'); mermaidBlock.classList.remove('is-loading');
iframe.classList.remove('tw-invisible'); iframe.classList.remove('tw-invisible');