1 | 'use strict';
|
---|
2 |
|
---|
3 | /**
|
---|
4 | * Takes an array of [keyValue1, keyValue2] pairs and creates an object of {keyValue1: keyValue2, keyValue2: keyValue1}
|
---|
5 | * @param {Array} array the array of pairs
|
---|
6 | * @return {Object} the {key, value} pair object
|
---|
7 | */
|
---|
8 | function arrayToObject(array) {
|
---|
9 | return array.reduce(function (obj, _ref) {
|
---|
10 | var prop1 = _ref[0],
|
---|
11 | prop2 = _ref[1];
|
---|
12 | obj[prop1] = prop2;
|
---|
13 | obj[prop2] = prop1;
|
---|
14 | return obj;
|
---|
15 | }, {});
|
---|
16 | }
|
---|
17 | function isBoolean(val) {
|
---|
18 | return typeof val === 'boolean';
|
---|
19 | }
|
---|
20 | function isFunction(val) {
|
---|
21 | return typeof val === 'function';
|
---|
22 | }
|
---|
23 | function isNumber(val) {
|
---|
24 | return typeof val === 'number';
|
---|
25 | }
|
---|
26 | function isNullOrUndefined(val) {
|
---|
27 | return val === null || typeof val === 'undefined';
|
---|
28 | }
|
---|
29 | function isObject(val) {
|
---|
30 | return val && typeof val === 'object';
|
---|
31 | }
|
---|
32 | function isString(val) {
|
---|
33 | return typeof val === 'string';
|
---|
34 | }
|
---|
35 | function includes(inclusive, inclusee) {
|
---|
36 | return inclusive.indexOf(inclusee) !== -1;
|
---|
37 | }
|
---|
38 |
|
---|
39 | /**
|
---|
40 | * Flip the sign of a CSS value, possibly with a unit.
|
---|
41 | *
|
---|
42 | * We can't just negate the value with unary minus due to the units.
|
---|
43 | *
|
---|
44 | * @private
|
---|
45 | * @param {String} value - the original value (for example 77%)
|
---|
46 | * @return {String} the result (for example -77%)
|
---|
47 | */
|
---|
48 | function flipSign(value) {
|
---|
49 | if (parseFloat(value) === 0) {
|
---|
50 | // Don't mangle zeroes
|
---|
51 | return value;
|
---|
52 | }
|
---|
53 | if (value[0] === '-') {
|
---|
54 | return value.slice(1);
|
---|
55 | }
|
---|
56 | return "-" + value;
|
---|
57 | }
|
---|
58 | function flipTransformSign(match, prefix, offset, suffix) {
|
---|
59 | return prefix + flipSign(offset) + suffix;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * Takes a percentage for background position and inverts it.
|
---|
64 | * This was copied and modified from CSSJanus:
|
---|
65 | * https://github.com/cssjanus/cssjanus/blob/4245f834365f6cfb0239191a151432fb85abab23/src/cssjanus.js#L152-L175
|
---|
66 | * @param {String} value - the original value (for example 77%)
|
---|
67 | * @return {String} the result (for example 23%)
|
---|
68 | */
|
---|
69 | function calculateNewBackgroundPosition(value) {
|
---|
70 | var idx = value.indexOf('.');
|
---|
71 | if (idx === -1) {
|
---|
72 | value = 100 - parseFloat(value) + "%";
|
---|
73 | } else {
|
---|
74 | // Two off, one for the "%" at the end, one for the dot itself
|
---|
75 | var len = value.length - idx - 2;
|
---|
76 | value = 100 - parseFloat(value);
|
---|
77 | value = value.toFixed(len) + "%";
|
---|
78 | }
|
---|
79 | return value;
|
---|
80 | }
|
---|
81 |
|
---|
82 | /**
|
---|
83 | * This takes a list of CSS values and converts it to an array
|
---|
84 | * @param {String} value - something like `1px`, `1px 2em`, or `3pt rgb(150, 230, 550) 40px calc(100% - 5px)`
|
---|
85 | * @return {Array} the split values (for example: `['3pt', 'rgb(150, 230, 550)', '40px', 'calc(100% - 5px)']`)
|
---|
86 | */
|
---|
87 | function getValuesAsList(value) {
|
---|
88 | return value.replace(/ +/g, ' ') // remove all extraneous spaces
|
---|
89 | .split(' ').map(function (i) {
|
---|
90 | return i.trim();
|
---|
91 | }) // get rid of extra space before/after each item
|
---|
92 | .filter(Boolean) // get rid of empty strings
|
---|
93 | // join items which are within parenthese
|
---|
94 | // luckily `calc (100% - 5px)` is invalid syntax and it must be `calc(100% - 5px)`, otherwise this would be even more complex
|
---|
95 | .reduce(function (_ref2, item) {
|
---|
96 | var list = _ref2.list,
|
---|
97 | state = _ref2.state;
|
---|
98 | var openParansCount = (item.match(/\(/g) || []).length;
|
---|
99 | var closedParansCount = (item.match(/\)/g) || []).length;
|
---|
100 | if (state.parensDepth > 0) {
|
---|
101 | list[list.length - 1] = list[list.length - 1] + " " + item;
|
---|
102 | } else {
|
---|
103 | list.push(item);
|
---|
104 | }
|
---|
105 | state.parensDepth += openParansCount - closedParansCount;
|
---|
106 | return {
|
---|
107 | list: list,
|
---|
108 | state: state
|
---|
109 | };
|
---|
110 | }, {
|
---|
111 | list: [],
|
---|
112 | state: {
|
---|
113 | parensDepth: 0
|
---|
114 | }
|
---|
115 | }).list;
|
---|
116 | }
|
---|
117 |
|
---|
118 | /**
|
---|
119 | * This is intended for properties that are `top right bottom left` and will switch them to `top left bottom right`
|
---|
120 | * @param {String} value - `1px 2px 3px 4px` for example, but also handles cases where there are too few/too many and
|
---|
121 | * simply returns the value in those cases (which is the correct behavior)
|
---|
122 | * @return {String} the result - `1px 4px 3px 2px` for example.
|
---|
123 | */
|
---|
124 | function handleQuartetValues(value) {
|
---|
125 | var splitValues = getValuesAsList(value);
|
---|
126 | if (splitValues.length <= 3 || splitValues.length > 4) {
|
---|
127 | return value;
|
---|
128 | }
|
---|
129 | var top = splitValues[0],
|
---|
130 | right = splitValues[1],
|
---|
131 | bottom = splitValues[2],
|
---|
132 | left = splitValues[3];
|
---|
133 | return [top, left, bottom, right].join(' ');
|
---|
134 | }
|
---|
135 |
|
---|
136 | /**
|
---|
137 | *
|
---|
138 | * @param {String|Number|Object} value css property value to test
|
---|
139 | * @returns If the css property value can(should?) have an RTL equivalent
|
---|
140 | */
|
---|
141 | function canConvertValue(value) {
|
---|
142 | return !isBoolean(value) && !isNullOrUndefined(value);
|
---|
143 | }
|
---|
144 |
|
---|
145 | /**
|
---|
146 | * Splits a shadow style into its separate shadows using the comma delimiter, but creating an exception
|
---|
147 | * for comma separated values in parentheses often used for rgba colours.
|
---|
148 | * @param {String} value
|
---|
149 | * @returns {Array} array of all box shadow values in the string
|
---|
150 | */
|
---|
151 | function splitShadow(value) {
|
---|
152 | var shadows = [];
|
---|
153 | var start = 0;
|
---|
154 | var end = 0;
|
---|
155 | var rgba = false;
|
---|
156 | while (end < value.length) {
|
---|
157 | if (!rgba && value[end] === ',') {
|
---|
158 | shadows.push(value.substring(start, end).trim());
|
---|
159 | end++;
|
---|
160 | start = end;
|
---|
161 | } else if (value[end] === "(") {
|
---|
162 | rgba = true;
|
---|
163 | end++;
|
---|
164 | } else if (value[end] === ')') {
|
---|
165 | rgba = false;
|
---|
166 | end++;
|
---|
167 | } else {
|
---|
168 | end++;
|
---|
169 | }
|
---|
170 | }
|
---|
171 |
|
---|
172 | // push the last shadow value if there is one
|
---|
173 | // istanbul ignore next
|
---|
174 | if (start != end) {
|
---|
175 | shadows.push(value.substring(start, end + 1));
|
---|
176 | }
|
---|
177 | return shadows;
|
---|
178 | }
|
---|
179 |
|
---|
180 | // some values require a little fudging, that fudging goes here.
|
---|
181 | var propertyValueConverters = {
|
---|
182 | padding: function padding(_ref) {
|
---|
183 | var value = _ref.value;
|
---|
184 | if (isNumber(value)) {
|
---|
185 | return value;
|
---|
186 | }
|
---|
187 | return handleQuartetValues(value);
|
---|
188 | },
|
---|
189 | textShadow: function textShadow(_ref2) {
|
---|
190 | var value = _ref2.value;
|
---|
191 | var flippedShadows = splitShadow(value).map(function (shadow) {
|
---|
192 | // intentionally leaving off the `g` flag here because we only want to change the first number (which is the offset-x)
|
---|
193 | return shadow.replace(/(^|\s)(-*)([.|\d]+)/, function (match, whiteSpace, negative, number) {
|
---|
194 | if (number === '0') {
|
---|
195 | return match;
|
---|
196 | }
|
---|
197 | var doubleNegative = negative === '' ? '-' : '';
|
---|
198 | return "" + whiteSpace + doubleNegative + number;
|
---|
199 | });
|
---|
200 | });
|
---|
201 | return flippedShadows.join(',');
|
---|
202 | },
|
---|
203 | borderColor: function borderColor(_ref3) {
|
---|
204 | var value = _ref3.value;
|
---|
205 | return handleQuartetValues(value);
|
---|
206 | },
|
---|
207 | borderRadius: function borderRadius(_ref4) {
|
---|
208 | var value = _ref4.value;
|
---|
209 | if (isNumber(value)) {
|
---|
210 | return value;
|
---|
211 | }
|
---|
212 | if (includes(value, '/')) {
|
---|
213 | var _value$split = value.split('/'),
|
---|
214 | radius1 = _value$split[0],
|
---|
215 | radius2 = _value$split[1];
|
---|
216 | var convertedRadius1 = propertyValueConverters.borderRadius({
|
---|
217 | value: radius1.trim()
|
---|
218 | });
|
---|
219 | var convertedRadius2 = propertyValueConverters.borderRadius({
|
---|
220 | value: radius2.trim()
|
---|
221 | });
|
---|
222 | return convertedRadius1 + " / " + convertedRadius2;
|
---|
223 | }
|
---|
224 | var splitValues = getValuesAsList(value);
|
---|
225 | switch (splitValues.length) {
|
---|
226 | case 2:
|
---|
227 | {
|
---|
228 | return splitValues.reverse().join(' ');
|
---|
229 | }
|
---|
230 | case 4:
|
---|
231 | {
|
---|
232 | var topLeft = splitValues[0],
|
---|
233 | topRight = splitValues[1],
|
---|
234 | bottomRight = splitValues[2],
|
---|
235 | bottomLeft = splitValues[3];
|
---|
236 | return [topRight, topLeft, bottomLeft, bottomRight].join(' ');
|
---|
237 | }
|
---|
238 | default:
|
---|
239 | {
|
---|
240 | return value;
|
---|
241 | }
|
---|
242 | }
|
---|
243 | },
|
---|
244 | background: function background(_ref5) {
|
---|
245 | var value = _ref5.value,
|
---|
246 | valuesToConvert = _ref5.valuesToConvert,
|
---|
247 | isRtl = _ref5.isRtl,
|
---|
248 | bgImgDirectionRegex = _ref5.bgImgDirectionRegex,
|
---|
249 | bgPosDirectionRegex = _ref5.bgPosDirectionRegex;
|
---|
250 | if (isNumber(value)) {
|
---|
251 | return value;
|
---|
252 | }
|
---|
253 |
|
---|
254 | // Yeah, this is in need of a refactor 🙃...
|
---|
255 | // but this property is a tough cookie 🍪
|
---|
256 | // get the backgroundPosition out of the string by removing everything that couldn't be the backgroundPosition value
|
---|
257 | var backgroundPositionValue = value.replace(/(url\(.*?\))|(rgba?\(.*?\))|(hsl\(.*?\))|(#[a-fA-F0-9]+)|((^| )(\D)+( |$))/g, '').trim();
|
---|
258 | // replace that backgroundPosition value with the converted version
|
---|
259 | value = value.replace(backgroundPositionValue, propertyValueConverters.backgroundPosition({
|
---|
260 | value: backgroundPositionValue,
|
---|
261 | valuesToConvert: valuesToConvert,
|
---|
262 | isRtl: isRtl,
|
---|
263 | bgPosDirectionRegex: bgPosDirectionRegex
|
---|
264 | }));
|
---|
265 | // do the backgroundImage value replacing on the whole value (because why not?)
|
---|
266 | return propertyValueConverters.backgroundImage({
|
---|
267 | value: value,
|
---|
268 | valuesToConvert: valuesToConvert,
|
---|
269 | bgImgDirectionRegex: bgImgDirectionRegex
|
---|
270 | });
|
---|
271 | },
|
---|
272 | backgroundImage: function backgroundImage(_ref6) {
|
---|
273 | var value = _ref6.value,
|
---|
274 | valuesToConvert = _ref6.valuesToConvert,
|
---|
275 | bgImgDirectionRegex = _ref6.bgImgDirectionRegex;
|
---|
276 | if (!includes(value, 'url(') && !includes(value, 'linear-gradient(')) {
|
---|
277 | return value;
|
---|
278 | }
|
---|
279 | return value.replace(bgImgDirectionRegex, function (match, g1, group2) {
|
---|
280 | return match.replace(group2, valuesToConvert[group2]);
|
---|
281 | });
|
---|
282 | },
|
---|
283 | backgroundPosition: function backgroundPosition(_ref7) {
|
---|
284 | var value = _ref7.value,
|
---|
285 | valuesToConvert = _ref7.valuesToConvert,
|
---|
286 | isRtl = _ref7.isRtl,
|
---|
287 | bgPosDirectionRegex = _ref7.bgPosDirectionRegex;
|
---|
288 | return value
|
---|
289 | // intentionally only grabbing the first instance of this because that represents `left`
|
---|
290 | .replace(isRtl ? /^((-|\d|\.)+%)/ : null, function (match, group) {
|
---|
291 | return calculateNewBackgroundPosition(group);
|
---|
292 | }).replace(bgPosDirectionRegex, function (match) {
|
---|
293 | return valuesToConvert[match];
|
---|
294 | });
|
---|
295 | },
|
---|
296 | backgroundPositionX: function backgroundPositionX(_ref8) {
|
---|
297 | var value = _ref8.value,
|
---|
298 | valuesToConvert = _ref8.valuesToConvert,
|
---|
299 | isRtl = _ref8.isRtl,
|
---|
300 | bgPosDirectionRegex = _ref8.bgPosDirectionRegex;
|
---|
301 | if (isNumber(value)) {
|
---|
302 | return value;
|
---|
303 | }
|
---|
304 | return propertyValueConverters.backgroundPosition({
|
---|
305 | value: value,
|
---|
306 | valuesToConvert: valuesToConvert,
|
---|
307 | isRtl: isRtl,
|
---|
308 | bgPosDirectionRegex: bgPosDirectionRegex
|
---|
309 | });
|
---|
310 | },
|
---|
311 | transition: function transition(_ref9) {
|
---|
312 | var value = _ref9.value,
|
---|
313 | propertiesToConvert = _ref9.propertiesToConvert;
|
---|
314 | return value.split(/,\s*/g).map(function (transition) {
|
---|
315 | var values = transition.split(' ');
|
---|
316 |
|
---|
317 | // Property is always defined first
|
---|
318 | values[0] = propertiesToConvert[values[0]] || values[0];
|
---|
319 | return values.join(' ');
|
---|
320 | }).join(', ');
|
---|
321 | },
|
---|
322 | transitionProperty: function transitionProperty(_ref10) {
|
---|
323 | var value = _ref10.value,
|
---|
324 | propertiesToConvert = _ref10.propertiesToConvert;
|
---|
325 | return value.split(/,\s*/g).map(function (prop) {
|
---|
326 | return propertiesToConvert[prop] || prop;
|
---|
327 | }).join(', ');
|
---|
328 | },
|
---|
329 | transform: function transform(_ref11) {
|
---|
330 | var value = _ref11.value;
|
---|
331 | // This was copied and modified from CSSJanus:
|
---|
332 | // https://github.com/cssjanus/cssjanus/blob/4a40f001b1ba35567112d8b8e1d9d95eda4234c3/src/cssjanus.js#L152-L153
|
---|
333 | var nonAsciiPattern = "[^\\u0020-\\u007e]";
|
---|
334 | var escapePattern = "(?:" + '(?:(?:\\[0-9a-f]{1,6})(?:\\r\\n|\\s)?)' + "|\\\\[^\\r\\n\\f0-9a-f])";
|
---|
335 | var signedQuantPattern = "((?:-?" + ('(?:[0-9]*\\.[0-9]+|[0-9]+)' + "(?:\\s*" + '(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)' + "|" + ("-?" + ("(?:[_a-z]|" + nonAsciiPattern + "|" + escapePattern + ")") + ("(?:[_a-z0-9-]|" + nonAsciiPattern + "|" + escapePattern + ")") + "*") + ")?") + ")|(?:inherit|auto))";
|
---|
336 | var translateXRegExp = new RegExp("(translateX\\s*\\(\\s*)" + signedQuantPattern + "(\\s*\\))", 'gi');
|
---|
337 | var translateRegExp = new RegExp("(translate\\s*\\(\\s*)" + signedQuantPattern + "((?:\\s*,\\s*" + signedQuantPattern + "){0,1}\\s*\\))", 'gi');
|
---|
338 | var translate3dRegExp = new RegExp("(translate3d\\s*\\(\\s*)" + signedQuantPattern + "((?:\\s*,\\s*" + signedQuantPattern + "){0,2}\\s*\\))", 'gi');
|
---|
339 | var rotateRegExp = new RegExp("(rotate[ZY]?\\s*\\(\\s*)" + signedQuantPattern + "(\\s*\\))", 'gi');
|
---|
340 | return value.replace(translateXRegExp, flipTransformSign).replace(translateRegExp, flipTransformSign).replace(translate3dRegExp, flipTransformSign).replace(rotateRegExp, flipTransformSign);
|
---|
341 | }
|
---|
342 | };
|
---|
343 | propertyValueConverters.objectPosition = propertyValueConverters.backgroundPosition;
|
---|
344 | propertyValueConverters.margin = propertyValueConverters.padding;
|
---|
345 | propertyValueConverters.borderWidth = propertyValueConverters.padding;
|
---|
346 | propertyValueConverters.boxShadow = propertyValueConverters.textShadow;
|
---|
347 | propertyValueConverters.webkitBoxShadow = propertyValueConverters.boxShadow;
|
---|
348 | propertyValueConverters.mozBoxShadow = propertyValueConverters.boxShadow;
|
---|
349 | propertyValueConverters.WebkitBoxShadow = propertyValueConverters.boxShadow;
|
---|
350 | propertyValueConverters.MozBoxShadow = propertyValueConverters.boxShadow;
|
---|
351 | propertyValueConverters.borderStyle = propertyValueConverters.borderColor;
|
---|
352 | propertyValueConverters.webkitTransform = propertyValueConverters.transform;
|
---|
353 | propertyValueConverters.mozTransform = propertyValueConverters.transform;
|
---|
354 | propertyValueConverters.WebkitTransform = propertyValueConverters.transform;
|
---|
355 | propertyValueConverters.MozTransform = propertyValueConverters.transform;
|
---|
356 | propertyValueConverters.transformOrigin = propertyValueConverters.backgroundPosition;
|
---|
357 | propertyValueConverters.webkitTransformOrigin = propertyValueConverters.transformOrigin;
|
---|
358 | propertyValueConverters.mozTransformOrigin = propertyValueConverters.transformOrigin;
|
---|
359 | propertyValueConverters.WebkitTransformOrigin = propertyValueConverters.transformOrigin;
|
---|
360 | propertyValueConverters.MozTransformOrigin = propertyValueConverters.transformOrigin;
|
---|
361 | propertyValueConverters.webkitTransition = propertyValueConverters.transition;
|
---|
362 | propertyValueConverters.mozTransition = propertyValueConverters.transition;
|
---|
363 | propertyValueConverters.WebkitTransition = propertyValueConverters.transition;
|
---|
364 | propertyValueConverters.MozTransition = propertyValueConverters.transition;
|
---|
365 | propertyValueConverters.webkitTransitionProperty = propertyValueConverters.transitionProperty;
|
---|
366 | propertyValueConverters.mozTransitionProperty = propertyValueConverters.transitionProperty;
|
---|
367 | propertyValueConverters.WebkitTransitionProperty = propertyValueConverters.transitionProperty;
|
---|
368 | propertyValueConverters.MozTransitionProperty = propertyValueConverters.transitionProperty;
|
---|
369 |
|
---|
370 | // kebab-case versions
|
---|
371 |
|
---|
372 | propertyValueConverters['text-shadow'] = propertyValueConverters.textShadow;
|
---|
373 | propertyValueConverters['border-color'] = propertyValueConverters.borderColor;
|
---|
374 | propertyValueConverters['border-radius'] = propertyValueConverters.borderRadius;
|
---|
375 | propertyValueConverters['background-image'] = propertyValueConverters.backgroundImage;
|
---|
376 | propertyValueConverters['background-position'] = propertyValueConverters.backgroundPosition;
|
---|
377 | propertyValueConverters['background-position-x'] = propertyValueConverters.backgroundPositionX;
|
---|
378 | propertyValueConverters['object-position'] = propertyValueConverters.objectPosition;
|
---|
379 | propertyValueConverters['border-width'] = propertyValueConverters.padding;
|
---|
380 | propertyValueConverters['box-shadow'] = propertyValueConverters.textShadow;
|
---|
381 | propertyValueConverters['-webkit-box-shadow'] = propertyValueConverters.textShadow;
|
---|
382 | propertyValueConverters['-moz-box-shadow'] = propertyValueConverters.textShadow;
|
---|
383 | propertyValueConverters['border-style'] = propertyValueConverters.borderColor;
|
---|
384 | propertyValueConverters['-webkit-transform'] = propertyValueConverters.transform;
|
---|
385 | propertyValueConverters['-moz-transform'] = propertyValueConverters.transform;
|
---|
386 | propertyValueConverters['transform-origin'] = propertyValueConverters.transformOrigin;
|
---|
387 | propertyValueConverters['-webkit-transform-origin'] = propertyValueConverters.transformOrigin;
|
---|
388 | propertyValueConverters['-moz-transform-origin'] = propertyValueConverters.transformOrigin;
|
---|
389 | propertyValueConverters['-webkit-transition'] = propertyValueConverters.transition;
|
---|
390 | propertyValueConverters['-moz-transition'] = propertyValueConverters.transition;
|
---|
391 | propertyValueConverters['transition-property'] = propertyValueConverters.transitionProperty;
|
---|
392 | propertyValueConverters['-webkit-transition-property'] = propertyValueConverters.transitionProperty;
|
---|
393 | propertyValueConverters['-moz-transition-property'] = propertyValueConverters.transitionProperty;
|
---|
394 |
|
---|
395 | // this will be an object of properties that map to their corresponding rtl property (their doppelganger)
|
---|
396 | var propertiesToConvert = arrayToObject([['paddingLeft', 'paddingRight'], ['marginLeft', 'marginRight'], ['left', 'right'], ['borderLeft', 'borderRight'], ['borderLeftColor', 'borderRightColor'], ['borderLeftStyle', 'borderRightStyle'], ['borderLeftWidth', 'borderRightWidth'], ['borderTopLeftRadius', 'borderTopRightRadius'], ['borderBottomLeftRadius', 'borderBottomRightRadius'],
|
---|
397 | // kebab-case versions
|
---|
398 | ['padding-left', 'padding-right'], ['margin-left', 'margin-right'], ['border-left', 'border-right'], ['border-left-color', 'border-right-color'], ['border-left-style', 'border-right-style'], ['border-left-width', 'border-right-width'], ['border-top-left-radius', 'border-top-right-radius'], ['border-bottom-left-radius', 'border-bottom-right-radius']]);
|
---|
399 | var propsToIgnore = ['content'];
|
---|
400 |
|
---|
401 | // this is the same as the propertiesToConvert except for values
|
---|
402 | var valuesToConvert = arrayToObject([['ltr', 'rtl'], ['left', 'right'], ['w-resize', 'e-resize'], ['sw-resize', 'se-resize'], ['nw-resize', 'ne-resize']]);
|
---|
403 |
|
---|
404 | // Sorry for the regex 😞, but basically thisis used to replace _every_ instance of
|
---|
405 | // `ltr`, `rtl`, `right`, and `left` in `backgroundimage` with the corresponding opposite.
|
---|
406 | // A situation we're accepting here:
|
---|
407 | // url('/left/right/rtl/ltr.png') will be changed to url('/right/left/ltr/rtl.png')
|
---|
408 | // Definite trade-offs here, but I think it's a good call.
|
---|
409 | var bgImgDirectionRegex = new RegExp('(^|\\W|_)((ltr)|(rtl)|(left)|(right))(\\W|_|$)', 'g');
|
---|
410 | var bgPosDirectionRegex = new RegExp('(left)|(right)');
|
---|
411 |
|
---|
412 | /**
|
---|
413 | * converts properties and values in the CSS in JS object to their corresponding RTL values
|
---|
414 | * @param {Object} object the CSS in JS object
|
---|
415 | * @return {Object} the RTL converted object
|
---|
416 | */
|
---|
417 | function convert(object) {
|
---|
418 | return Object.keys(object).reduce(function (newObj, originalKey) {
|
---|
419 | var originalValue = object[originalKey];
|
---|
420 | if (isString(originalValue)) {
|
---|
421 | // you're welcome to later code 😺
|
---|
422 | originalValue = originalValue.trim();
|
---|
423 | }
|
---|
424 |
|
---|
425 | // Some properties should never be transformed
|
---|
426 | if (includes(propsToIgnore, originalKey)) {
|
---|
427 | newObj[originalKey] = originalValue;
|
---|
428 | return newObj;
|
---|
429 | }
|
---|
430 | var _convertProperty = convertProperty(originalKey, originalValue),
|
---|
431 | key = _convertProperty.key,
|
---|
432 | value = _convertProperty.value;
|
---|
433 | newObj[key] = value;
|
---|
434 | return newObj;
|
---|
435 | }, Array.isArray(object) ? [] : {});
|
---|
436 | }
|
---|
437 |
|
---|
438 | /**
|
---|
439 | * Converts a property and its value to the corresponding RTL key and value
|
---|
440 | * @param {String} originalKey the original property key
|
---|
441 | * @param {Number|String|Object} originalValue the original css property value
|
---|
442 | * @return {Object} the new {key, value} pair
|
---|
443 | */
|
---|
444 | function convertProperty(originalKey, originalValue) {
|
---|
445 | var isNoFlip = /\/\*\s?@noflip\s?\*\//.test(originalValue);
|
---|
446 | var key = isNoFlip ? originalKey : getPropertyDoppelganger(originalKey);
|
---|
447 | var value = isNoFlip ? originalValue : getValueDoppelganger(key, originalValue);
|
---|
448 | return {
|
---|
449 | key: key,
|
---|
450 | value: value
|
---|
451 | };
|
---|
452 | }
|
---|
453 |
|
---|
454 | /**
|
---|
455 | * This gets the RTL version of the given property if it has a corresponding RTL property
|
---|
456 | * @param {String} property the name of the property
|
---|
457 | * @return {String} the name of the RTL property
|
---|
458 | */
|
---|
459 | function getPropertyDoppelganger(property) {
|
---|
460 | return propertiesToConvert[property] || property;
|
---|
461 | }
|
---|
462 |
|
---|
463 | /**
|
---|
464 | * This converts the given value to the RTL version of that value based on the key
|
---|
465 | * @param {String} key this is the key (note: this should be the RTL version of the originalKey)
|
---|
466 | * @param {String|Number|Object} originalValue the original css property value. If it's an object, then we'll convert that as well
|
---|
467 | * @return {String|Number|Object} the converted value
|
---|
468 | */
|
---|
469 | function getValueDoppelganger(key, originalValue) {
|
---|
470 | if (!canConvertValue(originalValue)) {
|
---|
471 | return originalValue;
|
---|
472 | }
|
---|
473 | if (isObject(originalValue)) {
|
---|
474 | return convert(originalValue); // recursion 🌀
|
---|
475 | }
|
---|
476 |
|
---|
477 | var isNum = isNumber(originalValue);
|
---|
478 | var isFunc = isFunction(originalValue);
|
---|
479 | var importantlessValue = isNum || isFunc ? originalValue : originalValue.replace(/ !important.*?$/, '');
|
---|
480 | var isImportant = !isNum && importantlessValue.length !== originalValue.length;
|
---|
481 | var valueConverter = propertyValueConverters[key];
|
---|
482 | var newValue;
|
---|
483 | if (valueConverter) {
|
---|
484 | newValue = valueConverter({
|
---|
485 | value: importantlessValue,
|
---|
486 | valuesToConvert: valuesToConvert,
|
---|
487 | propertiesToConvert: propertiesToConvert,
|
---|
488 | isRtl: true,
|
---|
489 | bgImgDirectionRegex: bgImgDirectionRegex,
|
---|
490 | bgPosDirectionRegex: bgPosDirectionRegex
|
---|
491 | });
|
---|
492 | } else {
|
---|
493 | newValue = valuesToConvert[importantlessValue] || importantlessValue;
|
---|
494 | }
|
---|
495 | if (isImportant) {
|
---|
496 | return newValue + " !important";
|
---|
497 | }
|
---|
498 | return newValue;
|
---|
499 | }
|
---|
500 |
|
---|
501 | exports.arrayToObject = arrayToObject;
|
---|
502 | exports.calculateNewBackgroundPosition = calculateNewBackgroundPosition;
|
---|
503 | exports.canConvertValue = canConvertValue;
|
---|
504 | exports.convert = convert;
|
---|
505 | exports.convertProperty = convertProperty;
|
---|
506 | exports.flipSign = flipSign;
|
---|
507 | exports.flipTransformSign = flipTransformSign;
|
---|
508 | exports.getPropertyDoppelganger = getPropertyDoppelganger;
|
---|
509 | exports.getValueDoppelganger = getValueDoppelganger;
|
---|
510 | exports.getValuesAsList = getValuesAsList;
|
---|
511 | exports.handleQuartetValues = handleQuartetValues;
|
---|
512 | exports.includes = includes;
|
---|
513 | exports.isBoolean = isBoolean;
|
---|
514 | exports.isFunction = isFunction;
|
---|
515 | exports.isNullOrUndefined = isNullOrUndefined;
|
---|
516 | exports.isNumber = isNumber;
|
---|
517 | exports.isObject = isObject;
|
---|
518 | exports.isString = isString;
|
---|
519 | exports.propertiesToConvert = propertiesToConvert;
|
---|
520 | exports.propertyValueConverters = propertyValueConverters;
|
---|
521 | exports.propsToIgnore = propsToIgnore;
|
---|
522 | exports.splitShadow = splitShadow;
|
---|
523 | exports.valuesToConvert = valuesToConvert;
|
---|