-
Notifications
You must be signed in to change notification settings - Fork 0
/
prefixer.js
144 lines (125 loc) · 3.1 KB
/
prefixer.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
import Browsers from "./browsers.js";
import vendor from "./vendor.js";
import * as utils from "./utils.js";
/**
* Recursively clone objects
*/
function clone(obj, parent) {
let cloned = new obj.constructor();
for (let i of Object.keys(obj || {})) {
let value = obj[i];
if (i === "parent" && typeof value === "object") {
if (parent) {
cloned[i] = parent;
}
} else if (i === "source" || i === null) {
cloned[i] = value;
} else if (Array.isArray(value)) {
cloned[i] = value.map((x) => clone(x, cloned));
} else if (
i !== "_autoprefixerPrefix" &&
i !== "_autoprefixerValues" &&
i !== "proxyCache"
) {
if (typeof value === "object" && value !== null) {
value = clone(value, cloned);
}
cloned[i] = value;
}
}
return cloned;
}
class Prefixer {
/**
* Add hack to selected names
*/
static hack(klass) {
if (!this.hacks) {
this.hacks = {};
}
return klass.names.map((name) => {
this.hacks[name] = klass;
return this.hacks[name];
});
}
/**
* Load hacks for some names
*/
static load(name, prefixes, all) {
let Klass = this.hacks && this.hacks[name];
if (Klass) {
return new Klass(name, prefixes, all);
} else {
return new this(name, prefixes, all);
}
}
/**
* Clone node and clean autprefixer custom caches
*/
static clone(node, overrides) {
let cloned = clone(node);
for (let name in overrides) {
cloned[name] = overrides[name];
}
return cloned;
}
constructor(name, prefixes, all) {
this.prefixes = prefixes;
this.name = name;
this.all = all;
}
/**
* Find prefix in node parents
*/
parentPrefix(node) {
let prefix;
if (typeof node._autoprefixerPrefix !== "undefined") {
prefix = node._autoprefixerPrefix;
} else if (node.type === "decl" && node.prop[0] === "-") {
prefix = vendor.prefix(node.prop);
} else if (node.type === "root") {
prefix = false;
} else if (
node.type === "rule" &&
node.selector.includes(":-") &&
/:(-\w+-)/.test(node.selector)
) {
prefix = node.selector.match(/:(-\w+-)/)[1];
} else if (node.type === "atrule" && node.name[0] === "-") {
prefix = vendor.prefix(node.name);
} else {
prefix = this.parentPrefix(node.parent);
}
if (!Browsers.prefixes().includes(prefix)) {
prefix = false;
}
node._autoprefixerPrefix = prefix;
return node._autoprefixerPrefix;
}
/**
* Clone node with prefixes
*/
process(node, result) {
if (!this.check(node)) {
return undefined;
}
let parent = this.parentPrefix(node);
let prefixes = this.prefixes.filter(
(prefix) => !parent || parent === utils.removeNote(prefix),
);
let added = [];
for (let prefix of prefixes) {
if (this.add(node, prefix, added.concat([prefix]), result)) {
added.push(prefix);
}
}
return added;
}
/**
* Shortcut for Prefixer.clone
*/
clone(node, overrides) {
return Prefixer.clone(node, overrides);
}
}
export default Prefixer;