-
Notifications
You must be signed in to change notification settings - Fork 0
/
svg_fix.js
150 lines (131 loc) · 3.91 KB
/
svg_fix.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
* Simple fix of the clipPath problem.
*
* Doesn't do much of optimization and UX transforms done in `svg_finalize.js`.
*
* Use for an auto-fix attemp (doesn't work when clipPath has transforms):
* fixCliping(.);
*
* Use for non-standard clipping (a starter point for an Inkscape fix):
* prepareReCliping(.);
*/
const fs = require('fs');
const { JSDOM } = require('jsdom');
const basePath = './img/temp/src';
const destPath = './img/temp/final';
const files = fs.readdirSync(basePath);
const svgFiles = files.filter(file => file.endsWith('.svg'));
svgFiles.forEach(svgFile => {
processSVG(basePath, svgFile);
});
/**
* Main
*/
function processSVG(baseSrcPath, svgFile, baseDstPath = destPath) {
try {
// Paths
const srcPath = baseSrcPath+'/'+svgFile;
const dstPath = baseDstPath+'/'+svgFile;
// Read the content of each SVG file
let content = fs.readFileSync(srcPath, 'utf8');
// DOM
const dom = new JSDOM(content);
const document = dom.window.document;
// make sure we have a problem
if (!document.querySelector('clipPath g')) {
console.log(`NOP ${svgFile}`);
fs.copyFileSync(srcPath, dstPath);
return;
}
// find/create defs
let defs = document.querySelector('defs');
if (!defs) {
const svg = document.querySelector('svg');
defs = document.createElement('defs');
svg.prepend(defs);
}
//move clip to defs (auto-fix)
// fixCliping(document, defs);
//starter point for an Inkscape fix
prepareReCliping(document);
// color
colorMod(document);
// save the modified SVG
saveAsSvg(dstPath, document);
console.log(`Done ${svgFile}`);
} catch (err) {
console.error(`Error processing file ${svgFile}:`, err);
return;
}
}
/**
* Save to a new SVG file.
* @param {String} dstPath For a new SVG.
* @param {Document} document The modfied document.
*/
function saveAsSvg(dstPath, document) {
let content = document.querySelector('svg').outerHTML;
content = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n` + content;
fs.writeFileSync(dstPath, content);
}
/**
* Move clipping to defs and transform it.
*
* @param {Document} document
* @param {HTMLElement} defs
*/
function fixCliping(document, defs) {
// Get clipPath tag and change node name to "g"
const clipPaths = document.querySelectorAll('clipPath');
for (const clipPath of clipPaths) {
const g = document.createElement('g');
g.id = clipPath.id;
// Move all children of clipPath to the new g element
while (clipPath.firstChild) {
g.appendChild(clipPath.firstChild);
}
// Append the new g element to defs and remove the original clipPath element
defs.appendChild(g);
clipPath.remove();
}
}
/**
* Preapre for re-clipping in Inkscape.
*
* When clipPath has transforms inside it might need resize in Inkscape.
* Merge to one path, resize.
*
* @param {Document} document
* @param {HTMLElement} defs
*/
function prepareReCliping(document) {
const svg = document.querySelector('svg');
const clipPaths = document.querySelectorAll('clipPath');
for (const clipPath of clipPaths) {
const g = document.createElement('g');
// g.id = clipPath.id;
g.id = 'post-clipPath-'+clipPath.id;
// Move all children of clipPath to the new g element
const children = clipPath.querySelectorAll(':not(g)');
for (const child of children) {
const indent = document.createTextNode('\n\t');
g.appendChild(indent);
g.appendChild(child);
}
g.appendChild(document.createTextNode('\n'));
// Append to the end
svg.appendChild(g);
clipPath.remove();
}
}
/**
* New colors of tiles.
* @param {Document} document
*/
function colorMod(document) {
// Change fill color of the <use> element
const useElement = document.querySelector('use[xlink\\:href="#state_outline"]');
if (useElement) {
useElement.setAttribute('fill', '#fdf9d2');
}
}