-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.js
More file actions
102 lines (85 loc) · 2.29 KB
/
index.js
File metadata and controls
102 lines (85 loc) · 2.29 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
/**
* Module dependencies.
*/
var visit = require('rework-visit');
/**
* Define custom function.
*/
module.exports = function(functions, args) {
if (!functions) throw new Error('functions object required');
return function(style){
var functionMatcher = functionMatcherBuilder(Object.keys(functions).join('|'));
visit(style, function(declarations){
func(declarations, functions, functionMatcher, args);
});
}
};
/**
* Visit declarations and apply functions.
*
* @param {Array} declarations
* @param {Object} functions
* @param {RegExp} functionMatcher
* @param {Boolean} [parseArgs]
* @api private
*/
function func(declarations, functions, functionMatcher, parseArgs) {
if (!declarations) return;
if (false !== parseArgs) parseArgs = true;
declarations.forEach(function(decl){
if ('comment' == decl.type) return;
var generatedFuncs = [], result, generatedFunc;
while (decl.value.match(functionMatcher)) {
decl.value = decl.value.replace(functionMatcher, function(_, name, args){
if (parseArgs) {
args = args.split(/\s*,\s*/).map(strip);
} else {
args = [strip(args)];
}
// Ensure result is string
result = '' + functions[name].apply(decl, args);
// Prevent fall into infinite loop like this:
//
// {
// url: function(path) {
// return 'url(' + '/some/prefix' + path + ')'
// }
// }
//
generatedFunc = {from: name, to: name + getRandomString()};
result = result.replace(functionMatcherBuilder(name), generatedFunc.to + '($2)');
generatedFuncs.push(generatedFunc);
return result;
});
}
generatedFuncs.forEach(function(func) {
decl.value = decl.value.replace(func.to, func.from);
})
});
}
/**
* Build function regexp
*
* @param {String} name
* @api private
*/
function functionMatcherBuilder(name) {
// /(?!\W+)(\w+)\(([^()]+)\)/
return new RegExp("(?!\\W+)(" + name + ")\\(([^\(\)]+)\\)");
}
/**
* get random string
*
* @api private
*/
function getRandomString() {
return Math.random().toString(36).slice(2);
}
/**
* strip quotes from string
* @api private
*/
function strip(str) {
if ('"' == str[0] || "'" == str[0]) return str.slice(1, -1);
return str;
}