-
Notifications
You must be signed in to change notification settings - Fork 6
/
index.js
120 lines (111 loc) · 3.03 KB
/
index.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
const { parse } = require('svgson')
const { renderToStaticMarkup } = require('react-dom/server')
const { createElement: e } = require('react')
const pretty = require('pretty')
const Element = require('./createElement')
const { optimize: optimizeSVG } = require('svgo')
const svgoDefaultConfig = {
plugins: [
{ name: 'removeStyleElement', active: true },
{ name: 'removeScriptElement', active: true },
{ name: 'removeViewBox', active: false },
{ name: 'removeTitle', active: false },
{
name: 'removeAttrs',
params: {
attrs: [
'(class|style)',
'xlink:href',
'aria-labelledby',
'aria-describedby',
'xmlns:xlink',
'data-name',
],
},
},
],
multipass: true,
}
const replaceTag = (icon) => ({ ...icon, name: 'symbol' })
const createIcon = (obj, key) => e(Element, { obj, key })
const createSprite = (icons) => {
return e('svg', { width: 0, height: 0, className: 'hidden' }, icons)
}
const getId = (obj) => obj['data-iconid']
const createRef = (id, className) => {
return e(
'svg',
{ className: className !== '' ? className : null },
e('use', { xlinkHref: `#${id}` })
)
}
const markup = (elem) => renderToStaticMarkup(elem)
const generateSprite = (result, { tidy, className }) => {
const multiResult = Array.isArray(result)
const icons = multiResult
? result.map(replaceTag).map(createIcon)
: createIcon(replaceTag(result))
const refs = multiResult
? result.map(getId).map((id) => createRef(id, className))
: createRef(getId(result), className)
const sprite = createSprite(icons)
const spriteOutput = markup(sprite)
const refsOutput = markup(refs)
const spriteDefs = tidy ? pretty(spriteOutput) : spriteOutput
const spriteRefs = tidy ? pretty(refsOutput) : refsOutput
return {
defs: spriteDefs,
refs: spriteRefs,
}
}
module.exports = async (
input,
{
tidy = false,
optimize = true,
svgoConfig = svgoDefaultConfig,
processId = (n) => `Icon_${n}`,
className = '',
} = {}
) => {
let n = 0
const transformNode = (node) => {
if (Array.isArray(node)) {
return node.map(transformNode)
} else {
if (node.name === 'svg') {
const id = processId(n++)
const { viewBox, width, height, ...extra } = node.attributes
let defViewBox = viewBox || `0 0 ${width} ${height}`
return {
...node,
attributes: {
...extra,
viewBox: defViewBox,
id,
},
'data-iconid': id,
}
}
return node
}
}
let icons = []
let optimized = []
if (optimize) {
try {
for (const icon of input) {
const iconOpt = optimizeSVG(icon, svgoConfig)
optimized.push(iconOpt.data)
}
icons = optimized
} catch (err) {
// console.log({ err })
}
} else {
icons = input
}
icons = icons.join(' ')
const processed = await parse(icons, { transformNode, camelcase: true })
return generateSprite(processed, { tidy, className })
}