-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.js
executable file
·88 lines (74 loc) · 3.06 KB
/
cli.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
#!/usr/bin/env node
'use strict'
import { program } from 'commander'
import fs from "fs"
import path from "path"
import isSvg from 'is-svg'
import { parse } from 'svgson'
import { createSVGWindow } from 'svgdom'
import { SVG, registerWindow } from '@svgdotjs/svg.js'
const getPaths = (node) => {
let paths = []
if (node.name == 'path') {
// push the path id and geometry to paths array
paths.push({id: node.attributes.id, d: node.attributes.d.replaceAll('\n', ' ')})
} else if (node.children && Array.isArray(node.children)) {
// process the paths children recursively
paths.push(...node.children.map(getPaths))
}
return paths
}
const description = `Extract svg paths by id and save them to new svg files.
--ids can be given multiple times or once with multiple values separated by space.`
program
.description(description)
.argument('<input file>', 'svg input file to convert')
.requiredOption('--ids <paths-ids...>', 'path ids to extract, that start with the specified values.')
.option('--ids-only', 'extract specified ids only, no others')
.action(async (inputFile, options) => {
const filePath = path.parse(inputFile)
const file = fs.readFileSync(inputFile)
const fileData = file.toString()
if (!isSvg(fileData)) {
throw 'Invalid SVG'
}
// parse the svg file
const parsedSVG = await parse(fileData)
// get an array of paths
const SVGPaths = getPaths(parsedSVG).flat(Infinity)
// make an object out of our options.ids where we can push filtered paths into
const pathIdGroups = options.ids.reduce((o, key) => ({ ...o, [key]: []}), {})
pathIdGroups.others = []
for (const node of SVGPaths) {
let found = false;
for (const id of options.ids) {
if (node.id.startsWith(id)) {
pathIdGroups[id].push(node)
found = true;
break
}
}
if (!found && !options.idsOnly) {
// if node.id does not start with any provided id, push it to others
pathIdGroups.others.push(node)
}
}
// create a new svg file for each id
for (const [id, nodes] of Object.entries(pathIdGroups)) {
if (nodes.length) {
// create a new svg document
const window = createSVGWindow()
const document = window.document
registerWindow(window, document)
const svg = SVG(document.documentElement).size(parsedSVG.attributes.width, parsedSVG.attributes.height)
// create paths
for (const node of nodes) {
svg.path(node.d).attr({id: node.id})
}
// save svg file
const svgPath = path.join(filePath.dir, filePath.name + '-' + id + filePath.ext)
fs.writeFileSync(svgPath, svg.svg())
}
}
})
program.parse()