From 0f8ee804d674116b086254cfb02d1e63c33b9b23 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 11 Dec 2025 23:24:02 +0100 Subject: [PATCH 1/3] Fix SVG size calulation, only use `style` attribute --- web_src/js/features/imagediff.ts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/web_src/js/features/imagediff.ts b/web_src/js/features/imagediff.ts index 20682f74d966f..558f458bb0df5 100644 --- a/web_src/js/features/imagediff.ts +++ b/web_src/js/features/imagediff.ts @@ -38,14 +38,14 @@ function getDefaultSvgBoundsIfUndefined(text: string, src: string) { return null; } -function createContext(imageAfter: HTMLImageElement, imageBefore: HTMLImageElement) { +function createContext(imageAfter: HTMLImageElement, imageBefore: HTMLImageElement, boundPair: any) { const sizeAfter = { - width: imageAfter?.width || 0, - height: imageAfter?.height || 0, + width: boundPair.after?.width || imageAfter?.width || 0, + height: boundPair.after?.height || imageAfter?.height || 0, }; const sizeBefore = { - width: imageBefore?.width || 0, - height: imageBefore?.height || 0, + width: boundPair.before?.width || imageBefore?.width || 0, + height: boundPair.before?.height || imageBefore?.height || 0, }; const maxSize = { width: Math.max(sizeBefore.width, sizeAfter.width), @@ -92,7 +92,8 @@ class ImageDiff { boundsInfo: containerEl.querySelector('.bounds-info-before'), }]; - await Promise.all(imageInfos.map(async (info) => { + const boundPair: any = {before: null, after: null}; + await Promise.all(imageInfos.map(async (info, index) => { const [success] = await Promise.all(Array.from(info.images, (img) => { return loadElem(img, info.path); })); @@ -102,11 +103,8 @@ class ImageDiff { const resp = await GET(info.path); const text = await resp.text(); const bounds = getDefaultSvgBoundsIfUndefined(text, info.path); + boundPair[index === 0 ? 'after' : 'before'] = bounds; if (bounds) { - for (const el of info.images) { - el.setAttribute('width', String(bounds.width)); - el.setAttribute('height', String(bounds.height)); - } hideElem(info.boundsInfo); } } @@ -115,10 +113,10 @@ class ImageDiff { const imagesAfter = imageInfos[0].images; const imagesBefore = imageInfos[1].images; - this.initSideBySide(createContext(imagesAfter[0], imagesBefore[0])); + this.initSideBySide(createContext(imagesAfter[0], imagesBefore[0], boundPair)); if (imagesAfter.length > 0 && imagesBefore.length > 0) { - this.initSwipe(createContext(imagesAfter[1], imagesBefore[1])); - this.initOverlay(createContext(imagesAfter[2], imagesBefore[2])); + this.initSwipe(createContext(imagesAfter[1], imagesBefore[1], boundPair)); + this.initOverlay(createContext(imagesAfter[2], imagesBefore[2], boundPair)); } queryElemChildren(containerEl, '.image-diff-tabs', (el) => el.classList.remove('is-loading')); } From f98feb1661b6bd3b1c0903ef379c6a603edad71a Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 11 Dec 2025 23:32:20 +0100 Subject: [PATCH 2/3] rename to svgBoundsInfo --- web_src/js/features/imagediff.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/web_src/js/features/imagediff.ts b/web_src/js/features/imagediff.ts index 558f458bb0df5..796a1e784520e 100644 --- a/web_src/js/features/imagediff.ts +++ b/web_src/js/features/imagediff.ts @@ -38,14 +38,14 @@ function getDefaultSvgBoundsIfUndefined(text: string, src: string) { return null; } -function createContext(imageAfter: HTMLImageElement, imageBefore: HTMLImageElement, boundPair: any) { +function createContext(imageAfter: HTMLImageElement, imageBefore: HTMLImageElement, svgBoundsInfo: any) { const sizeAfter = { - width: boundPair.after?.width || imageAfter?.width || 0, - height: boundPair.after?.height || imageAfter?.height || 0, + width: svgBoundsInfo.after?.width || imageAfter?.width || 0, + height: svgBoundsInfo.after?.height || imageAfter?.height || 0, }; const sizeBefore = { - width: boundPair.before?.width || imageBefore?.width || 0, - height: boundPair.before?.height || imageBefore?.height || 0, + width: svgBoundsInfo.before?.width || imageBefore?.width || 0, + height: svgBoundsInfo.before?.height || imageBefore?.height || 0, }; const maxSize = { width: Math.max(sizeBefore.width, sizeAfter.width), @@ -92,7 +92,7 @@ class ImageDiff { boundsInfo: containerEl.querySelector('.bounds-info-before'), }]; - const boundPair: any = {before: null, after: null}; + const svgBoundsInfo: any = {before: null, after: null}; await Promise.all(imageInfos.map(async (info, index) => { const [success] = await Promise.all(Array.from(info.images, (img) => { return loadElem(img, info.path); @@ -103,7 +103,7 @@ class ImageDiff { const resp = await GET(info.path); const text = await resp.text(); const bounds = getDefaultSvgBoundsIfUndefined(text, info.path); - boundPair[index === 0 ? 'after' : 'before'] = bounds; + svgBoundsInfo[index === 0 ? 'after' : 'before'] = bounds; if (bounds) { hideElem(info.boundsInfo); } @@ -113,10 +113,10 @@ class ImageDiff { const imagesAfter = imageInfos[0].images; const imagesBefore = imageInfos[1].images; - this.initSideBySide(createContext(imagesAfter[0], imagesBefore[0], boundPair)); + this.initSideBySide(createContext(imagesAfter[0], imagesBefore[0], svgBoundsInfo)); if (imagesAfter.length > 0 && imagesBefore.length > 0) { - this.initSwipe(createContext(imagesAfter[1], imagesBefore[1], boundPair)); - this.initOverlay(createContext(imagesAfter[2], imagesBefore[2], boundPair)); + this.initSwipe(createContext(imagesAfter[1], imagesBefore[1], svgBoundsInfo)); + this.initOverlay(createContext(imagesAfter[2], imagesBefore[2], svgBoundsInfo)); } queryElemChildren(containerEl, '.image-diff-tabs', (el) => el.classList.remove('is-loading')); } From 41598ad35bb78c6894697a5059df4d09fc241020 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 12 Dec 2025 10:33:26 +0800 Subject: [PATCH 3/3] show mask background for transparent svg files --- web_src/css/base.css | 2 ++ web_src/css/features/imagediff.css | 2 +- web_src/css/repo/file-view.css | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/web_src/css/base.css b/web_src/css/base.css index 3c8dd1a435458..1fde2f444b6da 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -39,6 +39,8 @@ --gap-inline: 0.25rem; /* gap for inline texts and elements, for example: the spaces for sentence with labels, button text, etc */ --gap-block: 0.5rem; /* gap for element blocks, for example: spaces between buttons, menu image & title, header icon & title etc */ + + --background-view-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAG0lEQVQYlWN4+vTpf3SMDTAMBYXYBLFpHgoKAeiOf0SGE9kbAAAAAElFTkSuQmCC") right bottom var(--color-primary-light-7); } @media (min-width: 768px) and (max-width: 1200px) { diff --git a/web_src/css/features/imagediff.css b/web_src/css/features/imagediff.css index ad3165e8d8958..d32a2098caf42 100644 --- a/web_src/css/features/imagediff.css +++ b/web_src/css/features/imagediff.css @@ -13,7 +13,7 @@ .image-diff-container img { border: 1px solid var(--color-primary-light-7); - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAG0lEQVQYlWN4+vTpf3SMDTAMBYXYBLFpHgoKAeiOf0SGE9kbAAAAAElFTkSuQmCC") right bottom var(--color-primary-light-7); + background: var(--background-view-image); } .image-diff-container .before-container { diff --git a/web_src/css/repo/file-view.css b/web_src/css/repo/file-view.css index 907f136afea2b..3f1c42a4a1f0b 100644 --- a/web_src/css/repo/file-view.css +++ b/web_src/css/repo/file-view.css @@ -81,6 +81,7 @@ .view-raw img[src$=".svg" i] { max-height: 600px !important; max-width: 600px !important; + background: var(--background-view-image); } .file-view-render-container {