diff options
author | Kristóf Marussy <kristof@marussy.com> | 2024-02-23 00:23:35 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2024-02-23 19:13:07 +0100 |
commit | c0e3f3774cd471f51d096d4980cf5f8565d13bef (patch) | |
tree | 0f0a2209674f2383d676e2fa9adbb443fcfb0241 /subprojects | |
parent | feat(web): SVG export (diff) | |
download | refinery-c0e3f3774cd471f51d096d4980cf5f8565d13bef.tar.gz refinery-c0e3f3774cd471f51d096d4980cf5f8565d13bef.tar.zst refinery-c0e3f3774cd471f51d096d4980cf5f8565d13bef.zip |
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.
Diffstat (limited to 'subprojects')
-rw-r--r-- | subprojects/frontend/src/graph/GraphTheme.tsx | 30 | ||||
-rw-r--r-- | subprojects/frontend/src/graph/postProcessSVG.ts | 27 |
2 files changed, 40 insertions, 17 deletions
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( | |||
27 | '& text': { | 27 | '& text': { |
28 | fill: stroke, | 28 | fill: stroke, |
29 | }, | 29 | }, |
30 | '& [stroke="black"]': { | 30 | '.edge-line': { |
31 | stroke, | 31 | stroke, |
32 | }, | 32 | }, |
33 | '& [fill="black"]': { | 33 | '.edge-arrow': { |
34 | fill: fill ?? stroke, | 34 | fill: fill ?? stroke, |
35 | }, | 35 | }, |
36 | }, | 36 | }, |
@@ -43,10 +43,8 @@ function createTypeHashStyles(theme: Theme, colorNodes: boolean): CSSObject { | |||
43 | } | 43 | } |
44 | const result: CSSObject = {}; | 44 | const result: CSSObject = {}; |
45 | range(theme.palette.highlight.typeHash.length).forEach((i) => { | 45 | range(theme.palette.highlight.typeHash.length).forEach((i) => { |
46 | result[`.node-typeHash-${i}`] = { | 46 | result[`.node-typeHash-${i} .node-header`] = { |
47 | '& [fill="green"]': { | 47 | fill: theme.palette.highlight.typeHash[i]?.box, |
48 | fill: theme.palette.highlight.typeHash[i]?.box, | ||
49 | }, | ||
50 | }; | 48 | }; |
51 | }); | 49 | }); |
52 | return result; | 50 | return result; |
@@ -85,25 +83,23 @@ export function createGraphTheme({ | |||
85 | fontFamily: theme.typography.fontFamily, | 83 | fontFamily: theme.typography.fontFamily, |
86 | fill: theme.palette.text.primary, | 84 | fill: theme.palette.text.primary, |
87 | }, | 85 | }, |
88 | '& [stroke="black"]': { | 86 | '.node-outline': { |
89 | stroke: theme.palette.text.primary, | 87 | stroke: theme.palette.text.primary, |
90 | }, | 88 | }, |
91 | '& [fill="green"]': { | 89 | '.node-header': { |
92 | fill: | 90 | fill: |
93 | theme.palette.mode === 'dark' | 91 | theme.palette.mode === 'dark' |
94 | ? theme.palette.primary.dark | 92 | ? theme.palette.primary.dark |
95 | : theme.palette.primary.light, | 93 | : theme.palette.primary.light, |
96 | }, | 94 | }, |
97 | '& [fill="white"]': { | 95 | '.node-bg': { |
98 | fill: theme.palette.background.default, | 96 | fill: theme.palette.background.default, |
99 | }, | 97 | }, |
100 | }, | 98 | }, |
101 | '.node-INDIVIDUAL': { | 99 | '.node-INDIVIDUAL .node-outline': { |
102 | '& [stroke="black"]': { | 100 | strokeWidth: 2, |
103 | strokeWidth: 2, | ||
104 | }, | ||
105 | }, | 101 | }, |
106 | '.node-shadow[fill="white"]': noEmbedIcons | 102 | '.node-shadow.node-bg': noEmbedIcons |
107 | ? { | 103 | ? { |
108 | // Inkscape can't handle opacity in exported SVG. | 104 | // Inkscape can't handle opacity in exported SVG. |
109 | fill: theme.palette.text.primary, | 105 | fill: theme.palette.text.primary, |
@@ -112,7 +108,7 @@ export function createGraphTheme({ | |||
112 | : { | 108 | : { |
113 | fill: alpha(theme.palette.text.primary, shadowAlapha), | 109 | fill: alpha(theme.palette.text.primary, shadowAlapha), |
114 | }, | 110 | }, |
115 | '.node-exists-UNKNOWN [stroke="black"]': { | 111 | '.node-exists-UNKNOWN .node-outline': { |
116 | strokeDasharray: '5 2', | 112 | strokeDasharray: '5 2', |
117 | }, | 113 | }, |
118 | ...createTypeHashStyles(theme, colorNodes), | 114 | ...createTypeHashStyles(theme, colorNodes), |
@@ -121,10 +117,10 @@ export function createGraphTheme({ | |||
121 | fontFamily: theme.typography.fontFamily, | 117 | fontFamily: theme.typography.fontFamily, |
122 | fill: theme.palette.text.primary, | 118 | fill: theme.palette.text.primary, |
123 | }, | 119 | }, |
124 | '& [stroke="black"]': { | 120 | '.edge-line': { |
125 | stroke: theme.palette.text.primary, | 121 | stroke: theme.palette.text.primary, |
126 | }, | 122 | }, |
127 | '& [fill="black"]': { | 123 | '.edge-arrow': { |
128 | fill: theme.palette.text.primary, | 124 | fill: theme.palette.text.primary, |
129 | }, | 125 | }, |
130 | }, | 126 | }, |
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) { | |||
166 | }); | 166 | }); |
167 | } | 167 | } |
168 | 168 | ||
169 | function markerColorToClass(svg: SVGSVGElement) { | ||
170 | svg.querySelectorAll('.node [stroke="black"]').forEach((node) => { | ||
171 | node.removeAttribute('stroke'); | ||
172 | node.classList.add('node-outline'); | ||
173 | }); | ||
174 | svg.querySelectorAll('.node [fill="green"]').forEach((node) => { | ||
175 | node.removeAttribute('fill'); | ||
176 | node.classList.add('node-header'); | ||
177 | }); | ||
178 | svg.querySelectorAll('.node [fill="white"]').forEach((node) => { | ||
179 | node.removeAttribute('fill'); | ||
180 | node.classList.add('node-bg'); | ||
181 | }); | ||
182 | svg.querySelectorAll('.edge [stroke="black"]').forEach((node) => { | ||
183 | node.removeAttribute('stroke'); | ||
184 | node.classList.add('edge-line'); | ||
185 | }); | ||
186 | svg.querySelectorAll('.edge [fill="black"]').forEach((node) => { | ||
187 | node.removeAttribute('fill'); | ||
188 | node.classList.add('edge-arrow'); | ||
189 | }); | ||
190 | svg.querySelectorAll('[font-family]').forEach((node) => { | ||
191 | node.removeAttribute('font-family'); | ||
192 | }); | ||
193 | } | ||
194 | |||
169 | export default function postProcessSvg(svg: SVGSVGElement) { | 195 | export default function postProcessSvg(svg: SVGSVGElement) { |
170 | // svg | 196 | // svg |
171 | // .querySelectorAll<SVGTitleElement>('title') | 197 | // .querySelectorAll<SVGTitleElement>('title') |
@@ -183,4 +209,5 @@ export default function postProcessSvg(svg: SVGSVGElement) { | |||
183 | svg.viewBox.baseVal.height + 12, | 209 | svg.viewBox.baseVal.height + 12, |
184 | ]; | 210 | ]; |
185 | svg.setAttribute('viewBox', viewBox.join(' ')); | 211 | svg.setAttribute('viewBox', viewBox.join(' ')); |
212 | markerColorToClass(svg); | ||
186 | } | 213 | } |