forked from robinweser/inline-style-prefixer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreatePrefixer.js
More file actions
135 lines (116 loc) · 4.35 KB
/
createPrefixer.js
File metadata and controls
135 lines (116 loc) · 4.35 KB
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
import getBrowserInformation from '../utils/getBrowserInformation'
import getPrefixedKeyframes from '../utils/getPrefixedKeyframes'
import capitalizeString from '../utils/capitalizeString'
import addNewValuesOnly from '../utils/addNewValuesOnly'
import isObject from '../utils/isObject'
import prefixValue from '../utils/prefixValue'
type DynamicData = {
prefixMap: Object,
plugins: Array<Function>
};
export default function createPrefixer(
{ prefixMap, plugins }: DynamicData,
fallback: ?Function = style => style
) {
return class Prefixer {
/**
* Instantiante a new prefixer
* @param {string} userAgent - userAgent to gather prefix information according to caniuse.com
* @param {string} keepUnprefixed - keeps unprefixed properties and values
*/
constructor(options = {}) {
const defaultUserAgent = typeof navigator !== 'undefined' ? navigator.userAgent : undefined
this._userAgent = options.userAgent || defaultUserAgent
this._keepUnprefixed = options.keepUnprefixed || false
if (this._userAgent) {
this._browserInfo = getBrowserInformation(this._userAgent)
}
// Checks if the userAgent was resolved correctly
if (this._browserInfo && this._browserInfo.cssPrefix) {
this.prefixedKeyframes = getPrefixedKeyframes(
this._browserInfo.browserName,
this._browserInfo.browserVersion,
this._browserInfo.cssPrefix
)
} else {
this._useFallback = true
return false
}
const prefixData = this._browserInfo.browserName && prefixMap[this._browserInfo.browserName]
if (prefixData) {
this._requiresPrefix = {}
for (const property in prefixData) {
if (prefixData[property] >= this._browserInfo.browserVersion) {
this._requiresPrefix[property] = true
}
}
this._hasPropsRequiringPrefix = Object.keys(this._requiresPrefix).length > 0
} else {
this._useFallback = true
}
this._metaData = {
browserVersion: this._browserInfo.browserVersion,
browserName: this._browserInfo.browserName,
cssPrefix: this._browserInfo.cssPrefix,
jsPrefix: this._browserInfo.jsPrefix,
keepUnprefixed: this._keepUnprefixed,
requiresPrefix: this._requiresPrefix
}
}
prefix(style: Object): Object {
// use static prefixer as fallback if userAgent can not be resolved
if (this._useFallback) {
return fallback(style)
}
// only add prefixes if needed
if (!this._hasPropsRequiringPrefix) {
return style
}
return this._prefixStyle(style)
}
_prefixStyle(style: Object): Object {
for (const property in style) {
const value = style[property]
// handle nested objects
if (isObject(value)) {
style[property] = this.prefix(value)
// handle array values
} else if (Array.isArray(value)) {
const combinedValue = []
for (let i = 0, len = value.length; i < len; ++i) {
const processedValue = prefixValue(plugins, property, value[i], style, this._metaData)
addNewValuesOnly(combinedValue, processedValue || value[i])
}
// only modify the value if it was touched
// by any plugin to prevent unnecessary mutations
if (combinedValue.length > 0) {
style[property] = combinedValue
}
} else {
const processedValue = prefixValue(plugins, property, value, style, this._metaData)
// only modify the value if it was touched
// by any plugin to prevent unnecessary mutations
if (processedValue) {
style[property] = processedValue
}
// add prefixes to properties
if (this._requiresPrefix.hasOwnProperty(property)) {
style[this._browserInfo.jsPrefix + capitalizeString(property)] = value
if (!this._keepUnprefixed) {
delete style[property]
}
}
}
}
return style
}
/**
* Returns a prefixed version of the style object using all vendor prefixes
* @param {Object} styles - Style object that gets prefixed properties added
* @returns {Object} - Style object with prefixed properties and values
*/
static prefixAll(styles) {
return fallback(styles)
}
}
}