-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
204 lines (180 loc) · 5.8 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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
var postcss = require( 'postcss' );
module.exports = postcss.plugin( 'postcss-random', function ( options ) {
return function ( css ) {
/*---------- global vars ----------*/
options = options || {};
// MIN and MAX values
var limitValues = {
min : 0,
max : 1,
};
// arguments passed to random()
var funcArguments;
// final value which replace the random() function
var newValue = 0;
// options passed as the third argument
var randomOptions = {
randomSeed : options['randomSeed'] || null,
round : Boolean(options['round']) || false,
noSeed : Boolean(options['noSeed']) || false,
floatingPoint : parseInt(options['floatingPoint']) || 5,
};
// warning messages
var warnings = {
invalidArguments : 'postcss-random requires a total count of 0, 2 or 3 arguments',
invalidOptionsFormat : 'Invalid options object format',
invalidFloatingPoint : 'Invalid floating point',
};
/*---------- global functions ----------*/
function setDefaultRandomOptions(){
randomOptions.round = Boolean(options['round']) || false;
randomOptions.noSeed = Boolean(options['noSeed']) || false;
randomOptions.floatingPoint = parseInt(options['floatingPoint']) || 5;
}
// essential random function, returns value depending on setted randomOptions
function getRandom(){
var randomGenerator = seedRandom;
if( randomOptions.noSeed ){
randomGenerator = simpleRandom;
}
// get random
var returnValue = randomGenerator( limitValues.max, limitValues.min );
// apply floating point correction
returnValue = returnValue.toFixed( randomOptions.floatingPoint );
// round if necessary
if( randomOptions.round ){
returnValue = Math.round( returnValue );
}
return returnValue;
}
// return simple random value, no seeding
function simpleRandom( max, min ){
max = max || 1;
min = min || 0;
var rnd = Math.random();
return min + rnd * (max - min);
}
// return seeded random
function seedRandom( max, min ) {
max = max || 1;
min = min || 0;
randomOptions.randomSeed = ( randomOptions.randomSeed * 9301 + 49297 ) % 233280;
var rnd = randomOptions.randomSeed / 233280;
return min + rnd * ( max - min );
}
// update limits
function setLimitValues() {
limitValues.min = parseInt( funcArguments[ 0 ] || 0 );
limitValues.max = parseInt( funcArguments[ 1 ] || 1 );
}
// set random options
function setOptions( argument ){
var customOptions;
// parse options, warn if invalid
try{
eval( 'customOptions =' + argument );
}catch( e ){
console.warn( warnings.invalidOptionsFormat, argument );
return;
}
// apply custom options to random options
for(var name in customOptions){
randomOptions[name] = customOptions[name];
}
// correct invalif floating point values
if( randomOptions.floatingPoint < 0 || isNaN(randomOptions.floatingPoint) ){
console.warn( warnings.invalidFloatingPoint, randomOptions.floatingPoint );
return;
}
}
// walk rules
css.walkRules( function ( rule ) {
// walk declarations
rule.walkDecls( function ( decl ) {
// reset default options
setDefaultRandomOptions();
var property = decl.prop;
var value = decl.value;
// if randomSeed property found, set random seed and return
if ( property === 'randomSeed' ) {
randomOptions.randomSeed = value;
decl.remove();
return;
}
if ( value.indexOf( 'random(' ) !== -1 ) {
// remove whitespace
value = value.replace( /\s/, '' );
// try to get arguments
try {
// first we get the whole random command
var commands = value.match( /random\(([^)]*)\)/g );
// loop over each command instance
for(var i = 0; i < commands.length; i++){
// current command
var curCommand = commands[i];
// minMaxSegment
var minMaxSegment = [];
// command inner
var commandInner = curCommand.match( /random\(([^)]*)\)/ )[ 1 ];
// seccond we replace the part ,{ with a bar
var objectTemp = commandInner.replace(/,\s*{/,'|');
// third we split it in half to seperate min/max and options
var segmentSplit = objectTemp.split('|');
// if length > 2 then there is something wrong
if( segmentSplit.length > 2){
console.warn( warnings.invalidOptionsFormat, commandInner );
return;
}else if( segmentSplit.length === 2){
// set funcArguments based on min & max values as well as options
minMaxSegment = segmentSplit[0];
funcArguments = minMaxSegment.split( ',' );
funcArguments.push( '{' + segmentSplit[1] );
}else{
// set funcArguments based on min & max values
if(segmentSplit[0].indexOf(',') !== -1){
minMaxSegment = segmentSplit[0];
funcArguments = minMaxSegment.split( ',' );
}else{
funcArguments = ['0','1'];
}
}
// set limits
if( funcArguments.length >= 2 ){
setLimitValues();
}
// perform action depending on arguments count
switch ( funcArguments.length ) {
case 0:
newValue = seedRandom();
break;
case 1:
setOptions( funcArguments[ 0 ] );
if( typeof randomOptions !== 'object' ){
console.warn( warnings.invalidOptionsFormat, randomOptions );
return;
}else{
newValue = getRandom();
}
break;
case 2:
newValue = getRandom();
break;
case 3:
setOptions( funcArguments[ 2 ] );
newValue = getRandom();
break;
default:
console.warn( warnings.invalidArguments );
return;
}
// finally replace value with new value
decl.value = decl.value.replace( /random\(([^)]*)\)/, newValue );
}
} catch ( e ) {
console.warn(e);
}
}
} );
} );
};
} );