-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
79 lines (65 loc) · 2.98 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
// Dependencies
const objectPath = require('object-path');
const kindOf = require('kind-of');
// Default options, see README.md
const defaults = {
pattern: /{{\s?([^\s]+?)\s?}}/gi,
commentsOnly: false,
data: {}
};
function postCSSReplace(opts = defaults) {
const options = Object.assign({}, defaults, opts);
// Check validity of provided pattern. If not valid throw TypeError
let regex = null;
if (options.pattern instanceof RegExp) {
regex = options.pattern;
} else if (typeof options.pattern === 'string') {
regex = new RegExp(options.pattern, 'gi');
} else {
throw new TypeError(`Invalid pattern provided. It is expected to be a string or an instance of RegExp. Got: ${kindOf(options.pattern)}`);
}
const replacementArgs = options.data && options.data.replaceAll != null ? [regex, options.data.replaceAll] : [regex, (match, key) => {
const replace = objectPath.get(options.data, key);
if (typeof replace !== 'string') {
return match;
}
return replace;
}];
return {
postcssPlugin: 'postcss-replace',
OnceExit(root) {
root[options.commentsOnly ? 'walkComments' : 'walk']((node) => {
// Before the switch statement was used, we used node.replaceValues(). This lead to
// incorrect behaviour as described in https://github.com/gridonic/postcss-replace/issues/5.
//
// For example: if the CSS contains at-rules like @media, calling replaceValues() would replace
// everything inside the @media { … } statement and since we are walking through *all* nodes, we would
// encounter the nodes from the @media statement again in the next iteration/call of our walk function.
//
// This is why we have refactored the logic of the walk function to use a switch statement in order to do
// the replacement only on the relevant nodes and use the appropriate replacement logic.
//
// This makes adding/handling new cases quite comfortable.
//
// @see http://api.postcss.org/
switch (node.constructor.name) {
case 'Comment':
node.text = node.text.replace(...replacementArgs);
break;
case 'Declaration':
node.prop = node.prop.replace(...replacementArgs);
node.value = node.value.replace(...replacementArgs);
break;
case 'AtRule':
node.params = node.params.replace(...replacementArgs);
break;
case 'Rule':
node.selector = node.selector.replace(...replacementArgs);
break;
}
});
}
}
}
postCSSReplace.postcss = true;
module.exports = postCSSReplace;