mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	fix(mermaid): fix export to PNG for some diagram types
This commit is contained in:
		
							parent
							
								
									3cdbc76fff
								
							
						
					
					
						commit
						3d0ec27038
					
				
							
								
								
									
										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 type { ViewScope } from "./link.js"; | ||||
| 
 | ||||
| const SVG_MIME = "image/svg+xml"; | ||||
| 
 | ||||
| function reloadFrontendApp(reason?: string) { | ||||
|     if (reason) { | ||||
|         logInfo(`Frontend app reload: ${reason}`); | ||||
| @ -654,27 +656,23 @@ function triggerDownload(fileName: string, dataUrl: string) { | ||||
|  */ | ||||
| function downloadSvgAsPng(nameWithoutExtension: string, svgContent: string) { | ||||
|     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.
 | ||||
|         const svgDocument = (new DOMParser()).parseFromString(svgContent, mime); | ||||
|         const width = svgDocument.documentElement?.getAttribute("width"); | ||||
|         const height = svgDocument.documentElement?.getAttribute("height"); | ||||
| 
 | ||||
|         if (!width || !height) { | ||||
|         const result = getSizeFromSvg(svgContent); | ||||
|         if (!result) { | ||||
|             reject(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Convert the image to a blob.
 | ||||
|         const { width, height } = result; | ||||
|         const svgBlob = new Blob([ svgContent ], { | ||||
|             type: mime | ||||
|             type: SVG_MIME | ||||
|         }) | ||||
| 
 | ||||
|         // Create an image element and load the SVG.
 | ||||
|         const imageEl = new Image(); | ||||
|         imageEl.width = parseFloat(width); | ||||
|         imageEl.height = parseFloat(height); | ||||
|         imageEl.width = width; | ||||
|         imageEl.height = height; | ||||
|         imageEl.onload = () => { | ||||
|             try { | ||||
|                 // 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. | ||||
|  * Returns: | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran