pretty-lights
Version:
CSS-in-JS with a reliable API
237 lines (181 loc) • 7.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isReactElement = isReactElement;
exports.isDOMElement = isDOMElement;
exports.getClassNamesFromNodes = getClassNamesFromNodes;
exports.getStylesFromClassNames = getStylesFromClassNames;
exports.getStyleElements = getStyleElements;
exports.getKeys = getKeys;
exports.hasClassNames = hasClassNames;
exports.getMediaRules = getMediaRules;
exports.RULE_TYPES = void 0;
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function flatMap(arr, iteratee) {
var _ref;
return (_ref = []).concat.apply(_ref, _toConsumableArray(arr.map(iteratee)));
}
var RULE_TYPES = {
media: 'media',
rule: 'rule'
};
exports.RULE_TYPES = RULE_TYPES;
function getClassNames(selectors, classes) {
return classes ? selectors.concat(classes.split(' ')) : selectors;
}
function getClassNamesFromTestRenderer(selectors, _ref2) {
var _ref2$props = _ref2.props,
props = _ref2$props === void 0 ? {} : _ref2$props;
return getClassNames(selectors, props.className || props["class"]);
}
function shouldDive(node) {
return typeof node.dive === 'function' && typeof node.type() !== 'string';
}
function isTagWithClassName(node) {
return node.prop('className') && typeof node.type() === 'string';
}
function getClassNamesFromEnzyme(selectors, node) {
// We need to dive if we have selected a styled child from a shallow render
var actualComponent = shouldDive(node) ? node.dive() : node; // Find the first node with a className prop
var components = actualComponent.findWhere(isTagWithClassName);
var classes = components.length && components.first().prop('className');
return getClassNames(selectors, classes);
}
function getClassNamesFromCheerio(selectors, node) {
var classes = node.attr('class');
return getClassNames(selectors, classes);
}
function getClassNamesFromDOMElement(selectors, node) {
return getClassNames(selectors, node.getAttribute('class'));
}
function isReactElement(val) {
return val.$$typeof === Symbol["for"]('react.test.json');
} // $FORK$ remove css prop checks
var domElementPattern = /^((HTML|SVG)\w*)?Element$/;
function isDOMElement(val) {
return val.nodeType === 1 && val.constructor && val.constructor.name && domElementPattern.test(val.constructor.name);
}
function isEnzymeElement(val) {
return typeof val.findWhere === 'function';
}
function isCheerioElement(val) {
return val.cheerio === '[cheerio object]';
}
function getClassNamesFromNodes(nodes) {
return nodes.reduce(function (selectors, node) {
if (isReactElement(node)) {
return getClassNamesFromTestRenderer(selectors, node);
}
if (isEnzymeElement(node)) {
return getClassNamesFromEnzyme(selectors, node);
}
if (isCheerioElement(node)) {
return getClassNamesFromCheerio(selectors, node);
}
return getClassNamesFromDOMElement(selectors, node);
}, []);
}
var keyframesPattern = /^@keyframes\s+(animation-[^{\s]+)+/;
var removeCommentPattern = /\/\*[\s\S]*?\*\//g;
var getElementRules = function getElementRules(element) {
var nonSpeedyRule = element.textContent;
if (nonSpeedyRule) {
return [nonSpeedyRule];
}
if (!element.sheet) {
return [];
} // $FlowFixMe - flow doesn't know about `cssRules` property
return [].slice.call(element.sheet.cssRules).map(function (cssRule) {
return cssRule.cssText;
});
};
function getStylesFromClassNames(classNames, elements) {
if (!classNames.length) {
return '';
} // eslint-disable-next-line no-use-before-define
var keys = getKeys(elements);
if (!keys.length) {
return '';
}
var keyPatten = new RegExp("^(".concat(keys.join('|'), ")-"));
var filteredClassNames = classNames.filter(function (className) {
return keyPatten.test(className);
});
if (!filteredClassNames.length) {
return '';
}
var selectorPattern = new RegExp("\\.(".concat(filteredClassNames.join('|'), ")"));
var keyframes = {};
var styles = '';
flatMap(elements, getElementRules).forEach(function (rule) {
if (selectorPattern.test(rule)) {
styles += rule;
}
var match = rule.match(keyframesPattern);
if (match !== null) {
var name = match[1];
if (keyframes[name] === undefined) {
keyframes[name] = '';
}
keyframes[name] += rule;
}
});
var keyframeNameKeys = Object.keys(keyframes);
var keyframesStyles = '';
if (keyframeNameKeys.length) {
var keyframesNamePattern = new RegExp(keyframeNameKeys.join('|'), 'g');
var keyframesNameCache = {};
var index = 0;
styles = styles.replace(keyframesNamePattern, function (name) {
if (keyframesNameCache[name] === undefined) {
keyframesNameCache[name] = "animation-".concat(index);
index += 1;
keyframesStyles += keyframes[name];
}
return keyframesNameCache[name];
});
keyframesStyles = keyframesStyles.replace(keyframesNamePattern, function (value) {
return keyframesNameCache[value];
});
}
return (keyframesStyles + styles).replace(removeCommentPattern, '');
}
function getStyleElements() {
var elements = Array.from(document.querySelectorAll('style[data-lights]')); // $FlowFixMe
return elements;
}
var unique = function unique(arr) {
return Array.from(new Set(arr));
};
function getKeys(elements) {
var keys = unique(elements.map(function (element) {
return element.getAttribute('data-lights');
})).filter(Boolean);
return keys;
}
function hasClassNames(classNames, selectors, target) {
// selectors is the classNames of specific css rule
return selectors.some(function (selector) {
// if no target, use className of the specific css rule and try to find it
// in the list of received node classNames to make sure this css rule
// applied for root element
if (!target) {
return classNames.includes(selector.slice(1));
} // check if selector (className) of specific css rule match target
return target instanceof RegExp ? target.test(selector) : selector.includes(target);
});
}
function getMediaRules(rules, media) {
return rules.filter(function (rule) {
var isMediaMatch = rule.media ? rule.media.replace(/\s/g, '').includes(media.replace(/\s/g, '')) : false;
return rule.type === RULE_TYPES.media && isMediaMatch;
}).reduce(function (mediaRules, mediaRule) {
return mediaRules.concat(mediaRule.rules);
}, []);
}