mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-02 13:44:16 +09:00
Backport https://github.com/go-gitea/gitea/pull/40046 Mermaid scales diagrams wider than the markup column down to its width, but the iframe kept the unscaled viewBox height, leaving a large blank area below them. The iframe now uses a CSS `aspect-ratio` capped at the viewBox height. Diagrams that don't scale (`useMaxWidth: false`) keep the fixed height. The cherry-pick conflicted only on the `srcdoc` line, which uses an `html` template on `main` but a plain string on `release/v28`. Fixes: https://github.com/go-gitea/gitea/issues/40045
This commit is contained in:
1 parent
3ed5886066
commit
5be73fa93a
2 files changed
+20
-5
No files matched your search
@@ -6,16 +6,23 @@ test('mermaid diagram in issue', async ({page, request}) => {
|
|||||||
const repoName = `e2e-mermaid-${randomString(8)}`;
|
const repoName = `e2e-mermaid-${randomString(8)}`;
|
||||||
const owner = env.GITEA_TEST_E2E_USER;
|
const owner = env.GITEA_TEST_E2E_USER;
|
||||||
await apiCreateRepo(request, {name: repoName, autoInit: false});
|
await apiCreateRepo(request, {name: repoName, autoInit: false});
|
||||||
const body = '```mermaid\nflowchart LR\n Alpha --> Beta\n Beta --> Gamma\n```\n';
|
const source = 'flowchart TD\n Alpha --> Beta --> Gamma\n Alpha --> Node1 & Node2 & Node3 & Node4 & Node5 & Node6 & Node7 & Node8';
|
||||||
const {index} = await apiCreateIssue(request, {owner, repo: repoName, title: 'mermaid test', body});
|
const {index} = await apiCreateIssue(request, {owner, repo: repoName, title: 'mermaid test', body: `\`\`\`mermaid\n${source}\n\`\`\`\n`});
|
||||||
await page.goto(`/${owner}/${repoName}/issues/${index}`);
|
await page.goto(`/${owner}/${repoName}/issues/${index}`);
|
||||||
|
|
||||||
const svg = page.frameLocator('iframe.markup-content-iframe').locator('svg');
|
const svg = page.frameLocator('iframe.markup-content-iframe').locator('svg');
|
||||||
await expect(svg).toContainText(/Alpha[\s\S]*Beta[\s\S]*Gamma/);
|
await expect(svg).toContainText(/Alpha[\s\S]*Beta[\s\S]*Gamma/);
|
||||||
|
const [iframeWidth, iframeHeight, svgWidth, svgHeight] = await page.locator('iframe.markup-content-iframe').evaluate((iframe: HTMLIFrameElement) => {
|
||||||
|
const iframeRect = iframe.getBoundingClientRect();
|
||||||
|
const svgRect = iframe.contentDocument!.querySelector('svg')!.getBoundingClientRect();
|
||||||
|
return [iframeRect.width, iframeRect.height, svgRect.width, svgRect.height];
|
||||||
|
});
|
||||||
|
expect(svgWidth).toBeCloseTo(iframeWidth, 0);
|
||||||
|
expect(svgHeight).toBeCloseTo(iframeHeight, 0);
|
||||||
|
|
||||||
await svg.hover();
|
await svg.hover();
|
||||||
await page.locator('.code-copy').click();
|
await page.locator('.code-copy').click();
|
||||||
await expect.poll(() => page.evaluate(() => navigator.clipboard.readText())).toBe('flowchart LR\n Alpha --> Beta\n Beta --> Gamma');
|
await expect.poll(() => page.evaluate(() => navigator.clipboard.readText())).toBe(source);
|
||||||
|
|
||||||
await assertNoJsError(page);
|
await assertNoJsError(page);
|
||||||
});
|
});
|
||||||
@@ -111,8 +111,16 @@ export async function initMarkupCodeMermaid(elMarkup: HTMLElement): Promise<void
|
|||||||
const iframe = document.createElement('iframe');
|
const iframe = document.createElement('iframe');
|
||||||
iframe.classList.add('markup-content-iframe', 'tw-invisible');
|
iframe.classList.add('markup-content-iframe', 'tw-invisible');
|
||||||
iframe.srcdoc = '<style>body { margin: 0; overflow: hidden; } #mermaid { display: block; margin: 0 auto; }</style>';
|
iframe.srcdoc = '<style>body { margin: 0; overflow: hidden; } #mermaid { display: block; margin: 0 auto; }</style>';
|
||||||
const viewBoxHeight = svgNode.viewBox.baseVal?.height;
|
const viewBox = svgNode.viewBox.baseVal;
|
||||||
if (viewBoxHeight) iframe.style.height = `${Math.max(Math.ceil(viewBoxHeight), 85)}px`; // min-height keeps the buttons from overlapping
|
if (viewBox?.height) {
|
||||||
|
iframe.style.height = `${Math.ceil(viewBox.height)}px`;
|
||||||
|
iframe.style.minHeight = '85px'; // keeps the buttons from overlapping
|
||||||
|
if (svgNode.getAttribute('width') === '100%') { // svg shrinks to the iframe width, so the height must follow its aspect ratio
|
||||||
|
iframe.style.aspectRatio = `${viewBox.width} / ${viewBox.height}`;
|
||||||
|
iframe.style.maxHeight = iframe.style.height;
|
||||||
|
iframe.style.height = 'auto';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// the iframe will be fully reloaded if its DOM context is changed (e.g.: moved in the DOM tree).
|
// the iframe will be fully reloaded if its DOM context is changed (e.g.: moved in the DOM tree).
|
||||||
// to avoid unnecessary reloading, we should insert the iframe to its final position only once.
|
// to avoid unnecessary reloading, we should insert the iframe to its final position only once.
|
||||||
|
|||||||
Reference in new issue
Block a user