From c0e3f3774cd471f51d096d4980cf5f8565d13bef Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Fri, 23 Feb 2024 00:23:35 +0100 Subject: refactor(frontend): cleaner SVG export Make sure svg can process the resulting SVG without changing visuals. In particular, we must not use specific stroke/fill values as CSS selectors, because svgo may change them into hex codes. Instead, we annotate all diagram elements with class names. --- subprojects/frontend/src/graph/GraphTheme.tsx | 30 ++++++++++-------------- subprojects/frontend/src/graph/postProcessSVG.ts | 27 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 17 deletions(-) (limited to 'subprojects/frontend/src') diff --git a/subprojects/frontend/src/graph/GraphTheme.tsx b/subprojects/frontend/src/graph/GraphTheme.tsx index b3f55a35..34954345 100644 --- a/subprojects/frontend/src/graph/GraphTheme.tsx +++ b/subprojects/frontend/src/graph/GraphTheme.tsx @@ -27,10 +27,10 @@ function createEdgeColor( '& text': { fill: stroke, }, - '& [stroke="black"]': { + '.edge-line': { stroke, }, - '& [fill="black"]': { + '.edge-arrow': { fill: fill ?? stroke, }, }, @@ -43,10 +43,8 @@ function createTypeHashStyles(theme: Theme, colorNodes: boolean): CSSObject { } const result: CSSObject = {}; range(theme.palette.highlight.typeHash.length).forEach((i) => { - result[`.node-typeHash-${i}`] = { - '& [fill="green"]': { - fill: theme.palette.highlight.typeHash[i]?.box, - }, + result[`.node-typeHash-${i} .node-header`] = { + fill: theme.palette.highlight.typeHash[i]?.box, }; }); return result; @@ -85,25 +83,23 @@ export function createGraphTheme({ fontFamily: theme.typography.fontFamily, fill: theme.palette.text.primary, }, - '& [stroke="black"]': { + '.node-outline': { stroke: theme.palette.text.primary, }, - '& [fill="green"]': { + '.node-header': { fill: theme.palette.mode === 'dark' ? theme.palette.primary.dark : theme.palette.primary.light, }, - '& [fill="white"]': { + '.node-bg': { fill: theme.palette.background.default, }, }, - '.node-INDIVIDUAL': { - '& [stroke="black"]': { - strokeWidth: 2, - }, + '.node-INDIVIDUAL .node-outline': { + strokeWidth: 2, }, - '.node-shadow[fill="white"]': noEmbedIcons + '.node-shadow.node-bg': noEmbedIcons ? { // Inkscape can't handle opacity in exported SVG. fill: theme.palette.text.primary, @@ -112,7 +108,7 @@ export function createGraphTheme({ : { fill: alpha(theme.palette.text.primary, shadowAlapha), }, - '.node-exists-UNKNOWN [stroke="black"]': { + '.node-exists-UNKNOWN .node-outline': { strokeDasharray: '5 2', }, ...createTypeHashStyles(theme, colorNodes), @@ -121,10 +117,10 @@ export function createGraphTheme({ fontFamily: theme.typography.fontFamily, fill: theme.palette.text.primary, }, - '& [stroke="black"]': { + '.edge-line': { stroke: theme.palette.text.primary, }, - '& [fill="black"]': { + '.edge-arrow': { fill: theme.palette.text.primary, }, }, diff --git a/subprojects/frontend/src/graph/postProcessSVG.ts b/subprojects/frontend/src/graph/postProcessSVG.ts index f434f80b..bf990f3a 100644 --- a/subprojects/frontend/src/graph/postProcessSVG.ts +++ b/subprojects/frontend/src/graph/postProcessSVG.ts @@ -166,6 +166,32 @@ function replaceImages(node: SVGGElement) { }); } +function markerColorToClass(svg: SVGSVGElement) { + svg.querySelectorAll('.node [stroke="black"]').forEach((node) => { + node.removeAttribute('stroke'); + node.classList.add('node-outline'); + }); + svg.querySelectorAll('.node [fill="green"]').forEach((node) => { + node.removeAttribute('fill'); + node.classList.add('node-header'); + }); + svg.querySelectorAll('.node [fill="white"]').forEach((node) => { + node.removeAttribute('fill'); + node.classList.add('node-bg'); + }); + svg.querySelectorAll('.edge [stroke="black"]').forEach((node) => { + node.removeAttribute('stroke'); + node.classList.add('edge-line'); + }); + svg.querySelectorAll('.edge [fill="black"]').forEach((node) => { + node.removeAttribute('fill'); + node.classList.add('edge-arrow'); + }); + svg.querySelectorAll('[font-family]').forEach((node) => { + node.removeAttribute('font-family'); + }); +} + export default function postProcessSvg(svg: SVGSVGElement) { // svg // .querySelectorAll('title') @@ -183,4 +209,5 @@ export default function postProcessSvg(svg: SVGSVGElement) { svg.viewBox.baseVal.height + 12, ]; svg.setAttribute('viewBox', viewBox.join(' ')); + markerColorToClass(svg); } -- cgit v1.2.3-54-g00ecf