UNPKG

10.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var Stylesheet_1 = require("./Stylesheet");
5var kebabRules_1 = require("./transforms/kebabRules");
6var prefixRules_1 = require("./transforms/prefixRules");
7var provideUnits_1 = require("./transforms/provideUnits");
8var rtlifyRules_1 = require("./transforms/rtlifyRules");
9var DISPLAY_NAME = 'displayName';
10function getDisplayName(rules) {
11 var rootStyle = rules && rules['&'];
12 return rootStyle ? rootStyle.displayName : undefined;
13}
14var globalSelectorRegExp = /\:global\((.+?)\)/g;
15/**
16 * Finds comma separated selectors in a :global() e.g. ":global(.class1, .class2, .class3)"
17 * and wraps them each in their own global ":global(.class1), :global(.class2), :global(.class3)"
18 *
19 * @param selectorWithGlobals The selector to process
20 * @returns The updated selector
21 */
22function expandCommaSeparatedGlobals(selectorWithGlobals) {
23 // We the selector does not have a :global() we can shortcut
24 if (!globalSelectorRegExp.test(selectorWithGlobals)) {
25 return selectorWithGlobals;
26 }
27 var replacementInfo = [];
28 var findGlobal = /\:global\((.+?)\)/g;
29 var match = null;
30 // Create a result list for global selectors so we can replace them.
31 while ((match = findGlobal.exec(selectorWithGlobals))) {
32 // Only if the found selector is a comma separated list we'll process it.
33 if (match[1].indexOf(',') > -1) {
34 replacementInfo.push([
35 match.index,
36 match.index + match[0].length,
37 // Wrap each of the found selectors in :global()
38 match[1]
39 .split(',')
40 .map(function (v) { return ":global(" + v.trim() + ")"; })
41 .join(', '),
42 ]);
43 }
44 }
45 // Replace the found selectors with their wrapped variants in reverse order
46 return replacementInfo
47 .reverse()
48 .reduce(function (selector, _a) {
49 var matchIndex = _a[0], matchEndIndex = _a[1], replacement = _a[2];
50 var prefix = selector.slice(0, matchIndex);
51 var suffix = selector.slice(matchEndIndex);
52 return prefix + replacement + suffix;
53 }, selectorWithGlobals);
54}
55function expandSelector(newSelector, currentSelector) {
56 if (newSelector.indexOf(':global(') >= 0) {
57 return newSelector.replace(globalSelectorRegExp, '$1');
58 }
59 else if (newSelector.indexOf(':') === 0) {
60 return currentSelector + newSelector;
61 }
62 else if (newSelector.indexOf('&') < 0) {
63 return currentSelector + ' ' + newSelector;
64 }
65 return newSelector;
66}
67function extractSelector(currentSelector, rules, selector, value) {
68 if (rules === void 0) { rules = { __order: [] }; }
69 if (selector.indexOf('@') === 0) {
70 selector = selector + '{' + currentSelector;
71 extractRules([value], rules, selector);
72 }
73 else if (selector.indexOf(',') > -1) {
74 expandCommaSeparatedGlobals(selector)
75 .split(',')
76 .map(function (s) { return s.trim(); })
77 .forEach(function (separatedSelector) {
78 return extractRules([value], rules, expandSelector(separatedSelector, currentSelector));
79 });
80 }
81 else {
82 extractRules([value], rules, expandSelector(selector, currentSelector));
83 }
84}
85function extractRules(args, rules, currentSelector) {
86 if (rules === void 0) { rules = { __order: [] }; }
87 if (currentSelector === void 0) { currentSelector = '&'; }
88 var stylesheet = Stylesheet_1.Stylesheet.getInstance();
89 var currentRules = rules[currentSelector];
90 if (!currentRules) {
91 currentRules = {};
92 rules[currentSelector] = currentRules;
93 rules.__order.push(currentSelector);
94 }
95 for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
96 var arg = args_1[_i];
97 // If the arg is a string, we need to look up the class map and merge.
98 if (typeof arg === 'string') {
99 var expandedRules = stylesheet.argsFromClassName(arg);
100 if (expandedRules) {
101 extractRules(expandedRules, rules, currentSelector);
102 }
103 // Else if the arg is an array, we need to recurse in.
104 }
105 else if (Array.isArray(arg)) {
106 extractRules(arg, rules, currentSelector);
107 }
108 else {
109 for (var prop in arg) {
110 if (arg.hasOwnProperty(prop)) {
111 var propValue = arg[prop];
112 if (prop === 'selectors') {
113 // every child is a selector.
114 var selectors = arg.selectors;
115 for (var newSelector in selectors) {
116 if (selectors.hasOwnProperty(newSelector)) {
117 extractSelector(currentSelector, rules, newSelector, selectors[newSelector]);
118 }
119 }
120 }
121 else if (typeof propValue === 'object') {
122 // prop is a selector.
123 if (propValue !== null) {
124 extractSelector(currentSelector, rules, prop, propValue);
125 }
126 }
127 else {
128 if (propValue !== undefined) {
129 // Else, add the rule to the currentSelector.
130 if (prop === 'margin' || prop === 'padding') {
131 expandQuads(currentRules, prop, propValue);
132 }
133 else {
134 currentRules[prop] = propValue;
135 }
136 }
137 }
138 }
139 }
140 }
141 }
142 return rules;
143}
144function expandQuads(currentRules, name, value) {
145 var parts = typeof value === 'string' ? value.split(' ') : [value];
146 currentRules[name + 'Top'] = parts[0];
147 currentRules[name + 'Right'] = parts[1] || parts[0];
148 currentRules[name + 'Bottom'] = parts[2] || parts[0];
149 currentRules[name + 'Left'] = parts[3] || parts[1] || parts[0];
150}
151function getKeyForRules(options, rules) {
152 var serialized = [options.rtl ? 'rtl' : 'ltr'];
153 var hasProps = false;
154 for (var _i = 0, _a = rules.__order; _i < _a.length; _i++) {
155 var selector = _a[_i];
156 serialized.push(selector);
157 var rulesForSelector = rules[selector];
158 for (var propName in rulesForSelector) {
159 if (rulesForSelector.hasOwnProperty(propName) && rulesForSelector[propName] !== undefined) {
160 hasProps = true;
161 serialized.push(propName, rulesForSelector[propName]);
162 }
163 }
164 }
165 return hasProps ? serialized.join('') : undefined;
166}
167function repeatString(target, count) {
168 if (count <= 0) {
169 return '';
170 }
171 if (count === 1) {
172 return target;
173 }
174 return target + repeatString(target, count - 1);
175}
176function serializeRuleEntries(options, ruleEntries) {
177 if (!ruleEntries) {
178 return '';
179 }
180 var allEntries = [];
181 for (var entry in ruleEntries) {
182 if (ruleEntries.hasOwnProperty(entry) && entry !== DISPLAY_NAME && ruleEntries[entry] !== undefined) {
183 allEntries.push(entry, ruleEntries[entry]);
184 }
185 }
186 // Apply transforms.
187 for (var i = 0; i < allEntries.length; i += 2) {
188 kebabRules_1.kebabRules(allEntries, i);
189 provideUnits_1.provideUnits(allEntries, i);
190 rtlifyRules_1.rtlifyRules(options, allEntries, i);
191 prefixRules_1.prefixRules(allEntries, i);
192 }
193 // Apply punctuation.
194 for (var i = 1; i < allEntries.length; i += 4) {
195 allEntries.splice(i, 1, ':', allEntries[i], ';');
196 }
197 return allEntries.join('');
198}
199exports.serializeRuleEntries = serializeRuleEntries;
200function styleToRegistration(options) {
201 var args = [];
202 for (var _i = 1; _i < arguments.length; _i++) {
203 args[_i - 1] = arguments[_i];
204 }
205 var rules = extractRules(args);
206 var key = getKeyForRules(options, rules);
207 if (key) {
208 var stylesheet = Stylesheet_1.Stylesheet.getInstance();
209 var registration = {
210 className: stylesheet.classNameFromKey(key),
211 key: key,
212 args: args,
213 };
214 if (!registration.className) {
215 registration.className = stylesheet.getClassName(getDisplayName(rules));
216 var rulesToInsert = [];
217 for (var _a = 0, _b = rules.__order; _a < _b.length; _a++) {
218 var selector = _b[_a];
219 rulesToInsert.push(selector, serializeRuleEntries(options, rules[selector]));
220 }
221 registration.rulesToInsert = rulesToInsert;
222 }
223 return registration;
224 }
225 return undefined;
226}
227exports.styleToRegistration = styleToRegistration;
228/**
229 * Insert style to stylesheet.
230 * @param registration Style registration.
231 * @param specificityMultiplier Number of times classname selector is repeated in the css rule.
232 * This is to increase css specificity in case it's needed. Default to 1.
233 */
234function applyRegistration(registration, specificityMultiplier) {
235 if (specificityMultiplier === void 0) { specificityMultiplier = 1; }
236 var stylesheet = Stylesheet_1.Stylesheet.getInstance();
237 var className = registration.className, key = registration.key, args = registration.args, rulesToInsert = registration.rulesToInsert;
238 if (rulesToInsert) {
239 // rulesToInsert is an ordered array of selector/rule pairs.
240 for (var i = 0; i < rulesToInsert.length; i += 2) {
241 var rules = rulesToInsert[i + 1];
242 if (rules) {
243 var selector = rulesToInsert[i];
244 selector = selector.replace(/&/g, repeatString("." + registration.className, specificityMultiplier));
245 // Insert. Note if a media query, we must close the query with a final bracket.
246 var processedRule = selector + "{" + rules + "}" + (selector.indexOf('@') === 0 ? '}' : '');
247 stylesheet.insertRule(processedRule);
248 }
249 }
250 stylesheet.cacheClassName(className, key, args, rulesToInsert);
251 }
252}
253exports.applyRegistration = applyRegistration;
254function styleToClassName(options) {
255 var args = [];
256 for (var _i = 1; _i < arguments.length; _i++) {
257 args[_i - 1] = arguments[_i];
258 }
259 var registration = styleToRegistration.apply(void 0, tslib_1.__spreadArrays([options], args));
260 if (registration) {
261 applyRegistration(registration, options.specificityMultiplier);
262 return registration.className;
263 }
264 return '';
265}
266exports.styleToClassName = styleToClassName;
267//# sourceMappingURL=styleToClassName.js.map
\No newline at end of file