ace-rtl.js
8.75 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
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
//simple script to convert styles to RTL
//it's not bullet proof or anything and some parts need to be manually treated
//it's because it doesn't convert all rules to RTL, only the parts that are needed will be put in a separate file
//ace-rtl.css and overriden
function makeRTL(css_input) {
function trim(str) {
return str.replace(/^\s+/, '').replace(/\s+$/, '');
}
var defaultify = {
'left': 'auto',
'right': 'auto',
'padding-right': 0,
'padding-left': 0,
'margin-right': 'auto',
'margin-left': 'auto',
'border-left-color': 'transparent',
'border-right-color': 'transparent',
'border-left-width': 'transparent',
'border-right-width': 'transparent',
'border-left-style': 'none',
'border-right-style': 'none',
'border-left': 'none',
'border-right': 'none',
'-moz-border-left-colors': 'none',
'-moz-border-right-colors': 'none',
'border-bottom-right-radius': 0,
'border-bottom-left-radius': 0,
'border-top-right-radius': 0,
'border-top-left-radius': 0
};
function splitted_values(rule, value) {
value = value.replace(/\!important/g, '');
if(rule.match(/border-color/i) && value.match(/rgb/i)) {
//remove extra spaces in border-color
value = trim(value).replace(/\s\s+/g, ' ').replace(/\s*([\(,])\s*/g, '$1')
}
var part = trim(value).split(/\s+/);
if(part.length >= 4) {
//if(part[3] == part[1]) return null;
//swap left & right value
if(rule.match(/border-radius/i)) return [part[1], part[0], part[3], part[2]].join(' ');
return [part[0], part[3], part[2], part[1]].join(' ');
}
//if(rule.match(/margin/i)) return part.join(' ');//if we return null, cases like [.rtl ul]'s margin will override that of [.nav-list], so we should have [.rtl .nav-list]'s margin again for safe measures
return null;
}
//first remove all comments
var selector_regex = /((?:\s*@media\s*[^\{\}]*)?(?:\s*@(?:-(?:moz|webkit|ms|o|khtml)-)?keyframes\s*[^\{\}]*)?(?:\s*[^\{\}]*))(\{)/ig
var lastCloseBracket = 100000000, media_wrap = false, media_selector = '', pre_media_length = 0;
var rtl_output = "";
var content = css_input.replace(/\/\*[^*]*\*+([^/*][^*]*\*+)*\//ig , '');//remove comments
var result;
while ((result = selector_regex.exec(content)) !== null) {
//we optimistically suppose that no '}' character is inside CSS values such as content:"}" or url('}.jpg')
var index = result.index;
if(media_wrap && index > lastCloseBracket) {
//we have reached end of a @media or @keyframe
if(rtl_output.length > pre_media_length)
rtl_output = rtl_output.substr(0, pre_media_length) + "\n" + trim(media_selector) + " {\n" + rtl_output.substr(pre_media_length) + "}\n";
media_selector = '';
media_wrap = false;
}
var end = content.indexOf('}', selector_regex.lastIndex);
lastCloseBracket = content.indexOf('}', end + 1);
var selector = result[1];
if(selector.match(/@media/i) || selector.match(/@(?:-(?:moz|webkit|ms|o|khtml)-)?keyframes/i)) {
media_selector = selector;
media_wrap = true;
pre_media_length = rtl_output.length;
} else {
var selector_parts = selector.split(/\,+/);
var valid_parts = [];
for(var c = 0 ; c < selector_parts.length; c++) {
//ignore selectors that have "-left or -right", because they are already directional
if(selector_parts[c].match(/(?:(?:[_\-\.])(?:left|right))|(?:\.arrowed)|(?:\.input-icon)|(\.rtl)|(\-rtl)|(\.dropdown-menu[^\:])|(\.scroll-)|(\.ace-switch)|(\.lbl)|(\.popover)|(\.table)|(\.ui-slider)|(\.nav-tabs)|(blockquote)|(\.datepicker)|(\.daterangepicker)|(\.dropdown-menu-right)|(\.footer-)|(\.chosen-)|(\.aside)/i)) {
continue;
}
var sel = trim(selector_parts[c]);
if(sel.match(/(?:\.no\-skin)|(?:\.skin\-\d)/)) valid_parts.push('.rtl'+sel);//.rtl.skin-1
else valid_parts.push('.rtl '+sel);//.rtl .selector
}
if(valid_parts.length == 0) continue;
var override_rules = {};
var rules_text = content.substring(selector_regex.lastIndex , end);
var rule_list = rules_text.match(/(?:([\w\*\-%]+)\s*\:\s*([^\;\}]+))/ig);
if(rule_list && rule_list.length > 0) {
for(var r = 0; r < rule_list.length; r++) {
var $rules = rule_list[r].match(/(?:([\w\*\-%]+)\s*\:\s*([^\;\}]+))/i);
var rule = $rules[1].toLowerCase();
var value = $rules[2];
if(rule.match(/(left|right)/i)) {
override_rules[rule] = {type: 1, value: value};
} else if(rule.match(/^(margin|padding|border-color|border-width|border-style|border-radius)$/i)) {
override_rules[rule] = {type: 2, value: value};
} else if(rule.match(/(box-shadow)/) && !value.match(/none/)) {
if(value.match(/^\s*(\d)/)) {
value = value.replace(/^\s*(\d)/ , '-$1');
override_rules[rule] = {type: 0, value: value};
}
else if(value.match(/^\s*(\-)(\d)/)) {
value = value.replace(/^\s*(\-)(\d)/ , '$2');
override_rules[rule] = {type: 0, value: value};
}
}
if(value.match(/(right|left)/i)) {
if(value.match(/right/i)) value = value.replace(/right/i, 'left');
else value = value.replace(/left/i, 'right');
override_rules[rule] = {type: 0, value: value};
}
else if(value.match(/center/i) && rule.match(/text\-align/i)) {
override_rules[rule] = {type: 0, value: value};
}
/**else if(value.match(/none/i) && rule.match(/float/i)) {
override_rules[rule] = {type: 0, value: value};
}*/
else if(value.match(/(rtl|ltr)/i)) {
if(value.match(/rtl/i)) value = value.replace(/rtl/i, 'ltr');
else value = value.replace(/ltr/i, 'rtl');
override_rules[rule] = {type: 0, value: value};
}
else if(value.match(/translateX\(/i)) {
if(value.match(/translateX\(\-(.*)\)/i))
value = value.replace(/translateX\(\-(.*)\)/ig , 'translateX($1)');
else value = value.replace(/translateX\(([^\-]*)\)/ig , 'translateX(-$1)');
override_rules[rule] = {type: 0, value: value};
}
/*else if(value.match(/rotate\(/i)) {
var val = value.replace(/rotate\(.*\)/i , function(text, found) {
console.log(text);
});
}*/
}
for(var rule in override_rules) if(override_rules.hasOwnProperty(rule)) {
var cur_rule = override_rules[rule];
if(cur_rule.type == 1) {
var flip_rule;
if(rule.match(/right/i)) flip_rule = rule.replace(/right/i, 'left');
else flip_rule = rule.replace(/left/i, 'right');
if(!(flip_rule in override_rules)) {
//add a nullify/defaultify value for the opposite side
override_rules[flip_rule] = {type: 0, value: cur_rule.value};
/**if(rule.match(/border-(left|right)$/i)) {
console.log(rule);
delete override_rules[rule];
rule += '-width';//change border-left to border-left-width
if(!(rule in override_rules)) override_rules[rule] = {}
override_rules[rule].value = defaultify[rule] + (cur_rule.value.match(/!important/) ? ' !important' : '');
override_rules[rule].type = 0;
}
else*/ {
override_rules[rule].value = defaultify[rule] + (cur_rule.value.match(/!important/) ? ' !important' : '');
override_rules[rule].type = 0;
}
} else {
//flip_rule is already a rule itself
//swap left & right values unless they are equal, in that case we ignore it!
var tmp1 = override_rules[rule].value;
var tmp2 = override_rules[flip_rule].value;
if(tmp1 === tmp2) {
delete override_rules[rule];
delete override_rules[flip_rule];
continue;
}
var important = tmp2.match(/!important/) || tmp1.match(/!important/);
override_rules[rule].value = tmp2 + (important && !tmp2.match(/!important/) ? ' !important' : '');
override_rules[flip_rule].value = tmp1 + (important && !tmp1.match(/!important/) ? ' !important' : '');
override_rules[flip_rule].type = override_rules[rule].type = 0;
}
} else if(cur_rule.type == 2) {
var new_value = splitted_values(rule, cur_rule.value);
if(new_value != null) {
override_rules[rule].value = new_value + (cur_rule.value.match(/!important/) ? ' !important' : '');
override_rules[rule].type = 0;
}
}
}
var new_rules_text = '';
for(var rule in override_rules) if(override_rules.hasOwnProperty(rule)) {
var new_rule = override_rules[rule];
if(new_rule.type == 0) {
new_rules_text += "\t"+ rule+": "+ new_rule.value +";\n";
}
}
if(new_rules_text.length > 0) {
rtl_output += trim(valid_parts.join(','))+" {\n";
rtl_output += new_rules_text;
rtl_output += "}\n";
}
}
}
}
//if there's a remaining open media query, close it
if(media_wrap) {
if(rtl_output.length > pre_media_length)
rtl_output = rtl_output.substr(0, pre_media_length) + "\n" + trim(media_selector) + " {\n" + rtl_output.substr(pre_media_length) + "}\n";
}
return rtl_output;
}