Last active
December 10, 2024 06:17
-
-
Save jongalloway/ce88bdde32d01bd94ccb13716a66d271 to your computer and use it in GitHub Desktop.
Mermaid diagrams use non-standard foreignObject and HTML instead of standard SVG. This snippet can be run in a browser console to get most of the way to SVG that can be edited in Inkscape and other SVG editors. More info about the issue this fixes here: https://github.com/mermaid-js/mermaid/issues/2688
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
// Manually set x and y values for text elements since calculation isn't reliable. Set to what works for your theme. | |
const textX = 0; | |
const textY = 17; | |
// Optional feature to insert a white rectangle below the diagram for dark mode visibility | |
const addBackgroundRect = false; | |
// Get the SVG element | |
const svg = document.querySelector('svg'); | |
// Remove the external stylesheet reference | |
const xmlStylesheet = document.querySelector('xml-stylesheet'); | |
if (xmlStylesheet) { | |
xmlStylesheet.remove(); | |
} | |
// Insert a white rectangle below the diagram if the feature is enabled | |
if (addBackgroundRect) { | |
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); | |
rect.setAttribute('x', 0); | |
rect.setAttribute('y', 0); | |
rect.setAttribute('width', '100%'); | |
rect.setAttribute('height', '100%'); | |
rect.setAttribute('fill', 'white'); | |
svg.insertBefore(rect, svg.firstChild); | |
} | |
// Convert foreignObject elements to SVG text elements | |
const foreignObjects = svg.querySelectorAll('foreignObject'); | |
foreignObjects.forEach(foreignObject => { | |
const div = foreignObject.querySelector('div'); | |
if (div) { | |
const span = div.querySelector('span'); | |
const p = div.querySelector('p'); | |
const textContent = span ? span.textContent : (p ? p.textContent : ''); | |
if (textContent) { | |
// Create a new text element | |
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text'); | |
text.setAttribute('x', textX); | |
text.setAttribute('y', textY); | |
// Extract and apply font styles | |
const computedStyle = window.getComputedStyle(div); | |
const fontFamily = computedStyle.fontFamily; | |
const fontSize = computedStyle.fontSize; | |
const fill = computedStyle.color; | |
text.setAttribute('style', `font-family: ${fontFamily}; font-size: ${fontSize}; fill: ${fill};`); | |
text.textContent = textContent; | |
// Replace the foreignObject with the new text element | |
foreignObject.parentNode.replaceChild(text, foreignObject); | |
} | |
} | |
}); | |
// Inline CSS styles | |
const style = svg.querySelector('style'); | |
if (style) { | |
const cssRules = style.sheet.cssRules; | |
for (let rule of cssRules) { | |
const selector = rule.selectorText; | |
const elements = svg.querySelectorAll(selector); | |
elements.forEach(element => { | |
const styleText = rule.style.cssText; | |
const existingStyle = element.getAttribute('style') || ''; | |
element.setAttribute('style', existingStyle + styleText); | |
}); | |
} | |
// Remove the style element | |
style.remove(); | |
} | |
console.log('SVG conversion complete'); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment