mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	fix(mermaid): fix export to PNG for some diagram types
This commit is contained in:
		
							
								
								
									
										22
									
								
								src/public/app/services/utils.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/public/app/services/utils.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | import { describe, expect, it } from "vitest"; | ||||||
|  | import { getSizeFromSvg } from "./utils.js"; | ||||||
|  |  | ||||||
|  | describe("getSizeFromSvg", () => { | ||||||
|  |     it("parses width & height attribute", () => { | ||||||
|  |         const svg = `<svg aria-roledescription="sequence" role="graphics-document document" viewBox="-50 -10 714 574" height="574" xmlns="http://www.w3.org/2000/svg" width="714" id="mermaid-graph-2"></svg>`; | ||||||
|  |         const result = getSizeFromSvg(svg); | ||||||
|  |         expect(result).toMatchObject({ | ||||||
|  |             width: 714, | ||||||
|  |             height: 574, | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it("parses viewbox", () => { | ||||||
|  |         const svg = `<svg aria-roledescription="er" role="graphics-document document" viewBox="0 0 872.2750244140625 655" style="max-width: 872.2750244140625px;" class="erDiagram" xmlns="http://www.w3.org/2000/svg" width="100%" id="mermaid-graph-2">`; | ||||||
|  |         const result = getSizeFromSvg(svg); | ||||||
|  |         expect(result).toMatchObject({ | ||||||
|  |             width: 872.2750244140625, | ||||||
|  |             height: 655 | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
| @@ -2,6 +2,8 @@ import dayjs from "dayjs"; | |||||||
| import { Modal } from "bootstrap"; | import { Modal } from "bootstrap"; | ||||||
| import type { ViewScope } from "./link.js"; | import type { ViewScope } from "./link.js"; | ||||||
|  |  | ||||||
|  | const SVG_MIME = "image/svg+xml"; | ||||||
|  |  | ||||||
| function reloadFrontendApp(reason?: string) { | function reloadFrontendApp(reason?: string) { | ||||||
|     if (reason) { |     if (reason) { | ||||||
|         logInfo(`Frontend app reload: ${reason}`); |         logInfo(`Frontend app reload: ${reason}`); | ||||||
| @@ -654,27 +656,23 @@ function triggerDownload(fileName: string, dataUrl: string) { | |||||||
|  */ |  */ | ||||||
| function downloadSvgAsPng(nameWithoutExtension: string, svgContent: string) { | function downloadSvgAsPng(nameWithoutExtension: string, svgContent: string) { | ||||||
|     return new Promise<void>((resolve, reject) => { |     return new Promise<void>((resolve, reject) => { | ||||||
|         const mime = "image/svg+xml"; |  | ||||||
|  |  | ||||||
|         // First, we need to determine the width and the height from the input SVG. |         // First, we need to determine the width and the height from the input SVG. | ||||||
|         const svgDocument = (new DOMParser()).parseFromString(svgContent, mime); |         const result = getSizeFromSvg(svgContent); | ||||||
|         const width = svgDocument.documentElement?.getAttribute("width"); |         if (!result) { | ||||||
|         const height = svgDocument.documentElement?.getAttribute("height"); |  | ||||||
|  |  | ||||||
|         if (!width || !height) { |  | ||||||
|             reject(); |             reject(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Convert the image to a blob. |         // Convert the image to a blob. | ||||||
|  |         const { width, height } = result; | ||||||
|         const svgBlob = new Blob([ svgContent ], { |         const svgBlob = new Blob([ svgContent ], { | ||||||
|             type: mime |             type: SVG_MIME | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|         // Create an image element and load the SVG. |         // Create an image element and load the SVG. | ||||||
|         const imageEl = new Image(); |         const imageEl = new Image(); | ||||||
|         imageEl.width = parseFloat(width); |         imageEl.width = width; | ||||||
|         imageEl.height = parseFloat(height); |         imageEl.height = height; | ||||||
|         imageEl.onload = () => { |         imageEl.onload = () => { | ||||||
|             try { |             try { | ||||||
|                 // Draw the image with a canvas. |                 // Draw the image with a canvas. | ||||||
| @@ -704,6 +702,34 @@ function downloadSvgAsPng(nameWithoutExtension: string, svgContent: string) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | export function getSizeFromSvg(svgContent: string) { | ||||||
|  |     const svgDocument = (new DOMParser()).parseFromString(svgContent, SVG_MIME); | ||||||
|  |  | ||||||
|  |     // Try to use width & height attributes if available. | ||||||
|  |     let width = svgDocument.documentElement?.getAttribute("width"); | ||||||
|  |     let height = svgDocument.documentElement?.getAttribute("height"); | ||||||
|  |  | ||||||
|  |     // If not, use the viewbox. | ||||||
|  |     if (!width || !height) { | ||||||
|  |         const viewBox = svgDocument.documentElement?.getAttribute("viewBox"); | ||||||
|  |         if (viewBox) { | ||||||
|  |             const viewBoxParts = viewBox.split(" "); | ||||||
|  |             width = viewBoxParts[2]; | ||||||
|  |             height = viewBoxParts[3]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (width && height) { | ||||||
|  |         return { | ||||||
|  |             width: parseFloat(width), | ||||||
|  |             height: parseFloat(height) | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         console.warn("SVG export error", svgDocument.documentElement); | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Compares two semantic version strings. |  * Compares two semantic version strings. | ||||||
|  * Returns: |  * Returns: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user