forked from FortAwesome/vue-fontawesome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
converter.js
121 lines (108 loc) · 3.1 KB
/
converter.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
import { h } from 'vue'
import humps from 'humps'
/**
* Converts a CSS style into a plain Javascript object.
* @param {String} style The style to converts into a plain Javascript object.
* @returns {Object}
*/
function styleToObject (style) {
return style.split(';')
.map(s => s.trim())
.filter(s => s)
.reduce(
(output, pair) => {
const idx = pair.indexOf(':')
const prop = humps.camelize(pair.slice(0, idx))
const value = pair.slice(idx + 1).trim()
output[prop] = value
return output
},
{}
)
}
/**
* Converts a CSS class list into a plain Javascript object.
* @param {Array<String>} classes The class list to convert.
* @returns {Object}
*/
function classToObject (classes) {
return classes.split(/\s+/)
.reduce(
(output, className) => {
output[className] = true
return output
},
{}
)
}
/**
* Combines collections of style classes into one collection
* @param {Array<String | String[]>} collections The collections to combine.
* @returns {Array<String>}
*/
function combineClassObjects (...collections) {
const finalSet = new Set([])
collections.forEach(set => {
if (Array.isArray(set)) {
finalSet.forEach(className => finalSet.add(className))
} else {
finalSet.add(set)
}
})
return Array.from(finalSet)
}
/**
* Converts a FontAwesome abstract element of an icon into a Vue render function.
* @param {AbstractElement | String} abstractElement The element to convert.
* @param {Object} props The user-defined props.
* @param {Object} attrs The user-defined native HTML attributes.
* @returns {Function | String}
*/
export default function convert (abstractElement, props = {}, attrs = {}) {
// If the abstract element is a string, we'll just return a string render function
if (typeof abstractElement === 'string') {
return abstractElement
}
// Converting abstract element children into Vue render functions, then we'll execute
// them to retrieve VDOM elements
const children = (abstractElement.children || [])
.map(child => convert(child))
.map(renderFn => typeof renderFn === 'string' ? renderFn : renderFn())
// Converting abstract element attributes into valid Vue format
const mixins = Object.keys(abstractElement.attributes || {})
.reduce(
(mixins, key) => {
const value = abstractElement.attributes[key]
switch (key) {
case 'class':
mixins.class = classToObject(value)
break
case 'style':
mixins.style = styleToObject(value)
break
default:
mixins.attrs[key] = value
}
return mixins
},
{
attrs: {},
class: {},
style: {}
}
)
// Now, we'll return the render function of the
const { class: _aClass = {}, style: aStyle = {}, ...otherAttrs } = attrs
return () =>
h(
abstractElement.tag,
{
...props,
class: mixins.class,
style: { ...mixins.style, ...aStyle },
...mixins.attrs,
...otherAttrs
},
children
)
}