277 lines
13 KiB
JavaScript
277 lines
13 KiB
JavaScript
|
define(["require", "exports", "tslib", "./Stylesheet", "./transforms/kebabRules", "./transforms/prefixRules", "./transforms/provideUnits", "./transforms/rtlifyRules", "./tokenizeWithParentheses"], function (require, exports, tslib_1, Stylesheet_1, kebabRules_1, prefixRules_1, provideUnits_1, rtlifyRules_1, tokenizeWithParentheses_1) {
|
||
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.styleToClassName = exports.applyRegistration = exports.styleToRegistration = exports.serializeRuleEntries = void 0;
|
||
|
var DISPLAY_NAME = 'displayName';
|
||
|
function getDisplayName(rules) {
|
||
|
var rootStyle = rules && rules['&'];
|
||
|
return rootStyle ? rootStyle.displayName : undefined;
|
||
|
}
|
||
|
var globalSelectorRegExp = /\:global\((.+?)\)/g;
|
||
|
/**
|
||
|
* Finds comma separated selectors in a :global() e.g. ":global(.class1, .class2, .class3)"
|
||
|
* and wraps them each in their own global ":global(.class1), :global(.class2), :global(.class3)"
|
||
|
*
|
||
|
* @param selectorWithGlobals The selector to process
|
||
|
* @returns The updated selector
|
||
|
*/
|
||
|
function expandCommaSeparatedGlobals(selectorWithGlobals) {
|
||
|
// We the selector does not have a :global() we can shortcut
|
||
|
if (!globalSelectorRegExp.test(selectorWithGlobals)) {
|
||
|
return selectorWithGlobals;
|
||
|
}
|
||
|
var replacementInfo = [];
|
||
|
var findGlobal = /\:global\((.+?)\)/g;
|
||
|
var match = null;
|
||
|
// Create a result list for global selectors so we can replace them.
|
||
|
while ((match = findGlobal.exec(selectorWithGlobals))) {
|
||
|
// Only if the found selector is a comma separated list we'll process it.
|
||
|
if (match[1].indexOf(',') > -1) {
|
||
|
replacementInfo.push([
|
||
|
match.index,
|
||
|
match.index + match[0].length,
|
||
|
// Wrap each of the found selectors in :global()
|
||
|
match[1]
|
||
|
.split(',')
|
||
|
.map(function (v) { return ":global(".concat(v.trim(), ")"); })
|
||
|
.join(', '),
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
// Replace the found selectors with their wrapped variants in reverse order
|
||
|
return replacementInfo
|
||
|
.reverse()
|
||
|
.reduce(function (selector, _a) {
|
||
|
var matchIndex = _a[0], matchEndIndex = _a[1], replacement = _a[2];
|
||
|
var prefix = selector.slice(0, matchIndex);
|
||
|
var suffix = selector.slice(matchEndIndex);
|
||
|
return prefix + replacement + suffix;
|
||
|
}, selectorWithGlobals);
|
||
|
}
|
||
|
function isSelector(potentialSelector) {
|
||
|
return potentialSelector.indexOf(':global(') >= 0 || potentialSelector.indexOf(':') === 0;
|
||
|
}
|
||
|
function expandSelector(newSelector, currentSelector) {
|
||
|
if (newSelector.indexOf(':global(') >= 0) {
|
||
|
return newSelector.replace(globalSelectorRegExp, '$1');
|
||
|
}
|
||
|
else if (newSelector.indexOf(':host(') === 0) {
|
||
|
return newSelector;
|
||
|
}
|
||
|
else if (newSelector.indexOf(':') === 0) {
|
||
|
return currentSelector + newSelector;
|
||
|
}
|
||
|
else if (newSelector.indexOf('&') < 0) {
|
||
|
return currentSelector + ' ' + newSelector;
|
||
|
}
|
||
|
return newSelector;
|
||
|
}
|
||
|
function extractSelector(currentSelector, rules, selector, value, stylesheet) {
|
||
|
if (rules === void 0) { rules = { __order: [] }; }
|
||
|
if (selector.indexOf('@') === 0) {
|
||
|
selector = selector + '{' + currentSelector;
|
||
|
extractRules([value], rules, selector, stylesheet);
|
||
|
}
|
||
|
else if (selector.indexOf(',') > -1) {
|
||
|
expandCommaSeparatedGlobals(selector)
|
||
|
.split(',')
|
||
|
.map(function (s) { return s.trim(); })
|
||
|
.forEach(function (separatedSelector) {
|
||
|
return extractRules([value], rules, expandSelector(separatedSelector, currentSelector), stylesheet);
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
extractRules([value], rules, expandSelector(selector, currentSelector), stylesheet);
|
||
|
}
|
||
|
}
|
||
|
function extractRules(args, rules, currentSelector, stylesheet) {
|
||
|
if (rules === void 0) { rules = { __order: [] }; }
|
||
|
if (currentSelector === void 0) { currentSelector = '&'; }
|
||
|
var currentRules = rules[currentSelector];
|
||
|
if (!currentRules) {
|
||
|
currentRules = {};
|
||
|
rules[currentSelector] = currentRules;
|
||
|
rules.__order.push(currentSelector);
|
||
|
}
|
||
|
for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
|
||
|
var arg = args_1[_i];
|
||
|
// If the arg is a string, we need to look up the class map and merge.
|
||
|
if (typeof arg === 'string') {
|
||
|
var expandedRules = stylesheet.argsFromClassName(arg);
|
||
|
if (expandedRules) {
|
||
|
extractRules(expandedRules, rules, currentSelector, stylesheet);
|
||
|
}
|
||
|
// Else if the arg is an array, we need to recurse in.
|
||
|
}
|
||
|
else if (Array.isArray(arg)) {
|
||
|
extractRules(arg, rules, currentSelector, stylesheet);
|
||
|
}
|
||
|
else {
|
||
|
for (var prop in arg) {
|
||
|
if (arg.hasOwnProperty(prop)) {
|
||
|
var propValue = arg[prop];
|
||
|
if (prop === 'selectors') {
|
||
|
// every child is a selector.
|
||
|
var selectors = arg.selectors;
|
||
|
for (var newSelector in selectors) {
|
||
|
if (selectors.hasOwnProperty(newSelector)) {
|
||
|
extractSelector(currentSelector, rules, newSelector, selectors[newSelector], stylesheet);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (typeof propValue === 'object' || isSelector(prop)) {
|
||
|
// prop is a selector.
|
||
|
if (propValue !== null && propValue !== undefined) {
|
||
|
extractSelector(currentSelector, rules, prop, propValue, stylesheet);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (propValue !== undefined) {
|
||
|
// Else, add the rule to the currentSelector.
|
||
|
if (prop === 'margin' || prop === 'padding') {
|
||
|
expandQuads(currentRules, prop, propValue);
|
||
|
}
|
||
|
else {
|
||
|
currentRules[prop] = propValue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return rules;
|
||
|
}
|
||
|
function expandQuads(currentRules, name, value) {
|
||
|
var parts = typeof value === 'string' ? (0, tokenizeWithParentheses_1.tokenizeWithParentheses)(value) : [value];
|
||
|
if (parts.length === 0) {
|
||
|
parts.push(value);
|
||
|
}
|
||
|
if (parts[parts.length - 1] === '!important') {
|
||
|
// Remove !important from parts, and append it to each part individually
|
||
|
parts = parts.slice(0, -1).map(function (p) { return p + ' !important'; });
|
||
|
}
|
||
|
currentRules[name + 'Top'] = parts[0];
|
||
|
currentRules[name + 'Right'] = parts[1] || parts[0];
|
||
|
currentRules[name + 'Bottom'] = parts[2] || parts[0];
|
||
|
currentRules[name + 'Left'] = parts[3] || parts[1] || parts[0];
|
||
|
}
|
||
|
function getKeyForRules(options, rules) {
|
||
|
var serialized = [options.rtl ? 'rtl' : 'ltr'];
|
||
|
var hasProps = false;
|
||
|
for (var _i = 0, _a = rules.__order; _i < _a.length; _i++) {
|
||
|
var selector = _a[_i];
|
||
|
serialized.push(selector);
|
||
|
var rulesForSelector = rules[selector];
|
||
|
for (var propName in rulesForSelector) {
|
||
|
if (rulesForSelector.hasOwnProperty(propName) && rulesForSelector[propName] !== undefined) {
|
||
|
hasProps = true;
|
||
|
serialized.push(propName, rulesForSelector[propName]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return hasProps ? serialized.join('') : undefined;
|
||
|
}
|
||
|
function repeatString(target, count) {
|
||
|
if (count <= 0) {
|
||
|
return '';
|
||
|
}
|
||
|
if (count === 1) {
|
||
|
return target;
|
||
|
}
|
||
|
return target + repeatString(target, count - 1);
|
||
|
}
|
||
|
function serializeRuleEntries(options, ruleEntries) {
|
||
|
if (!ruleEntries) {
|
||
|
return '';
|
||
|
}
|
||
|
var allEntries = [];
|
||
|
for (var entry in ruleEntries) {
|
||
|
if (ruleEntries.hasOwnProperty(entry) && entry !== DISPLAY_NAME && ruleEntries[entry] !== undefined) {
|
||
|
allEntries.push(entry, ruleEntries[entry]);
|
||
|
}
|
||
|
}
|
||
|
// Apply transforms.
|
||
|
for (var i = 0; i < allEntries.length; i += 2) {
|
||
|
(0, kebabRules_1.kebabRules)(allEntries, i);
|
||
|
(0, provideUnits_1.provideUnits)(allEntries, i);
|
||
|
(0, rtlifyRules_1.rtlifyRules)(options, allEntries, i);
|
||
|
(0, prefixRules_1.prefixRules)(allEntries, i);
|
||
|
}
|
||
|
// Apply punctuation.
|
||
|
for (var i = 1; i < allEntries.length; i += 4) {
|
||
|
allEntries.splice(i, 1, ':', allEntries[i], ';');
|
||
|
}
|
||
|
return allEntries.join('');
|
||
|
}
|
||
|
exports.serializeRuleEntries = serializeRuleEntries;
|
||
|
function styleToRegistration(options) {
|
||
|
var _a;
|
||
|
var args = [];
|
||
|
for (var _i = 1; _i < arguments.length; _i++) {
|
||
|
args[_i - 1] = arguments[_i];
|
||
|
}
|
||
|
var stylesheet = (_a = options.stylesheet) !== null && _a !== void 0 ? _a : Stylesheet_1.Stylesheet.getInstance(options.shadowConfig);
|
||
|
var rules = extractRules(args, undefined, undefined, stylesheet);
|
||
|
var key = getKeyForRules(options, rules);
|
||
|
if (key) {
|
||
|
var registration = {
|
||
|
className: stylesheet.classNameFromKey(key),
|
||
|
key: key,
|
||
|
args: args,
|
||
|
};
|
||
|
if (!registration.className) {
|
||
|
registration.className = stylesheet.getClassName(getDisplayName(rules));
|
||
|
var rulesToInsert = [];
|
||
|
for (var _b = 0, _c = rules.__order; _b < _c.length; _b++) {
|
||
|
var selector = _c[_b];
|
||
|
rulesToInsert.push(selector, serializeRuleEntries(options, rules[selector]));
|
||
|
}
|
||
|
registration.rulesToInsert = rulesToInsert;
|
||
|
}
|
||
|
return registration;
|
||
|
}
|
||
|
return undefined;
|
||
|
}
|
||
|
exports.styleToRegistration = styleToRegistration;
|
||
|
/**
|
||
|
* Insert style to stylesheet.
|
||
|
* @param registration Style registration.
|
||
|
* @param specificityMultiplier Number of times classname selector is repeated in the css rule.
|
||
|
* This is to increase css specificity in case it's needed. Default to 1.
|
||
|
*/
|
||
|
function applyRegistration(registration, specificityMultiplier, shadowConfig, sheet) {
|
||
|
if (specificityMultiplier === void 0) { specificityMultiplier = 1; }
|
||
|
var stylesheet = sheet !== null && sheet !== void 0 ? sheet : Stylesheet_1.Stylesheet.getInstance(shadowConfig);
|
||
|
var className = registration.className, key = registration.key, args = registration.args, rulesToInsert = registration.rulesToInsert;
|
||
|
if (rulesToInsert) {
|
||
|
// rulesToInsert is an ordered array of selector/rule pairs.
|
||
|
for (var i = 0; i < rulesToInsert.length; i += 2) {
|
||
|
var rules = rulesToInsert[i + 1];
|
||
|
if (rules) {
|
||
|
var selector = rulesToInsert[i];
|
||
|
selector = selector.replace(/&/g, repeatString(".".concat(registration.className), specificityMultiplier));
|
||
|
// Insert. Note if a media query, we must close the query with a final bracket.
|
||
|
var processedRule = "".concat(selector, "{").concat(rules, "}").concat(selector.indexOf('@') === 0 ? '}' : '');
|
||
|
stylesheet.insertRule(processedRule);
|
||
|
}
|
||
|
}
|
||
|
stylesheet.cacheClassName(className, key, args, rulesToInsert);
|
||
|
}
|
||
|
}
|
||
|
exports.applyRegistration = applyRegistration;
|
||
|
function styleToClassName(options) {
|
||
|
var args = [];
|
||
|
for (var _i = 1; _i < arguments.length; _i++) {
|
||
|
args[_i - 1] = arguments[_i];
|
||
|
}
|
||
|
var registration = styleToRegistration.apply(void 0, tslib_1.__spreadArray([options], args, false));
|
||
|
if (registration) {
|
||
|
applyRegistration(registration, options.specificityMultiplier, options.shadowConfig, options.stylesheet);
|
||
|
return registration.className;
|
||
|
}
|
||
|
return '';
|
||
|
}
|
||
|
exports.styleToClassName = styleToClassName;
|
||
|
});
|
||
|
//# sourceMappingURL=styleToClassName.js.map
|