'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var Stylis = _interopDefault(require('stylis/stylis.min')); var _insertRulePlugin = _interopDefault(require('stylis-rule-sheet')); var React = require('react'); var React__default = _interopDefault(React); var unitless = _interopDefault(require('@emotion/unitless')); var reactIs = require('react-is'); var supportsColor = _interopDefault(require('supports-color')); var transformDeclPairs = _interopDefault(require('css-to-react-native')); var memoize = _interopDefault(require('memoize-one')); var merge = _interopDefault(require('merge-anything')); // // Source: https://github.com/garycourt/murmurhash-js/blob/master/murmurhash2_gc.js function murmurhash(c) { for (var e = c.length | 0, a = e | 0, d = 0, b; e >= 4;) { b = c.charCodeAt(d) & 255 | (c.charCodeAt(++d) & 255) << 8 | (c.charCodeAt(++d) & 255) << 16 | (c.charCodeAt(++d) & 255) << 24, b = 1540483477 * (b & 65535) + ((1540483477 * (b >>> 16) & 65535) << 16), b ^= b >>> 24, b = 1540483477 * (b & 65535) + ((1540483477 * (b >>> 16) & 65535) << 16), a = 1540483477 * (a & 65535) + ((1540483477 * (a >>> 16) & 65535) << 16) ^ b, e -= 4, ++d; } switch (e) { case 3: a ^= (c.charCodeAt(d + 2) & 255) << 16; case 2: a ^= (c.charCodeAt(d + 1) & 255) << 8; case 1: a ^= c.charCodeAt(d) & 255, a = 1540483477 * (a & 65535) + ((1540483477 * (a >>> 16) & 65535) << 16); } a ^= a >>> 13; a = 1540483477 * (a & 65535) + ((1540483477 * (a >>> 16) & 65535) << 16); return (a ^ a >>> 15) >>> 0; } // function getComponentName(target) { return (process.env.NODE_ENV !== 'production' ? typeof target === 'string' && target : false) || target.displayName || target.name || 'Component'; } // function isFunction(test) { return typeof test === 'function'; } // function isStatelessFunction(test) { return typeof test === 'function' && !(test.prototype && test.prototype.isReactComponent); } var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var objectWithoutProperties = function (obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; // var isPlainObject = (function (x) { return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x.constructor === Object; }); // function isStyledComponent(target) { return target && typeof target.styledComponentId === 'string'; } // var SC_ATTR = typeof process !== 'undefined' && (process.env.REACT_APP_SC_ATTR || process.env.SC_ATTR) || 'data-styled'; var SC_VERSION_ATTR = 'data-styled-version'; var SC_STREAM_ATTR = 'data-styled-streamed'; var IS_BROWSER = typeof window !== 'undefined' && 'HTMLElement' in window; var DISABLE_SPEEDY = typeof SC_DISABLE_SPEEDY === 'boolean' && SC_DISABLE_SPEEDY || typeof process !== 'undefined' && (process.env.REACT_APP_SC_DISABLE_SPEEDY || process.env.SC_DISABLE_SPEEDY) || process.env.NODE_ENV !== 'production'; // /** * Parse errors.md and turn it into a simple hash of code: message */ var ERRORS = process.env.NODE_ENV !== 'production' ? { "1": "Cannot create styled-component for component: %s.\n\n", "2": "Can't collect styles once you've consumed a `ServerStyleSheet`'s styles! `ServerStyleSheet` is a one off instance for each server-side render cycle.\n\n- Are you trying to reuse it across renders?\n- Are you accidentally calling collectStyles twice?\n\n", "3": "Streaming SSR is only supported in a Node.js environment; Please do not try to call this method in the browser.\n\n", "4": "The `StyleSheetManager` expects a valid target or sheet prop!\n\n- Does this error occur on the client and is your target falsy?\n- Does this error occur on the server and is the sheet falsy?\n\n", "5": "The clone method cannot be used on the client!\n\n- Are you running in a client-like environment on the server?\n- Are you trying to run SSR on the client?\n\n", "6": "Trying to insert a new style tag, but the given Node is unmounted!\n\n- Are you using a custom target that isn't mounted?\n- Does your document not have a valid head element?\n- Have you accidentally removed a style tag manually?\n\n", "7": "ThemeProvider: Please return an object from your \"theme\" prop function, e.g.\n\n```js\ntheme={() => ({})}\n```\n\n", "8": "ThemeProvider: Please make your \"theme\" prop an object.\n\n", "9": "Missing document `
`\n\n", "10": "Cannot find a StyleSheet instance. Usually this happens if there are multiple copies of styled-components loaded at once. Check out this issue for how to troubleshoot and fix the common cases where this situation can happen: https://github.com/styled-components/styled-components/issues/1941#issuecomment-417862021\n\n", "11": "_This error was replaced with a dev-time warning, it will be deleted for v4 final._ [createGlobalStyle] received children which will not be rendered. Please use the component without passing children elements.\n\n", "12": "It seems you are interpolating a keyframe declaration (%s) into an untagged string. This was supported in styled-components v3, but is not longer supported in v4 as keyframes are now injected on-demand. Please wrap your string in the css\\`\\` helper which ensures the styles are injected correctly. See https://www.styled-components.com/docs/api#css\n\n", "13": "%s is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.\n" } : {}; /** * super basic version of sprintf */ function format() { var a = arguments.length <= 0 ? undefined : arguments[0]; var b = []; for (var c = 1, len = arguments.length; c < len; c += 1) { b.push(arguments.length <= c ? undefined : arguments[c]); } b.forEach(function (d) { a = a.replace(/%[a-z]/, d); }); return a; } /** * Create an error file out of errors.md for development and a simple web link to the full errors * in production mode. */ var StyledComponentsError = function (_Error) { inherits(StyledComponentsError, _Error); function StyledComponentsError(code) { classCallCheck(this, StyledComponentsError); for (var _len = arguments.length, interpolations = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { interpolations[_key - 1] = arguments[_key]; } if (process.env.NODE_ENV === 'production') { var _this = possibleConstructorReturn(this, _Error.call(this, 'An error occurred. See https://github.com/styled-components/styled-components/blob/master/packages/styled-components/src/utils/errors.md#' + code + ' for more information.' + (interpolations.length > 0 ? ' Additional arguments: ' + interpolations.join(', ') : ''))); } else { var _this = possibleConstructorReturn(this, _Error.call(this, format.apply(undefined, [ERRORS[code]].concat(interpolations)).trim())); } return possibleConstructorReturn(_this); } return StyledComponentsError; }(Error); // var SC_COMPONENT_ID = /^[^\S\n]*?\/\* sc-component-id:\s*(\S+)\s+\*\//gm; var extractComps = (function (maybeCSS) { var css = '' + (maybeCSS || ''); // Definitely a string, and a clone var existingComponents = []; css.replace(SC_COMPONENT_ID, function (match, componentId, matchIndex) { existingComponents.push({ componentId: componentId, matchIndex: matchIndex }); return match; }); return existingComponents.map(function (_ref, i) { var componentId = _ref.componentId, matchIndex = _ref.matchIndex; var nextComp = existingComponents[i + 1]; var cssFromDOM = nextComp ? css.slice(matchIndex, nextComp.matchIndex) : css.slice(matchIndex); return { componentId: componentId, cssFromDOM: cssFromDOM }; }); }); // // NOTE: This stylis instance is only used to split rules from SSR'd style tags var stylisSplitter = new Stylis({ global: false, cascade: true, keyframe: false, prefix: false, compress: false, semicolon: true }); var stylis = new Stylis({ global: false, cascade: true, keyframe: false, prefix: true, compress: false, semicolon: false // NOTE: This means "autocomplete missing semicolons" }); // Wrap `insertRulePlugin to build a list of rules, // and then make our own plugin to return the rules. This // makes it easier to hook into the existing SSR architecture var parsingRules = []; // eslint-disable-next-line consistent-return var returnRulesPlugin = function returnRulesPlugin(context) { if (context === -2) { var parsedRules = parsingRules; parsingRules = []; return parsedRules; } }; var parseRulesPlugin = _insertRulePlugin(function (rule) { parsingRules.push(rule); }); var _componentId = void 0; var _selector = void 0; var _selectorRegexp = void 0; var selfReferenceReplacer = function selfReferenceReplacer(match, offset, string) { if ( // the first self-ref is always untouched offset > 0 && // there should be at least two self-refs to do a replacement (.b > .b) string.slice(0, offset).indexOf(_selector) !== -1 && // no consecutive self refs (.b.b); that is a precedence boost and treated differently string.slice(offset - _selector.length, offset) !== _selector) { return '.' + _componentId; } return match; }; /** * When writing a style like * * & + & { * color: red; * } * * The second ampersand should be a reference to the static component class. stylis * has no knowledge of static class so we have to intelligently replace the base selector. */ var selfReferenceReplacementPlugin = function selfReferenceReplacementPlugin(context, _, selectors) { if (context === 2 && selectors.length && selectors[0].lastIndexOf(_selector) > 0) { // eslint-disable-next-line no-param-reassign selectors[0] = selectors[0].replace(_selectorRegexp, selfReferenceReplacer); } }; stylis.use([selfReferenceReplacementPlugin, parseRulesPlugin, returnRulesPlugin]); stylisSplitter.use([parseRulesPlugin, returnRulesPlugin]); var splitByRules = function splitByRules(css) { return stylisSplitter('', css); }; // /* eslint-disable camelcase, no-undef */ var getNonce = (function () { return typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null; }); // /* These are helpers for the StyleTags to keep track of the injected * rule names for each (component) ID that they're keeping track of. * They're crucial for detecting whether a name has already been * injected. * (This excludes rehydrated names) */ /* adds a new ID:name pairing to a names dictionary */ var addNameForId = function addNameForId(names, id, name) { if (name) { // eslint-disable-next-line no-param-reassign var namesForId = names[id] || (names[id] = Object.create(null)); namesForId[name] = true; } }; /* resets an ID entirely by overwriting it in the dictionary */ var resetIdNames = function resetIdNames(names, id) { // eslint-disable-next-line no-param-reassign names[id] = Object.create(null); }; /* factory for a names dictionary checking the existance of an ID:name pairing */ var hasNameForId = function hasNameForId(names) { return function (id, name) { return names[id] !== undefined && names[id][name]; }; }; /* stringifies names for the html/element output */ var stringifyNames = function stringifyNames(names) { var str = ''; // eslint-disable-next-line guard-for-in for (var id in names) { str += Object.keys(names[id]).join(' ') + ' '; } return str.trim(); }; /* clones the nested names dictionary */ var cloneNames = function cloneNames(names) { var clone = Object.create(null); // eslint-disable-next-line guard-for-in for (var id in names) { clone[id] = _extends({}, names[id]); } return clone; }; // /* These are helpers that deal with the insertRule (aka speedy) API * They are used in the StyleTags and specifically the speedy tag */ /* retrieve a sheet for a given style tag */ var sheetForTag = function sheetForTag(tag) { // $FlowFixMe if (tag.sheet) return tag.sheet; /* Firefox quirk requires us to step through all stylesheets to find one owned by the given tag */ var size = tag.ownerDocument.styleSheets.length; for (var i = 0; i < size; i += 1) { var sheet = tag.ownerDocument.styleSheets[i]; // $FlowFixMe if (sheet.ownerNode === tag) return sheet; } /* we should always be able to find a tag */ throw new StyledComponentsError(10); }; /* insert a rule safely and return whether it was actually injected */ var safeInsertRule = function safeInsertRule(sheet, cssRule, index) { /* abort early if cssRule string is falsy */ if (!cssRule) return false; var maxIndex = sheet.cssRules.length; try { /* use insertRule and cap passed index with maxIndex (no of cssRules) */ sheet.insertRule(cssRule, index <= maxIndex ? index : maxIndex); } catch (err) { /* any error indicates an invalid rule */ return false; } return true; }; /* deletes `size` rules starting from `removalIndex` */ var deleteRules = function deleteRules(sheet, removalIndex, size) { var lowerBound = removalIndex - size; for (var i = removalIndex; i > lowerBound; i -= 1) { sheet.deleteRule(i); } }; // /* this marker separates component styles and is important for rehydration */ var makeTextMarker = function makeTextMarker(id) { return '\n/* sc-component-id: ' + id + ' */\n'; }; /* add up all numbers in array up until and including the index */ var addUpUntilIndex = function addUpUntilIndex(sizes, index) { var totalUpToIndex = 0; for (var i = 0; i <= index; i += 1) { totalUpToIndex += sizes[i]; } return totalUpToIndex; }; /* create a new style tag after lastEl */ var makeStyleTag = function makeStyleTag(target, tagEl, insertBefore) { var targetDocument = document; if (target) targetDocument = target.ownerDocument;else if (tagEl) targetDocument = tagEl.ownerDocument; var el = targetDocument.createElement('style'); el.setAttribute(SC_ATTR, ''); el.setAttribute(SC_VERSION_ATTR, "4.4.1"); var nonce = getNonce(); if (nonce) { el.setAttribute('nonce', nonce); } /* Work around insertRule quirk in EdgeHTML */ el.appendChild(targetDocument.createTextNode('')); if (target && !tagEl) { /* Append to target when no previous element was passed */ target.appendChild(el); } else { if (!tagEl || !target || !tagEl.parentNode) { throw new StyledComponentsError(6); } /* Insert new style tag after the previous one */ tagEl.parentNode.insertBefore(el, insertBefore ? tagEl : tagEl.nextSibling); } return el; }; /* takes a css factory function and outputs an html styled tag factory */ var wrapAsHtmlTag = function wrapAsHtmlTag(css, names) { return function (additionalAttrs) { var nonce = getNonce(); var attrs = [nonce && 'nonce="' + nonce + '"', SC_ATTR + '="' + stringifyNames(names) + '"', SC_VERSION_ATTR + '="' + "4.4.1" + '"', additionalAttrs]; var htmlAttr = attrs.filter(Boolean).join(' '); return ''; }; }; /* takes a css factory function and outputs an element factory */ var wrapAsElement = function wrapAsElement(css, names) { return function () { var _props; var props = (_props = {}, _props[SC_ATTR] = stringifyNames(names), _props[SC_VERSION_ATTR] = "4.4.1", _props); var nonce = getNonce(); if (nonce) { // $FlowFixMe props.nonce = nonce; } // eslint-disable-next-line react/no-danger return React__default.createElement('style', _extends({}, props, { dangerouslySetInnerHTML: { __html: css() } })); }; }; var getIdsFromMarkersFactory = function getIdsFromMarkersFactory(markers) { return function () { return Object.keys(markers); }; }; /* speedy tags utilise insertRule */ var makeSpeedyTag = function makeSpeedyTag(el, getImportRuleTag) { var names = Object.create(null); var markers = Object.create(null); var sizes = []; var extractImport = getImportRuleTag !== undefined; /* indicates whether getImportRuleTag was called */ var usedImportRuleTag = false; var insertMarker = function insertMarker(id) { var prev = markers[id]; if (prev !== undefined) { return prev; } markers[id] = sizes.length; sizes.push(0); resetIdNames(names, id); return markers[id]; }; var insertRules = function insertRules(id, cssRules, name) { var marker = insertMarker(id); var sheet = sheetForTag(el); var insertIndex = addUpUntilIndex(sizes, marker); var injectedRules = 0; var importRules = []; var cssRulesSize = cssRules.length; for (var i = 0; i < cssRulesSize; i += 1) { var cssRule = cssRules[i]; var mayHaveImport = extractImport; /* @import rules are reordered to appear first */ if (mayHaveImport && cssRule.indexOf('@import') !== -1) { importRules.push(cssRule); } else if (safeInsertRule(sheet, cssRule, insertIndex + injectedRules)) { mayHaveImport = false; injectedRules += 1; } } if (extractImport && importRules.length > 0) { usedImportRuleTag = true; // $FlowFixMe getImportRuleTag().insertRules(id + '-import', importRules); } sizes[marker] += injectedRules; /* add up no of injected rules */ addNameForId(names, id, name); }; var removeRules = function removeRules(id) { var marker = markers[id]; if (marker === undefined) return; // $FlowFixMe if (el.isConnected === false) return; var size = sizes[marker]; var sheet = sheetForTag(el); var removalIndex = addUpUntilIndex(sizes, marker) - 1; deleteRules(sheet, removalIndex, size); sizes[marker] = 0; resetIdNames(names, id); if (extractImport && usedImportRuleTag) { // $FlowFixMe getImportRuleTag().removeRules(id + '-import'); } }; var css = function css() { var _sheetForTag = sheetForTag(el), cssRules = _sheetForTag.cssRules; var str = ''; // eslint-disable-next-line guard-for-in for (var id in markers) { str += makeTextMarker(id); var marker = markers[id]; var end = addUpUntilIndex(sizes, marker); var size = sizes[marker]; for (var i = end - size; i < end; i += 1) { var rule = cssRules[i]; if (rule !== undefined) { str += rule.cssText; } } } return str; }; return { clone: function clone() { throw new StyledComponentsError(5); }, css: css, getIds: getIdsFromMarkersFactory(markers), hasNameForId: hasNameForId(names), insertMarker: insertMarker, insertRules: insertRules, removeRules: removeRules, sealed: false, styleTag: el, toElement: wrapAsElement(css, names), toHTML: wrapAsHtmlTag(css, names) }; }; var makeTextNode = function makeTextNode(targetDocument, id) { return targetDocument.createTextNode(makeTextMarker(id)); }; var makeBrowserTag = function makeBrowserTag(el, getImportRuleTag) { var names = Object.create(null); var markers = Object.create(null); var extractImport = getImportRuleTag !== undefined; /* indicates whether getImportRuleTag was called */ var usedImportRuleTag = false; var insertMarker = function insertMarker(id) { var prev = markers[id]; if (prev !== undefined) { return prev; } markers[id] = makeTextNode(el.ownerDocument, id); el.appendChild(markers[id]); names[id] = Object.create(null); return markers[id]; }; var insertRules = function insertRules(id, cssRules, name) { var marker = insertMarker(id); var importRules = []; var cssRulesSize = cssRules.length; for (var i = 0; i < cssRulesSize; i += 1) { var rule = cssRules[i]; var mayHaveImport = extractImport; if (mayHaveImport && rule.indexOf('@import') !== -1) { importRules.push(rule); } else { mayHaveImport = false; var separator = i === cssRulesSize - 1 ? '' : ' '; marker.appendData('' + rule + separator); } } addNameForId(names, id, name); if (extractImport && importRules.length > 0) { usedImportRuleTag = true; // $FlowFixMe getImportRuleTag().insertRules(id + '-import', importRules); } }; var removeRules = function removeRules(id) { var marker = markers[id]; if (marker === undefined) return; /* create new empty text node and replace the current one */ var newMarker = makeTextNode(el.ownerDocument, id); el.replaceChild(newMarker, marker); markers[id] = newMarker; resetIdNames(names, id); if (extractImport && usedImportRuleTag) { // $FlowFixMe getImportRuleTag().removeRules(id + '-import'); } }; var css = function css() { var str = ''; // eslint-disable-next-line guard-for-in for (var id in markers) { str += markers[id].data; } return str; }; return { clone: function clone() { throw new StyledComponentsError(5); }, css: css, getIds: getIdsFromMarkersFactory(markers), hasNameForId: hasNameForId(names), insertMarker: insertMarker, insertRules: insertRules, removeRules: removeRules, sealed: false, styleTag: el, toElement: wrapAsElement(css, names), toHTML: wrapAsHtmlTag(css, names) }; }; var makeServerTag = function makeServerTag(namesArg, markersArg) { var names = namesArg === undefined ? Object.create(null) : namesArg; var markers = markersArg === undefined ? Object.create(null) : markersArg; var insertMarker = function insertMarker(id) { var prev = markers[id]; if (prev !== undefined) { return prev; } return markers[id] = ['']; }; var insertRules = function insertRules(id, cssRules, name) { var marker = insertMarker(id); marker[0] += cssRules.join(' '); addNameForId(names, id, name); }; var removeRules = function removeRules(id) { var marker = markers[id]; if (marker === undefined) return; marker[0] = ''; resetIdNames(names, id); }; var css = function css() { var str = ''; // eslint-disable-next-line guard-for-in for (var id in markers) { var cssForId = markers[id][0]; if (cssForId) { str += makeTextMarker(id) + cssForId; } } return str; }; var clone = function clone() { var namesClone = cloneNames(names); var markersClone = Object.create(null); // eslint-disable-next-line guard-for-in for (var id in markers) { markersClone[id] = [markers[id][0]]; } return makeServerTag(namesClone, markersClone); }; var tag = { clone: clone, css: css, getIds: getIdsFromMarkersFactory(markers), hasNameForId: hasNameForId(names), insertMarker: insertMarker, insertRules: insertRules, removeRules: removeRules, sealed: false, styleTag: null, toElement: wrapAsElement(css, names), toHTML: wrapAsHtmlTag(css, names) }; return tag; }; var makeTag = function makeTag(target, tagEl, forceServer, insertBefore, getImportRuleTag) { if (IS_BROWSER && !forceServer) { var el = makeStyleTag(target, tagEl, insertBefore); if (DISABLE_SPEEDY) { return makeBrowserTag(el, getImportRuleTag); } else { return makeSpeedyTag(el, getImportRuleTag); } } return makeServerTag(); }; var rehydrate = function rehydrate(tag, els, extracted) { /* add all extracted components to the new tag */ for (var i = 0, len = extracted.length; i < len; i += 1) { var _extracted$i = extracted[i], componentId = _extracted$i.componentId, cssFromDOM = _extracted$i.cssFromDOM; var cssRules = splitByRules(cssFromDOM); tag.insertRules(componentId, cssRules); } /* remove old HTMLStyleElements, since they have been rehydrated */ for (var _i = 0, _len = els.length; _i < _len; _i += 1) { var el = els[_i]; if (el.parentNode) { el.parentNode.removeChild(el); } } }; // var SPLIT_REGEX = /\s+/; /* determine the maximum number of components before tags are sharded */ var MAX_SIZE = void 0; if (IS_BROWSER) { /* in speedy mode we can keep a lot more rules in a sheet before a slowdown can be expected */ MAX_SIZE = DISABLE_SPEEDY ? 40 : 1000; } else { /* for servers we do not need to shard at all */ MAX_SIZE = -1; } var sheetRunningId = 0; var master = void 0; var StyleSheet = function () { /* a map from ids to tags */ /* deferred rules for a given id */ /* this is used for not reinjecting rules via hasNameForId() */ /* when rules for an id are removed using remove() we have to ignore rehydratedNames for it */ /* a list of tags belonging to this StyleSheet */ /* a tag for import rules */ /* current capacity until a new tag must be created */ /* children (aka clones) of this StyleSheet inheriting all and future injections */ function StyleSheet() { var _this = this; var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : IS_BROWSER ? document.head : null; var forceServer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; classCallCheck(this, StyleSheet); this.getImportRuleTag = function () { var importRuleTag = _this.importRuleTag; if (importRuleTag !== undefined) { return importRuleTag; } var firstTag = _this.tags[0]; var insertBefore = true; return _this.importRuleTag = makeTag(_this.target, firstTag ? firstTag.styleTag : null, _this.forceServer, insertBefore); }; sheetRunningId += 1; this.id = sheetRunningId; this.forceServer = forceServer; this.target = forceServer ? null : target; this.tagMap = {}; this.deferred = {}; this.rehydratedNames = {}; this.ignoreRehydratedNames = {}; this.tags = []; this.capacity = 1; this.clones = []; } /* rehydrate all SSR'd style tags */ StyleSheet.prototype.rehydrate = function rehydrate$$1() { if (!IS_BROWSER || this.forceServer) return this; var els = []; var extracted = []; var isStreamed = false; /* retrieve all of our SSR style elements from the DOM */ var nodes = document.querySelectorAll('style[' + SC_ATTR + '][' + SC_VERSION_ATTR + '="' + "4.4.1" + '"]'); var nodesSize = nodes.length; /* abort rehydration if no previous style tags were found */ if (!nodesSize) return this; for (var i = 0; i < nodesSize; i += 1) { var el = nodes[i]; /* check if style tag is a streamed tag */ if (!isStreamed) isStreamed = !!el.getAttribute(SC_STREAM_ATTR); /* retrieve all component names */ var elNames = (el.getAttribute(SC_ATTR) || '').trim().split(SPLIT_REGEX); var elNamesSize = elNames.length; for (var j = 0, name; j < elNamesSize; j += 1) { name = elNames[j]; /* add rehydrated name to sheet to avoid re-adding styles */ this.rehydratedNames[name] = true; } /* extract all components and their CSS */ extracted.push.apply(extracted, extractComps(el.textContent)); /* store original HTMLStyleElement */ els.push(el); } /* abort rehydration if nothing was extracted */ var extractedSize = extracted.length; if (!extractedSize) return this; /* create a tag to be used for rehydration */ var tag = this.makeTag(null); rehydrate(tag, els, extracted); /* reset capacity and adjust MAX_SIZE by the initial size of the rehydration */ this.capacity = Math.max(1, MAX_SIZE - extractedSize); this.tags.push(tag); /* retrieve all component ids */ for (var _j = 0; _j < extractedSize; _j += 1) { this.tagMap[extracted[_j].componentId] = tag; } return this; }; /* retrieve a "master" instance of StyleSheet which is typically used when no other is available * The master StyleSheet is targeted by createGlobalStyle, keyframes, and components outside of any * StyleSheetManager's context */ /* reset the internal "master" instance */ StyleSheet.reset = function reset() { var forceServer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; master = new StyleSheet(undefined, forceServer).rehydrate(); }; /* adds "children" to the StyleSheet that inherit all of the parents' rules * while their own rules do not affect the parent */ StyleSheet.prototype.clone = function clone() { var sheet = new StyleSheet(this.target, this.forceServer); /* add to clone array */ this.clones.push(sheet); /* clone all tags */ sheet.tags = this.tags.map(function (tag) { var ids = tag.getIds(); var newTag = tag.clone(); /* reconstruct tagMap */ for (var i = 0; i < ids.length; i += 1) { sheet.tagMap[ids[i]] = newTag; } return newTag; }); /* clone other maps */ sheet.rehydratedNames = _extends({}, this.rehydratedNames); sheet.deferred = _extends({}, this.deferred); return sheet; }; /* force StyleSheet to create a new tag on the next injection */ StyleSheet.prototype.sealAllTags = function sealAllTags() { this.capacity = 1; this.tags.forEach(function (tag) { // eslint-disable-next-line no-param-reassign tag.sealed = true; }); }; StyleSheet.prototype.makeTag = function makeTag$$1(tag) { var lastEl = tag ? tag.styleTag : null; var insertBefore = false; return makeTag(this.target, lastEl, this.forceServer, insertBefore, this.getImportRuleTag); }; /* get a tag for a given componentId, assign the componentId to one, or shard */ StyleSheet.prototype.getTagForId = function getTagForId(id) { /* simply return a tag, when the componentId was already assigned one */ var prev = this.tagMap[id]; if (prev !== undefined && !prev.sealed) { return prev; } var tag = this.tags[this.tags.length - 1]; /* shard (create a new tag) if the tag is exhausted (See MAX_SIZE) */ this.capacity -= 1; if (this.capacity === 0) { this.capacity = MAX_SIZE; tag = this.makeTag(tag); this.tags.push(tag); } return this.tagMap[id] = tag; }; /* mainly for createGlobalStyle to check for its id */ StyleSheet.prototype.hasId = function hasId(id) { return this.tagMap[id] !== undefined; }; /* caching layer checking id+name to already have a corresponding tag and injected rules */ StyleSheet.prototype.hasNameForId = function hasNameForId(id, name) { /* exception for rehydrated names which are checked separately */ if (this.ignoreRehydratedNames[id] === undefined && this.rehydratedNames[name]) { return true; } var tag = this.tagMap[id]; return tag !== undefined && tag.hasNameForId(id, name); }; /* registers a componentId and registers it on its tag */ StyleSheet.prototype.deferredInject = function deferredInject(id, cssRules) { /* don't inject when the id is already registered */ if (this.tagMap[id] !== undefined) return; var clones = this.clones; for (var i = 0; i < clones.length; i += 1) { clones[i].deferredInject(id, cssRules); } this.getTagForId(id).insertMarker(id); this.deferred[id] = cssRules; }; /* injects rules for a given id with a name that will need to be cached */ StyleSheet.prototype.inject = function inject(id, cssRules, name) { var clones = this.clones; for (var i = 0; i < clones.length; i += 1) { clones[i].inject(id, cssRules, name); } var tag = this.getTagForId(id); /* add deferred rules for component */ if (this.deferred[id] !== undefined) { // Combine passed cssRules with previously deferred CSS rules // NOTE: We cannot mutate the deferred array itself as all clones // do the same (see clones[i].inject) var rules = this.deferred[id].concat(cssRules); tag.insertRules(id, rules, name); this.deferred[id] = undefined; } else { tag.insertRules(id, cssRules, name); } }; /* removes all rules for a given id, which doesn't remove its marker but resets it */ StyleSheet.prototype.remove = function remove(id) { var tag = this.tagMap[id]; if (tag === undefined) return; var clones = this.clones; for (var i = 0; i < clones.length; i += 1) { clones[i].remove(id); } /* remove all rules from the tag */ tag.removeRules(id); /* ignore possible rehydrated names */ this.ignoreRehydratedNames[id] = true; /* delete possible deferred rules */ this.deferred[id] = undefined; }; StyleSheet.prototype.toHTML = function toHTML() { return this.tags.map(function (tag) { return tag.toHTML(); }).join(''); }; StyleSheet.prototype.toReactElements = function toReactElements() { var id = this.id; return this.tags.map(function (tag, i) { var key = 'sc-' + id + '-' + i; return React.cloneElement(tag.toElement(), { key: key }); }); }; createClass(StyleSheet, null, [{ key: 'master', get: function get$$1() { return master || (master = new StyleSheet().rehydrate()); } /* NOTE: This is just for backwards-compatibility with jest-styled-components */ }, { key: 'instance', get: function get$$1() { return StyleSheet.master; } }]); return StyleSheet; }(); // var Keyframes = function () { function Keyframes(name, rules) { var _this = this; classCallCheck(this, Keyframes); this.inject = function (styleSheet) { if (!styleSheet.hasNameForId(_this.id, _this.name)) { styleSheet.inject(_this.id, _this.rules, _this.name); } }; this.toString = function () { throw new StyledComponentsError(12, String(_this.name)); }; this.name = name; this.rules = rules; this.id = 'sc-keyframes-' + name; } Keyframes.prototype.getName = function getName() { return this.name; }; return Keyframes; }(); // /** * inlined version of * https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/hyphenateStyleName.js */ var uppercasePattern = /([A-Z])/g; var msPattern = /^ms-/; /** * Hyphenates a camelcased CSS property name, for example: * * > hyphenateStyleName('backgroundColor') * < "background-color" * > hyphenateStyleName('MozTransition') * < "-moz-transition" * > hyphenateStyleName('msTransition') * < "-ms-transition" * * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix * is converted to `-ms-`. * * @param {string} string * @return {string} */ function hyphenateStyleName(string) { return string.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern, '-ms-'); } // // Taken from https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/shared/dangerousStyleValue.js function addUnitIfNeeded(name, value) { // https://github.com/amilajack/eslint-plugin-flowtype-errors/issues/133 // $FlowFixMe if (value == null || typeof value === 'boolean' || value === '') { return ''; } if (typeof value === 'number' && value !== 0 && !(name in unitless)) { return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers } return String(value).trim(); } // /** * It's falsish not falsy because 0 is allowed. */ var isFalsish = function isFalsish(chunk) { return chunk === undefined || chunk === null || chunk === false || chunk === ''; }; var objToCssArray = function objToCssArray(obj, prevKey) { var rules = []; var keys = Object.keys(obj); keys.forEach(function (key) { if (!isFalsish(obj[key])) { if (isPlainObject(obj[key])) { rules.push.apply(rules, objToCssArray(obj[key], key)); return rules; } else if (isFunction(obj[key])) { rules.push(hyphenateStyleName(key) + ':', obj[key], ';'); return rules; } rules.push(hyphenateStyleName(key) + ': ' + addUnitIfNeeded(key, obj[key]) + ';'); } return rules; }); return prevKey ? [prevKey + ' {'].concat(rules, ['}']) : rules; }; function flatten(chunk, executionContext, styleSheet) { if (Array.isArray(chunk)) { var ruleSet = []; for (var i = 0, len = chunk.length, result; i < len; i += 1) { result = flatten(chunk[i], executionContext, styleSheet); if (result === null) continue;else if (Array.isArray(result)) ruleSet.push.apply(ruleSet, result);else ruleSet.push(result); } return ruleSet; } if (isFalsish(chunk)) { return null; } /* Handle other components */ if (isStyledComponent(chunk)) { return '.' + chunk.styledComponentId; } /* Either execute or defer the function */ if (isFunction(chunk)) { if (isStatelessFunction(chunk) && executionContext) { var _result = chunk(executionContext); if (process.env.NODE_ENV !== 'production' && reactIs.isElement(_result)) { // eslint-disable-next-line no-console console.warn(getComponentName(chunk) + ' is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.'); } return flatten(_result, executionContext, styleSheet); } else return chunk; } if (chunk instanceof Keyframes) { if (styleSheet) { chunk.inject(styleSheet); return chunk.getName(); } else return chunk; } /* Handle objects */ return isPlainObject(chunk) ? objToCssArray(chunk) : chunk.toString(); } // var printed = {}; function warnOnce(message) { if (printed[message]) return; printed[message] = true; if (typeof console !== 'undefined' && console.warn) console.warn(message); } // var SINGLE_QUOTE = "'".charCodeAt(0); var DOUBLE_QUOTE = '"'.charCodeAt(0); var BACKSLASH = '\\'.charCodeAt(0); var SLASH = '/'.charCodeAt(0); var NEWLINE = '\n'.charCodeAt(0); var SPACE = ' '.charCodeAt(0); var FEED = '\f'.charCodeAt(0); var TAB = '\t'.charCodeAt(0); var CR = '\r'.charCodeAt(0); var OPEN_SQUARE = '['.charCodeAt(0); var CLOSE_SQUARE = ']'.charCodeAt(0); var OPEN_PARENTHESES = '('.charCodeAt(0); var CLOSE_PARENTHESES = ')'.charCodeAt(0); var OPEN_CURLY = '{'.charCodeAt(0); var CLOSE_CURLY = '}'.charCodeAt(0); var SEMICOLON = ';'.charCodeAt(0); var ASTERISK = '*'.charCodeAt(0); var COLON = ':'.charCodeAt(0); var AT = '@'.charCodeAt(0); var RE_AT_END = /[ \n\t\r\f\{\(\)'"\\;/\[\]#]/g; var RE_WORD_END = /[ \n\t\r\f\(\)\{\}:;@!'"\\\]\[#]|\/(?=\*)/g; var RE_BAD_BRACKET = /.[\\\/\("'\n]/; function tokenize(input) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var tokens = []; var css = input.css.valueOf(); var ignore = options.ignoreErrors; var code = void 0, next = void 0, quote = void 0, lines = void 0, last = void 0, content = void 0, escape = void 0, nextLine = void 0, nextOffset = void 0, escaped = void 0, escapePos = void 0, prev = void 0, n = void 0; var length = css.length; var offset = -1; var line = 1; var pos = 0; function unclosed(what) { throw input.error('Unclosed ' + what, line, pos - offset); } while (pos < length) { code = css.charCodeAt(pos); if (code === NEWLINE || code === FEED || code === CR && css.charCodeAt(pos + 1) !== NEWLINE) { offset = pos; line += 1; } switch (code) { case NEWLINE: case SPACE: case TAB: case CR: case FEED: next = pos; do { next += 1; code = css.charCodeAt(next); if (code === NEWLINE) { offset = next; line += 1; } } while (code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED); tokens.push(['space', css.slice(pos, next)]); pos = next - 1; break; case OPEN_SQUARE: tokens.push(['[', '[', line, pos - offset]); break; case CLOSE_SQUARE: tokens.push([']', ']', line, pos - offset]); break; case OPEN_CURLY: tokens.push(['{', '{', line, pos - offset]); break; case CLOSE_CURLY: tokens.push(['}', '}', line, pos - offset]); break; case COLON: tokens.push([':', ':', line, pos - offset]); break; case SEMICOLON: tokens.push([';', ';', line, pos - offset]); break; case OPEN_PARENTHESES: prev = tokens.length ? tokens[tokens.length - 1][1] : ''; n = css.charCodeAt(pos + 1); if (prev === 'url' && n !== SINGLE_QUOTE && n !== DOUBLE_QUOTE && n !== SPACE && n !== NEWLINE && n !== TAB && n !== FEED && n !== CR) { next = pos; do { escaped = false; next = css.indexOf(')', next + 1); if (next === -1) { if (ignore) { next = pos; break; } else { unclosed('bracket'); } } escapePos = next; while (css.charCodeAt(escapePos - 1) === BACKSLASH) { escapePos -= 1; escaped = !escaped; } } while (escaped); tokens.push(['brackets', css.slice(pos, next + 1), line, pos - offset, line, next - offset]); pos = next; } else { next = css.indexOf(')', pos + 1); content = css.slice(pos, next + 1); if (next === -1 || RE_BAD_BRACKET.test(content)) { tokens.push(['(', '(', line, pos - offset]); } else { tokens.push(['brackets', content, line, pos - offset, line, next - offset]); pos = next; } } break; case CLOSE_PARENTHESES: tokens.push([')', ')', line, pos - offset]); break; case SINGLE_QUOTE: case DOUBLE_QUOTE: quote = code === SINGLE_QUOTE ? "'" : '"'; next = pos; do { escaped = false; next = css.indexOf(quote, next + 1); if (next === -1) { if (ignore) { next = pos + 1; break; } else { unclosed('quote'); } } escapePos = next; while (css.charCodeAt(escapePos - 1) === BACKSLASH) { escapePos -= 1; escaped = !escaped; } } while (escaped); content = css.slice(pos, next + 1); lines = content.split('\n'); last = lines.length - 1; if (last > 0) { nextLine = line + last; nextOffset = next - lines[last].length; } else { nextLine = line; nextOffset = offset; } tokens.push(['string', css.slice(pos, next + 1), line, pos - offset, nextLine, next - nextOffset]); offset = nextOffset; line = nextLine; pos = next; break; case AT: RE_AT_END.lastIndex = pos + 1; RE_AT_END.test(css); if (RE_AT_END.lastIndex === 0) { next = css.length - 1; } else { next = RE_AT_END.lastIndex - 2; } tokens.push(['at-word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]); pos = next; break; case BACKSLASH: next = pos; escape = true; while (css.charCodeAt(next + 1) === BACKSLASH) { next += 1; escape = !escape; } code = css.charCodeAt(next + 1); if (escape && code !== SLASH && code !== SPACE && code !== NEWLINE && code !== TAB && code !== CR && code !== FEED) { next += 1; } tokens.push(['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]); pos = next; break; default: if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) { next = css.indexOf('*/', pos + 2) + 1; if (next === 0) { if (ignore) { next = css.length; } else { unclosed('comment'); } } content = css.slice(pos, next + 1); lines = content.split('\n'); last = lines.length - 1; if (last > 0) { nextLine = line + last; nextOffset = next - lines[last].length; } else { nextLine = line; nextOffset = offset; } tokens.push(['comment', content, line, pos - offset, nextLine, next - nextOffset]); offset = nextOffset; line = nextLine; pos = next; } else { RE_WORD_END.lastIndex = pos + 1; RE_WORD_END.test(css); if (RE_WORD_END.lastIndex === 0) { next = css.length - 1; } else { next = RE_WORD_END.lastIndex - 2; } tokens.push(['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]); pos = next; } break; } pos++; } return tokens; } // var HIGHLIGHT_THEME = { brackets: [36, 39], // cyan string: [31, 39], // red 'at-word': [31, 39], // red comment: [90, 39], // gray '{': [32, 39], // green '}': [32, 39], // green ':': [1, 22], // bold ';': [1, 22], // bold '(': [1, 22], // bold ')': [1, 22] // bold }; function code(color) { return '\x1B[' + color + 'm'; } function terminalHighlight(css) { var tokens = tokenize(new Input(css), { ignoreErrors: true }); var result = []; tokens.forEach(function (token) { var color = HIGHLIGHT_THEME[token[0]]; if (color) { result.push(token[1].split(/\r?\n/).map(function (i) { return code(color[0]) + i + code(color[1]); }).join('\n')); } else { result.push(token[1]); } }); return result.join(''); } // /** * The CSS parser throws this error for broken CSS. * * Custom parsers can throw this error for broken custom syntax using * the {@link Node#error} method. * * PostCSS will use the input source map to detect the original error location. * If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS, * PostCSS will show the original position in the Sass file. * * If you need the position in the PostCSS input * (e.g., to debug the previous compiler), use `error.input.file`. * * @example * // Catching and checking syntax error * try { * postcss.parse('a{') * } catch (error) { * if ( error.name === 'CssSyntaxError' ) { * error //=> CssSyntaxError * } * } * * @example * // Raising error from plugin * throw node.error('Unknown variable', { plugin: 'postcss-vars' }); */ var CssSyntaxError = function () { /** * @param {string} message - error message * @param {number} [line] - source line of the error * @param {number} [column] - source column of the error * @param {string} [source] - source code of the broken file * @param {string} [file] - absolute path to the broken file * @param {string} [plugin] - PostCSS plugin name, if error came from plugin */ function CssSyntaxError(message, line, column, source, file, plugin) { classCallCheck(this, CssSyntaxError); /** * @member {string} - Always equal to `'CssSyntaxError'`. You should * always check error type * by `error.name === 'CssSyntaxError'` instead of * `error instanceof CssSyntaxError`, because * npm could have several PostCSS versions. * * @example * if ( error.name === 'CssSyntaxError' ) { * error //=> CssSyntaxError * } */ this.name = 'CssSyntaxError'; /** * @member {string} - Error message. * * @example * error.message //=> 'Unclosed block' */ this.reason = message; if (file) { /** * @member {string} - Absolute path to the broken file. * * @example * error.file //=> 'a.sass' * error.input.file //=> 'a.css' */ this.file = file; } if (source) { /** * @member {string} - Source code of the broken file. * * @example * error.source //=> 'a { b {} }' * error.input.column //=> 'a b { }' */ this.source = source; } if (plugin) { /** * @member {string} - Plugin name, if error came from plugin. * * @example * error.plugin //=> 'postcss-vars' */ this.plugin = plugin; } if (typeof line !== 'undefined' && typeof column !== 'undefined') { /** * @member {number} - Source line of the error. * * @example * error.line //=> 2 * error.input.line //=> 4 */ this.line = line; /** * @member {number} - Source column of the error. * * @example * error.column //=> 1 * error.input.column //=> 4 */ this.column = column; } this.setMessage(); if (Error.captureStackTrace) { Error.captureStackTrace(this, CssSyntaxError); } } CssSyntaxError.prototype.setMessage = function setMessage() { /** * @member {string} - Full error text in the GNU error format * with plugin, file, line and column. * * @example * error.message //=> 'a.css:1:1: Unclosed block' */ this.message = this.plugin ? this.plugin + ': ' : ''; this.message += this.file ? this.file : '*/
.
* * `important`: the content of the important statement,
* if it is not just `!important`.
*
* PostCSS cleans selectors, declaration values and at-rule parameters
* from comments and extra spaces, but it stores origin content in raws
* properties. As such, if you don’t change a declaration’s value,
* PostCSS will use the raw value with comments.
*
* @example
* const root = postcss.parse('a {\n color:black\n}')
* root.first.first.raws //=> { before: '\n ', between: ':' }
*/
}]);
return Node;
}();
//
/**
* Represents a CSS declaration.
*
* @extends Node
*
* @example
* const root = postcss.parse('a { color: black }');
* const decl = root.first.first;
* decl.type //=> 'decl'
* decl.toString() //=> ' color: black'
*/
var Declaration = function (_Node) {
inherits(Declaration, _Node);
function Declaration(defaults$$1) {
classCallCheck(this, Declaration);
var _this = possibleConstructorReturn(this, _Node.call(this, defaults$$1));
_this.type = 'decl';
return _this;
}
createClass(Declaration, [{
key: '_value',
get: function get$$1() {
warnOnce('Node#_value was deprecated. Use Node#raws.value');
return this.raws.value;
},
set: function set$$1(val) {
warnOnce('Node#_value was deprecated. Use Node#raws.value');
this.raws.value = val;
}
}, {
key: '_important',
get: function get$$1() {
warnOnce('Node#_important was deprecated. Use Node#raws.important');
return this.raws.important;
},
set: function set$$1(val) {
warnOnce('Node#_important was deprecated. Use Node#raws.important');
this.raws.important = val;
}
/**
* @memberof Declaration#
* @member {string} prop - the declaration’s property name
*
* @example
* const root = postcss.parse('a { color: black }');
* const decl = root.first.first;
* decl.prop //=> 'color'
*/
/**
* @memberof Declaration#
* @member {string} value - the declaration’s value
*
* @example
* const root = postcss.parse('a { color: black }');
* const decl = root.first.first;
* decl.value //=> 'black'
*/
/**
* @memberof Declaration#
* @member {boolean} important - `true` if the declaration
* has an !important annotation.
*
* @example
* const root = postcss.parse('a { color: black !important; color: red }');
* root.first.first.important //=> true
* root.first.last.important //=> undefined
*/
/**
* @memberof Declaration#
* @member {object} raws - Information to generate byte-to-byte equal
* node string as it was in the origin input.
*
* Every parser saves its own properties,
* but the default CSS parser uses:
*
* * `before`: the space symbols before the node. It also stores `*`
* and `_` symbols before the declaration (IE hack).
* * `between`: the symbols between the property and value
* for declarations, selector and `{` for rules, or last parameter
* and `{` for at-rules.
* * `important`: the content of the important statement,
* if it is not just `!important`.
*
* PostCSS cleans declaration from comments and extra spaces,
* but it stores origin content in raws properties.
* As such, if you don’t change a declaration’s value,
* PostCSS will use the raw value with comments.
*
* @example
* const root = postcss.parse('a {\n color:black\n}')
* root.first.first.raws //=> { before: '\n ', between: ':' }
*/
}]);
return Declaration;
}(Node);
//
/**
* Represents a comment between declarations or statements (rule and at-rules).
*
* Comments inside selectors, at-rule parameters, or declaration values
* will be stored in the `raws` properties explained above.
*
* @extends Node
*/
var Comment = function (_Node) {
inherits(Comment, _Node);
function Comment(defaults$$1) {
classCallCheck(this, Comment);
var _this = possibleConstructorReturn(this, _Node.call(this, defaults$$1));
_this.type = 'comment';
return _this;
}
createClass(Comment, [{
key: 'left',
get: function get$$1() {
warnOnce('Comment#left was deprecated. Use Comment#raws.left');
return this.raws.left;
},
set: function set$$1(val) {
warnOnce('Comment#left was deprecated. Use Comment#raws.left');
this.raws.left = val;
}
}, {
key: 'right',
get: function get$$1() {
warnOnce('Comment#right was deprecated. Use Comment#raws.right');
return this.raws.right;
},
set: function set$$1(val) {
warnOnce('Comment#right was deprecated. Use Comment#raws.right');
this.raws.right = val;
}
/**
* @memberof Comment#
* @member {string} text - the comment’s text
*/
/**
* @memberof Comment#
* @member {object} raws - Information to generate byte-to-byte equal
* node string as it was in the origin input.
*
* Every parser saves its own properties,
* but the default CSS parser uses:
*
* * `before`: the space symbols before the node.
* * `left`: the space symbols between `/*` and the comment’s text.
* * `right`: the space symbols between the comment’s text.
*/
}]);
return Comment;
}(Node);
//
var Parser = function () {
function Parser(input) {
classCallCheck(this, Parser);
this.input = input;
this.pos = 0;
this.root = new Root();
this.current = this.root;
this.spaces = '';
this.semicolon = false;
this.root.source = { input: input, start: { line: 1, column: 1 } };
}
Parser.prototype.tokenize = function tokenize$$1() {
this.tokens = tokenize(this.input);
};
Parser.prototype.loop = function loop() {
var token = void 0;
while (this.pos < this.tokens.length) {
token = this.tokens[this.pos];
switch (token[0]) {
case 'space':
case ';':
this.spaces += token[1];
break;
case '}':
this.end(token);
break;
case 'comment':
this.comment(token);
break;
case 'at-word':
this.atrule(token);
break;
case '{':
this.emptyRule(token);
break;
default:
this.other();
break;
}
this.pos += 1;
}
this.endFile();
};
Parser.prototype.comment = function comment(token) {
var node = new Comment();
this.init(node, token[2], token[3]);
node.source.end = { line: token[4], column: token[5] };
var text = token[1].slice(2, -2);
if (/^\s*$/.test(text)) {
node.text = '';
node.raws.left = text;
node.raws.right = '';
} else {
var match = text.match(/^(\s*)([^]*[^\s])(\s*)$/);
node.text = match[2];
node.raws.left = match[1];
node.raws.right = match[3];
}
};
Parser.prototype.emptyRule = function emptyRule(token) {
var node = new Rule();
this.init(node, token[2], token[3]);
node.selector = '';
node.raws.between = '';
this.current = node;
};
Parser.prototype.other = function other() {
var token = void 0;
var end = false;
var type = null;
var colon = false;
var bracket = null;
var brackets = [];
var start = this.pos;
while (this.pos < this.tokens.length) {
token = this.tokens[this.pos];
type = token[0];
if (type === '(' || type === '[') {
if (!bracket) bracket = token;
brackets.push(type === '(' ? ')' : ']');
} else if (brackets.length === 0) {
if (type === ';') {
if (colon) {
this.decl(this.tokens.slice(start, this.pos + 1));
return;
} else {
break;
}
} else if (type === '{') {
this.rule(this.tokens.slice(start, this.pos + 1));
return;
} else if (type === '}') {
this.pos -= 1;
end = true;
break;
} else if (type === ':') {
colon = true;
}
} else if (type === brackets[brackets.length - 1]) {
brackets.pop();
if (brackets.length === 0) bracket = null;
}
this.pos += 1;
}
if (this.pos === this.tokens.length) {
this.pos -= 1;
end = true;
}
if (brackets.length > 0) this.unclosedBracket(bracket);
if (end && colon) {
while (this.pos > start) {
token = this.tokens[this.pos][0];
if (token !== 'space' && token !== 'comment') break;
this.pos -= 1;
}
this.decl(this.tokens.slice(start, this.pos + 1));
return;
}
this.unknownWord(start);
};
Parser.prototype.rule = function rule(tokens) {
tokens.pop();
var node = new Rule();
this.init(node, tokens[0][2], tokens[0][3]);
node.raws.between = this.spacesFromEnd(tokens);
this.raw(node, 'selector', tokens);
this.current = node;
};
Parser.prototype.decl = function decl(tokens) {
var node = new Declaration();
this.init(node);
var last = tokens[tokens.length - 1];
if (last[0] === ';') {
this.semicolon = true;
tokens.pop();
}
if (last[4]) {
node.source.end = { line: last[4], column: last[5] };
} else {
node.source.end = { line: last[2], column: last[3] };
}
while (tokens[0][0] !== 'word') {
node.raws.before += tokens.shift()[1];
}
node.source.start = { line: tokens[0][2], column: tokens[0][3] };
node.prop = '';
while (tokens.length) {
var type = tokens[0][0];
if (type === ':' || type === 'space' || type === 'comment') {
break;
}
node.prop += tokens.shift()[1];
}
node.raws.between = '';
var token = void 0;
while (tokens.length) {
token = tokens.shift();
if (token[0] === ':') {
node.raws.between += token[1];
break;
} else {
node.raws.between += token[1];
}
}
if (node.prop[0] === '_' || node.prop[0] === '*') {
node.raws.before += node.prop[0];
node.prop = node.prop.slice(1);
}
node.raws.between += this.spacesFromStart(tokens);
this.precheckMissedSemicolon(tokens);
for (var i = tokens.length - 1; i > 0; i--) {
token = tokens[i];
if (token[1] === '!important') {
node.important = true;
var string = this.stringFrom(tokens, i);
string = this.spacesFromEnd(tokens) + string;
if (string !== ' !important') node.raws.important = string;
break;
} else if (token[1] === 'important') {
var cache = tokens.slice(0);
var str = '';
for (var j = i; j > 0; j--) {
var _type = cache[j][0];
if (str.trim().indexOf('!') === 0 && _type !== 'space') {
break;
}
str = cache.pop()[1] + str;
}
if (str.trim().indexOf('!') === 0) {
node.important = true;
node.raws.important = str;
tokens = cache;
}
}
if (token[0] !== 'space' && token[0] !== 'comment') {
break;
}
}
this.raw(node, 'value', tokens);
if (node.value.indexOf(':') !== -1) this.checkMissedSemicolon(tokens);
};
Parser.prototype.atrule = function atrule(token) {
var node = new AtRule();
node.name = token[1].slice(1);
if (node.name === '') {
this.unnamedAtrule(node, token);
}
this.init(node, token[2], token[3]);
var last = false;
var open = false;
var params = [];
this.pos += 1;
while (this.pos < this.tokens.length) {
token = this.tokens[this.pos];
if (token[0] === ';') {
node.source.end = { line: token[2], column: token[3] };
this.semicolon = true;
break;
} else if (token[0] === '{') {
open = true;
break;
} else if (token[0] === '}') {
this.end(token);
break;
} else {
params.push(token);
}
this.pos += 1;
}
if (this.pos === this.tokens.length) {
last = true;
}
node.raws.between = this.spacesFromEnd(params);
if (params.length) {
node.raws.afterName = this.spacesFromStart(params);
this.raw(node, 'params', params);
if (last) {
token = params[params.length - 1];
node.source.end = { line: token[4], column: token[5] };
this.spaces = node.raws.between;
node.raws.between = '';
}
} else {
node.raws.afterName = '';
node.params = '';
}
if (open) {
node.nodes = [];
this.current = node;
}
};
Parser.prototype.end = function end(token) {
if (this.current.nodes && this.current.nodes.length) {
this.current.raws.semicolon = this.semicolon;
}
this.semicolon = false;
this.current.raws.after = (this.current.raws.after || '') + this.spaces;
this.spaces = '';
if (this.current.parent) {
this.current.source.end = { line: token[2], column: token[3] };
this.current = this.current.parent;
} else {
this.unexpectedClose(token);
}
};
Parser.prototype.endFile = function endFile() {
if (this.current.parent) this.unclosedBlock();
if (this.current.nodes && this.current.nodes.length) {
this.current.raws.semicolon = this.semicolon;
}
this.current.raws.after = (this.current.raws.after || '') + this.spaces;
};
// Helpers
Parser.prototype.init = function init(node, line, column) {
this.current.push(node);
node.source = { start: { line: line, column: column }, input: this.input };
node.raws.before = this.spaces;
this.spaces = '';
if (node.type !== 'comment') this.semicolon = false;
};
Parser.prototype.raw = function raw(node, prop, tokens) {
var token = void 0,
type = void 0;
var length = tokens.length;
var value = '';
var clean = true;
for (var i = 0; i < length; i += 1) {
token = tokens[i];
type = token[0];
if (type === 'comment' || type === 'space' && i === length - 1) {
clean = false;
} else {
value += token[1];
}
}
if (!clean) {
var raw = tokens.reduce(function (all, i) {
return all + i[1];
}, '');
node.raws[prop] = { value: value, raw: raw };
}
node[prop] = value;
};
Parser.prototype.spacesFromEnd = function spacesFromEnd(tokens) {
var lastTokenType = void 0;
var spaces = '';
while (tokens.length) {
lastTokenType = tokens[tokens.length - 1][0];
if (lastTokenType !== 'space' && lastTokenType !== 'comment') break;
spaces = tokens.pop()[1] + spaces;
}
return spaces;
};
Parser.prototype.spacesFromStart = function spacesFromStart(tokens) {
var next = void 0;
var spaces = '';
while (tokens.length) {
next = tokens[0][0];
if (next !== 'space' && next !== 'comment') break;
spaces += tokens.shift()[1];
}
return spaces;
};
Parser.prototype.stringFrom = function stringFrom(tokens, from) {
var result = '';
for (var i = from; i < tokens.length; i++) {
result += tokens[i][1];
}
tokens.splice(from, tokens.length - from);
return result;
};
Parser.prototype.colon = function colon(tokens) {
var brackets = 0;
var token = void 0,
type = void 0,
prev = void 0;
for (var i = 0; i < tokens.length; i++) {
token = tokens[i];
type = token[0];
if (type === '(') {
brackets += 1;
} else if (type === ')') {
brackets -= 1;
} else if (brackets === 0 && type === ':') {
if (!prev) {
this.doubleColon(token);
} else if (prev[0] === 'word' && prev[1] === 'progid') {
continue;
} else {
return i;
}
}
prev = token;
}
return false;
};
// Errors
Parser.prototype.unclosedBracket = function unclosedBracket(bracket) {
throw this.input.error('Unclosed bracket', bracket[2], bracket[3]);
};
Parser.prototype.unknownWord = function unknownWord(start) {
var token = this.tokens[start];
throw this.input.error('Unknown word', token[2], token[3]);
};
Parser.prototype.unexpectedClose = function unexpectedClose(token) {
throw this.input.error('Unexpected }', token[2], token[3]);
};
Parser.prototype.unclosedBlock = function unclosedBlock() {
var pos = this.current.source.start;
throw this.input.error('Unclosed block', pos.line, pos.column);
};
Parser.prototype.doubleColon = function doubleColon(token) {
throw this.input.error('Double colon', token[2], token[3]);
};
Parser.prototype.unnamedAtrule = function unnamedAtrule(node, token) {
throw this.input.error('At-rule without name', token[2], token[3]);
};
Parser.prototype.precheckMissedSemicolon = function precheckMissedSemicolon(tokens) {
};
Parser.prototype.checkMissedSemicolon = function checkMissedSemicolon(tokens) {
var colon = this.colon(tokens);
if (colon === false) return;
var founded = 0;
var token = void 0;
for (var j = colon - 1; j >= 0; j--) {
token = tokens[j];
if (token[0] !== 'space') {
founded += 1;
if (founded === 2) break;
}
}
throw this.input.error('Missed semicolon', token[2], token[3]);
};
return Parser;
}();
//
function parse(css, opts) {
if (opts && opts.safe) {
throw new Error('Option safe was removed. ' + 'Use parser: require("postcss-safe-parser")');
}
var input = new Input(css, opts);
var parser = new Parser(input);
try {
parser.tokenize();
parser.loop();
} catch (e) {
if (e.name === 'CssSyntaxError' && opts && opts.from) {
if (/\.scss$/i.test(opts.from)) {
e.message += '\nYou tried to parse SCSS with ' + 'the standard CSS parser; ' + 'try again with the postcss-scss parser';
} else if (/\.less$/i.test(opts.from)) {
e.message += '\nYou tried to parse Less with ' + 'the standard CSS parser; ' + 'try again with the postcss-less parser';
}
}
throw e;
}
return parser.root;
}
//
function cleanSource(nodes) {
return nodes.map(function (i) {
if (i.nodes) i.nodes = cleanSource(i.nodes);
delete i.source;
return i;
});
}
/**
* @callback childCondition
* @param {Node} node - container child
* @param {number} index - child index
* @param {Node[]} nodes - all container children
* @return {boolean}
*/
/**
* @callback childIterator
* @param {Node} node - container child
* @param {number} index - child index
* @return {false|undefined} returning `false` will break iteration
*/
/**
* The {@link Root}, {@link AtRule}, and {@link Rule} container nodes
* inherit some common methods to help work with their children.
*
* Note that all containers can store any content. If you write a rule inside
* a rule, PostCSS will parse it.
*
* @extends Node
* @abstract
*/
var Container = function (_Node) {
inherits(Container, _Node);
function Container() {
classCallCheck(this, Container);
return possibleConstructorReturn(this, _Node.apply(this, arguments));
}
Container.prototype.push = function push(child) {
child.parent = this;
this.nodes.push(child);
return this;
};
/**
* Iterates through the container’s immediate children,
* calling `callback` for each child.
*
* Returning `false` in the callback will break iteration.
*
* This method only iterates through the container’s immediate children.
* If you need to recursively iterate through all the container’s descendant
* nodes, use {@link Container#walk}.
*
* Unlike the for `{}`-cycle or `Array#forEach` this iterator is safe
* if you are mutating the array of child nodes during iteration.
* PostCSS will adjust the current index to match the mutations.
*
* @param {childIterator} callback - iterator receives each node and index
*
* @return {false|undefined} returns `false` if iteration was broke
*
* @example
* const root = postcss.parse('a { color: black; z-index: 1 }');
* const rule = root.first;
*
* for ( let decl of rule.nodes ) {
* decl.cloneBefore({ prop: '-webkit-' + decl.prop });
* // Cycle will be infinite, because cloneBefore moves the current node
* // to the next index
* }
*
* rule.each(decl => {
* decl.cloneBefore({ prop: '-webkit-' + decl.prop });
* // Will be executed only for color and z-index
* });
*/
Container.prototype.each = function each(callback) {
if (!this.lastEach) this.lastEach = 0;
if (!this.indexes) this.indexes = {};
this.lastEach += 1;
var id = this.lastEach;
this.indexes[id] = 0;
if (!this.nodes) return undefined;
var index = void 0,
result = void 0;
while (this.indexes[id] < this.nodes.length) {
index = this.indexes[id];
result = callback(this.nodes[index], index);
if (result === false) break;
this.indexes[id] += 1;
}
delete this.indexes[id];
return result;
};
/**
* Traverses the container’s descendant nodes, calling callback
* for each node.
*
* Like container.each(), this method is safe to use
* if you are mutating arrays during iteration.
*
* If you only need to iterate through the container’s immediate children,
* use {@link Container#each}.
*
* @param {childIterator} callback - iterator receives each node and index
*
* @return {false|undefined} returns `false` if iteration was broke
*
* @example
* root.walk(node => {
* // Traverses all descendant nodes.
* });
*/
Container.prototype.walk = function walk(callback) {
return this.each(function (child, i) {
var result = callback(child, i);
if (result !== false && child.walk) {
result = child.walk(callback);
}
return result;
});
};
/**
* Traverses the container’s descendant nodes, calling callback
* for each declaration node.
*
* If you pass a filter, iteration will only happen over declarations
* with matching properties.
*
* Like {@link Container#each}, this method is safe
* to use if you are mutating arrays during iteration.
*
* @param {string|RegExp} [prop] - string or regular expression
* to filter declarations by property name
* @param {childIterator} callback - iterator receives each node and index
*
* @return {false|undefined} returns `false` if iteration was broke
*
* @example
* root.walkDecls(decl => {
* checkPropertySupport(decl.prop);
* });
*
* root.walkDecls('border-radius', decl => {
* decl.remove();
* });
*
* root.walkDecls(/^background/, decl => {
* decl.value = takeFirstColorFromGradient(decl.value);
* });
*/
Container.prototype.walkDecls = function walkDecls(prop, callback) {
if (!callback) {
callback = prop;
return this.walk(function (child, i) {
if (child.type === 'decl') {
return callback(child, i);
}
});
} else if (prop instanceof RegExp) {
return this.walk(function (child, i) {
if (child.type === 'decl' && prop.test(child.prop)) {
return callback(child, i);
}
});
} else {
return this.walk(function (child, i) {
if (child.type === 'decl' && child.prop === prop) {
return callback(child, i);
}
});
}
};
/**
* Traverses the container’s descendant nodes, calling callback
* for each rule node.
*
* If you pass a filter, iteration will only happen over rules
* with matching selectors.
*
* Like {@link Container#each}, this method is safe
* to use if you are mutating arrays during iteration.
*
* @param {string|RegExp} [selector] - string or regular expression
* to filter rules by selector
* @param {childIterator} callback - iterator receives each node and index
*
* @return {false|undefined} returns `false` if iteration was broke
*
* @example
* const selectors = [];
* root.walkRules(rule => {
* selectors.push(rule.selector);
* });
* console.log(`Your CSS uses ${selectors.length} selectors`);
*/
Container.prototype.walkRules = function walkRules(selector, callback) {
if (!callback) {
callback = selector;
return this.walk(function (child, i) {
if (child.type === 'rule') {
return callback(child, i);
}
});
} else if (selector instanceof RegExp) {
return this.walk(function (child, i) {
if (child.type === 'rule' && selector.test(child.selector)) {
return callback(child, i);
}
});
} else {
return this.walk(function (child, i) {
if (child.type === 'rule' && child.selector === selector) {
return callback(child, i);
}
});
}
};
/**
* Traverses the container’s descendant nodes, calling callback
* for each at-rule node.
*
* If you pass a filter, iteration will only happen over at-rules
* that have matching names.
*
* Like {@link Container#each}, this method is safe
* to use if you are mutating arrays during iteration.
*
* @param {string|RegExp} [name] - string or regular expression
* to filter at-rules by name
* @param {childIterator} callback - iterator receives each node and index
*
* @return {false|undefined} returns `false` if iteration was broke
*
* @example
* root.walkAtRules(rule => {
* if ( isOld(rule.name) ) rule.remove();
* });
*
* let first = false;
* root.walkAtRules('charset', rule => {
* if ( !first ) {
* first = true;
* } else {
* rule.remove();
* }
* });
*/
Container.prototype.walkAtRules = function walkAtRules(name, callback) {
if (!callback) {
callback = name;
return this.walk(function (child, i) {
if (child.type === 'atrule') {
return callback(child, i);
}
});
} else if (name instanceof RegExp) {
return this.walk(function (child, i) {
if (child.type === 'atrule' && name.test(child.name)) {
return callback(child, i);
}
});
} else {
return this.walk(function (child, i) {
if (child.type === 'atrule' && child.name === name) {
return callback(child, i);
}
});
}
};
/**
* Traverses the container’s descendant nodes, calling callback
* for each comment node.
*
* Like {@link Container#each}, this method is safe
* to use if you are mutating arrays during iteration.
*
* @param {childIterator} callback - iterator receives each node and index
*
* @return {false|undefined} returns `false` if iteration was broke
*
* @example
* root.walkComments(comment => {
* comment.remove();
* });
*/
Container.prototype.walkComments = function walkComments(callback) {
return this.walk(function (child, i) {
if (child.type === 'comment') {
return callback(child, i);
}
});
};
/**
* Inserts new nodes to the start of the container.
*
* @param {...(Node|object|string|Node[])} children - new nodes
*
* @return {Node} this node for methods chain
*
* @example
* const decl1 = postcss.decl({ prop: 'color', value: 'black' });
* const decl2 = postcss.decl({ prop: 'background-color', value: 'white' });
* rule.append(decl1, decl2);
*
* root.append({ name: 'charset', params: '"UTF-8"' }); // at-rule
* root.append({ selector: 'a' }); // rule
* rule.append({ prop: 'color', value: 'black' }); // declaration
* rule.append({ text: 'Comment' }) // comment
*
* root.append('a {}');
* root.first.append('color: black; z-index: 1');
*/
Container.prototype.append = function append() {
var _this2 = this;
for (var _len = arguments.length, children = Array(_len), _key = 0; _key < _len; _key++) {
children[_key] = arguments[_key];
}
children.forEach(function (child) {
var nodes = _this2.normalize(child, _this2.last);
nodes.forEach(function (node) {
return _this2.nodes.push(node);
});
});
return this;
};
/**
* Inserts new nodes to the end of the container.
*
* @param {...(Node|object|string|Node[])} children - new nodes
*
* @return {Node} this node for methods chain
*
* @example
* const decl1 = postcss.decl({ prop: 'color', value: 'black' });
* const decl2 = postcss.decl({ prop: 'background-color', value: 'white' });
* rule.prepend(decl1, decl2);
*
* root.append({ name: 'charset', params: '"UTF-8"' }); // at-rule
* root.append({ selector: 'a' }); // rule
* rule.append({ prop: 'color', value: 'black' }); // declaration
* rule.append({ text: 'Comment' }) // comment
*
* root.append('a {}');
* root.first.append('color: black; z-index: 1');
*/
Container.prototype.prepend = function prepend() {
var _this3 = this;
for (var _len2 = arguments.length, children = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
children[_key2] = arguments[_key2];
}
children = children.reverse();
children.forEach(function (child) {
var nodes = _this3.normalize(child, _this3.first, 'prepend').reverse();
nodes.forEach(function (node) {
return _this3.nodes.unshift(node);
});
for (var id in _this3.indexes) {
_this3.indexes[id] = _this3.indexes[id] + nodes.length;
}
});
return this;
};
Container.prototype.cleanRaws = function cleanRaws(keepBetween) {
_Node.prototype.cleanRaws.call(this, keepBetween);
if (this.nodes) {
this.nodes.forEach(function (node) {
return node.cleanRaws(keepBetween);
});
}
};
/**
* Insert new node before old node within the container.
*
* @param {Node|number} exist - child or child’s index.
* @param {Node|object|string|Node[]} add - new node
*
* @return {Node} this node for methods chain
*
* @example
* rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop }));
*/
Container.prototype.insertBefore = function insertBefore(exist, add) {
var _this4 = this;
exist = this.index(exist);
var type = exist === 0 ? 'prepend' : false;
var nodes = this.normalize(add, this.nodes[exist], type).reverse();
nodes.forEach(function (node) {
return _this4.nodes.splice(exist, 0, node);
});
var index = void 0;
for (var id in this.indexes) {
index = this.indexes[id];
if (exist <= index) {
this.indexes[id] = index + nodes.length;
}
}
return this;
};
/**
* Insert new node after old node within the container.
*
* @param {Node|number} exist - child or child’s index
* @param {Node|object|string|Node[]} add - new node
*
* @return {Node} this node for methods chain
*/
Container.prototype.insertAfter = function insertAfter(exist, add) {
var _this5 = this;
exist = this.index(exist);
var nodes = this.normalize(add, this.nodes[exist]).reverse();
nodes.forEach(function (node) {
return _this5.nodes.splice(exist + 1, 0, node);
});
var index = void 0;
for (var id in this.indexes) {
index = this.indexes[id];
if (exist < index) {
this.indexes[id] = index + nodes.length;
}
}
return this;
};
Container.prototype.remove = function remove(child) {
if (typeof child !== 'undefined') {
warnOnce('Container#remove is deprecated. ' + 'Use Container#removeChild');
this.removeChild(child);
} else {
_Node.prototype.remove.call(this);
}
return this;
};
/**
* Removes node from the container and cleans the parent properties
* from the node and its children.
*
* @param {Node|number} child - child or child’s index
*
* @return {Node} this node for methods chain
*
* @example
* rule.nodes.length //=> 5
* rule.removeChild(decl);
* rule.nodes.length //=> 4
* decl.parent //=> undefined
*/
Container.prototype.removeChild = function removeChild(child) {
child = this.index(child);
this.nodes[child].parent = undefined;
this.nodes.splice(child, 1);
var index = void 0;
for (var id in this.indexes) {
index = this.indexes[id];
if (index >= child) {
this.indexes[id] = index - 1;
}
}
return this;
};
/**
* Removes all children from the container
* and cleans their parent properties.
*
* @return {Node} this node for methods chain
*
* @example
* rule.removeAll();
* rule.nodes.length //=> 0
*/
Container.prototype.removeAll = function removeAll() {
this.nodes.forEach(function (node) {
return node.parent = undefined;
});
this.nodes = [];
return this;
};
/**
* Passes all declaration values within the container that match pattern
* through callback, replacing those values with the returned result
* of callback.
*
* This method is useful if you are using a custom unit or function
* and need to iterate through all values.
*
* @param {string|RegExp} pattern - replace pattern
* @param {object} opts - options to speed up the search
* @param {string|string[]} opts.props - an array of property names
* @param {string} opts.fast - string that’s used
* to narrow down values and speed up
the regexp search
* @param {function|string} callback - string to replace pattern
* or callback that returns a new
* value.
* The callback will receive
* the same arguments as those
* passed to a function parameter
* of `String#replace`.
*
* @return {Node} this node for methods chain
*
* @example
* root.replaceValues(/\d+rem/, { fast: 'rem' }, string => {
* return 15 * parseInt(string) + 'px';
* });
*/
Container.prototype.replaceValues = function replaceValues(pattern, opts, callback) {
if (!callback) {
callback = opts;
opts = {};
}
this.walkDecls(function (decl) {
if (opts.props && opts.props.indexOf(decl.prop) === -1) return;
if (opts.fast && decl.value.indexOf(opts.fast) === -1) return;
decl.value = decl.value.replace(pattern, callback);
});
return this;
};
/**
* Returns `true` if callback returns `true`
* for all of the container’s children.
*
* @param {childCondition} condition - iterator returns true or false.
*
* @return {boolean} is every child pass condition
*
* @example
* const noPrefixes = rule.every(i => i.prop[0] !== '-');
*/
Container.prototype.every = function every(condition) {
return this.nodes.every(condition);
};
/**
* Returns `true` if callback returns `true` for (at least) one
* of the container’s children.
*
* @param {childCondition} condition - iterator returns true or false.
*
* @return {boolean} is some child pass condition
*
* @example
* const hasPrefix = rule.some(i => i.prop[0] === '-');
*/
Container.prototype.some = function some(condition) {
return this.nodes.some(condition);
};
/**
* Returns a `child`’s index within the {@link Container#nodes} array.
*
* @param {Node} child - child of the current container.
*
* @return {number} child index
*
* @example
* rule.index( rule.nodes[2] ) //=> 2
*/
Container.prototype.index = function index(child) {
if (typeof child === 'number') {
return child;
} else {
return this.nodes.indexOf(child);
}
};
/**
* The container’s first child.
*
* @type {Node}
*
* @example
* rule.first == rules.nodes[0];
*/
Container.prototype.normalize = function normalize(nodes, sample) {
var _this6 = this;
if (typeof nodes === 'string') {
nodes = cleanSource(parse(nodes).nodes);
} else if (!Array.isArray(nodes)) {
if (nodes.type === 'root') {
nodes = nodes.nodes;
} else if (nodes.type) {
nodes = [nodes];
} else if (nodes.prop) {
if (typeof nodes.value === 'undefined') {
throw new Error('Value field is missed in node creation');
} else if (typeof nodes.value !== 'string') {
nodes.value = String(nodes.value);
}
nodes = [new Declaration(nodes)];
} else if (nodes.selector) {
nodes = [new Rule(nodes)];
} else if (nodes.name) {
nodes = [new AtRule(nodes)];
} else if (nodes.text) {
nodes = [new Comment(nodes)];
} else {
throw new Error('Unknown node type in node creation');
}
}
var processed = nodes.map(function (i) {
if (typeof i.raws === 'undefined') i = _this6.rebuild(i);
if (i.parent) i = i.clone();
if (typeof i.raws.before === 'undefined') {
if (sample && typeof sample.raws.before !== 'undefined') {
i.raws.before = sample.raws.before.replace(/[^\s]/g, '');
}
}
i.parent = _this6;
return i;
});
return processed;
};
Container.prototype.rebuild = function rebuild(node, parent) {
var _this7 = this;
var fix = void 0;
if (node.type === 'root') {
fix = new Root();
} else if (node.type === 'atrule') {
fix = new AtRule();
} else if (node.type === 'rule') {
fix = new Rule();
} else if (node.type === 'decl') {
fix = new Declaration();
} else if (node.type === 'comment') {
fix = new Comment();
}
for (var i in node) {
if (i === 'nodes') {
fix.nodes = node.nodes.map(function (j) {
return _this7.rebuild(j, fix);
});
} else if (i === 'parent' && parent) {
fix.parent = parent;
} else if (node.hasOwnProperty(i)) {
fix[i] = node[i];
}
}
return fix;
};
Container.prototype.eachInside = function eachInside(callback) {
warnOnce('Container#eachInside is deprecated. ' + 'Use Container#walk instead.');
return this.walk(callback);
};
Container.prototype.eachDecl = function eachDecl(prop, callback) {
warnOnce('Container#eachDecl is deprecated. ' + 'Use Container#walkDecls instead.');
return this.walkDecls(prop, callback);
};
Container.prototype.eachRule = function eachRule(selector, callback) {
warnOnce('Container#eachRule is deprecated. ' + 'Use Container#walkRules instead.');
return this.walkRules(selector, callback);
};
Container.prototype.eachAtRule = function eachAtRule(name, callback) {
warnOnce('Container#eachAtRule is deprecated. ' + 'Use Container#walkAtRules instead.');
return this.walkAtRules(name, callback);
};
Container.prototype.eachComment = function eachComment(callback) {
warnOnce('Container#eachComment is deprecated. ' + 'Use Container#walkComments instead.');
return this.walkComments(callback);
};
createClass(Container, [{
key: 'first',
get: function get$$1() {
if (!this.nodes) return undefined;
return this.nodes[0];
}
/**
* The container’s last child.
*
* @type {Node}
*
* @example
* rule.last == rule.nodes[rule.nodes.length - 1];
*/
}, {
key: 'last',
get: function get$$1() {
if (!this.nodes) return undefined;
return this.nodes[this.nodes.length - 1];
}
}, {
key: 'semicolon',
get: function get$$1() {
warnOnce('Node#semicolon is deprecated. Use Node#raws.semicolon');
return this.raws.semicolon;
},
set: function set$$1(val) {
warnOnce('Node#semicolon is deprecated. Use Node#raws.semicolon');
this.raws.semicolon = val;
}
}, {
key: 'after',
get: function get$$1() {
warnOnce('Node#after is deprecated. Use Node#raws.after');
return this.raws.after;
},
set: function set$$1(val) {
warnOnce('Node#after is deprecated. Use Node#raws.after');
this.raws.after = val;
}
/**
* @memberof Container#
* @member {Node[]} nodes - an array containing the container’s children
*
* @example
* const root = postcss.parse('a { color: black }');
* root.nodes.length //=> 1
* root.nodes[0].selector //=> 'a'
* root.nodes[0].nodes[0].prop //=> 'color'
*/
}]);
return Container;
}(Node);
//
/**
* Represents an at-rule.
*
* If it’s followed in the CSS by a {} block, this node will have
* a nodes property representing its children.
*
* @extends Container
*
* @example
* const root = postcss.parse('@charset "UTF-8"; @media print {}');
*
* const charset = root.first;
* charset.type //=> 'atrule'
* charset.nodes //=> undefined
*
* const media = root.last;
* media.nodes //=> []
*/
var AtRule = function (_Container) {
inherits(AtRule, _Container);
function AtRule(defaults$$1) {
classCallCheck(this, AtRule);
var _this = possibleConstructorReturn(this, _Container.call(this, defaults$$1));
_this.type = 'atrule';
return _this;
}
AtRule.prototype.append = function append() {
var _Container$prototype$;
if (!this.nodes) this.nodes = [];
for (var _len = arguments.length, children = Array(_len), _key = 0; _key < _len; _key++) {
children[_key] = arguments[_key];
}
return (_Container$prototype$ = _Container.prototype.append).call.apply(_Container$prototype$, [this].concat(children));
};
AtRule.prototype.prepend = function prepend() {
var _Container$prototype$2;
if (!this.nodes) this.nodes = [];
for (var _len2 = arguments.length, children = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
children[_key2] = arguments[_key2];
}
return (_Container$prototype$2 = _Container.prototype.prepend).call.apply(_Container$prototype$2, [this].concat(children));
};
createClass(AtRule, [{
key: 'afterName',
get: function get$$1() {
warnOnce('AtRule#afterName was deprecated. Use AtRule#raws.afterName');
return this.raws.afterName;
},
set: function set$$1(val) {
warnOnce('AtRule#afterName was deprecated. Use AtRule#raws.afterName');
this.raws.afterName = val;
}
}, {
key: '_params',
get: function get$$1() {
warnOnce('AtRule#_params was deprecated. Use AtRule#raws.params');
return this.raws.params;
},
set: function set$$1(val) {
warnOnce('AtRule#_params was deprecated. Use AtRule#raws.params');
this.raws.params = val;
}
/**
* @memberof AtRule#
* @member {string} name - the at-rule’s name immediately follows the `@`
*
* @example
* const root = postcss.parse('@media print {}');
* media.name //=> 'media'
* const media = root.first;
*/
/**
* @memberof AtRule#
* @member {string} params - the at-rule’s parameters, the values
* that follow the at-rule’s name but precede
* any {} block
*
* @example
* const root = postcss.parse('@media print, screen {}');
* const media = root.first;
* media.params //=> 'print, screen'
*/
/**
* @memberof AtRule#
* @member {object} raws - Information to generate byte-to-byte equal
* node string as it was in the origin input.
*
* Every parser saves its own properties,
* but the default CSS parser uses:
*
* * `before`: the space symbols before the node. It also stores `*`
* and `_` symbols before the declaration (IE hack).
* * `after`: the space symbols after the last child of the node
* to the end of the node.
* * `between`: the symbols between the property and value
* for declarations, selector and `{` for rules, or last parameter
* and `{` for at-rules.
* * `semicolon`: contains true if the last child has
* an (optional) semicolon.
* * `afterName`: the space between the at-rule name and its parameters.
*
* PostCSS cleans at-rule parameters from comments and extra spaces,
* but it stores origin content in raws properties.
* As such, if you don’t change a declaration’s value,
* PostCSS will use the raw value with comments.
*
* @example
* const root = postcss.parse(' @media\nprint {\n}')
* root.first.first.raws //=> { before: ' ',
* // between: ' ',
* // afterName: '\n',
* // after: '\n' }
*/
}]);
return AtRule;
}(Container);
//
/**
* Contains helpers for safely splitting lists of CSS values,
* preserving parentheses and quotes.
*
* @example
* const list = postcss.list;
*
* @namespace list
*/
var list = {
split: function split(string, separators, last) {
var array = [];
var current = '';
var split = false;
var func = 0;
var quote = false;
var escape = false;
for (var i = 0; i < string.length; i++) {
var letter = string[i];
if (quote) {
if (escape) {
escape = false;
} else if (letter === '\\') {
escape = true;
} else if (letter === quote) {
quote = false;
}
} else if (letter === '"' || letter === "'") {
quote = letter;
} else if (letter === '(') {
func += 1;
} else if (letter === ')') {
if (func > 0) func -= 1;
} else if (func === 0) {
if (separators.indexOf(letter) !== -1) split = true;
}
if (split) {
if (current !== '') array.push(current.trim());
current = '';
split = false;
} else {
current += letter;
}
}
if (last || current !== '') array.push(current.trim());
return array;
},
/**
* Safely splits space-separated values (such as those for `background`,
* `border-radius`, and other shorthand properties).
*
* @param {string} string - space-separated values
*
* @return {string[]} splitted values
*
* @example
* postcss.list.space('1px calc(10% + 1px)') //=> ['1px', 'calc(10% + 1px)']
*/
space: function space(string) {
var spaces = [' ', '\n', '\t'];
return list.split(string, spaces);
},
/**
* Safely splits comma-separated values (such as those for `transition-*`
* and `background` properties).
*
* @param {string} string - comma-separated values
*
* @return {string[]} splitted values
*
* @example
* postcss.list.comma('black, linear-gradient(white, black)')
* //=> ['black', 'linear-gradient(white, black)']
*/
comma: function comma(string) {
var comma = ',';
return list.split(string, [comma], true);
}
};
//
/**
* Represents a CSS rule: a selector followed by a declaration block.
*
* @extends Container
*
* @example
* const root = postcss.parse('a{}');
* const rule = root.first;
* rule.type //=> 'rule'
* rule.toString() //=> 'a{}'
*/
var Rule = function (_Container) {
inherits(Rule, _Container);
function Rule(defaults$$1) {
classCallCheck(this, Rule);
var _this = possibleConstructorReturn(this, _Container.call(this, defaults$$1));
_this.type = 'rule';
if (!_this.nodes) _this.nodes = [];
return _this;
}
/**
* An array containing the rule’s individual selectors.
* Groups of selectors are split at commas.
*
* @type {string[]}
*
* @example
* const root = postcss.parse('a, b { }');
* const rule = root.first;
*
* rule.selector //=> 'a, b'
* rule.selectors //=> ['a', 'b']
*
* rule.selectors = ['a', 'strong'];
* rule.selector //=> 'a, strong'
*/
createClass(Rule, [{
key: 'selectors',
get: function get$$1() {
return list.comma(this.selector);
},
set: function set$$1(values) {
var match = this.selector ? this.selector.match(/,\s*/) : null;
var sep = match ? match[0] : ',' + this.raw('between', 'beforeOpen');
this.selector = values.join(sep);
}
}, {
key: '_selector',
get: function get$$1() {
warnOnce('Rule#_selector is deprecated. Use Rule#raws.selector');
return this.raws.selector;
},
set: function set$$1(val) {
warnOnce('Rule#_selector is deprecated. Use Rule#raws.selector');
this.raws.selector = val;
}
/**
* @memberof Rule#
* @member {string} selector - the rule’s full selector represented
* as a string
*
* @example
* const root = postcss.parse('a, b { }');
* const rule = root.first;
* rule.selector //=> 'a, b'
*/
/**
* @memberof Rule#
* @member {object} raws - Information to generate byte-to-byte equal
* node string as it was in the origin input.
*
* Every parser saves its own properties,
* but the default CSS parser uses:
*
* * `before`: the space symbols before the node. It also stores `*`
* and `_` symbols before the declaration (IE hack).
* * `after`: the space symbols after the last child of the node
* to the end of the node.
* * `between`: the symbols between the property and value
* for declarations, selector and `{` for rules, or last parameter
* and `{` for at-rules.
* * `semicolon`: contains true if the last child has
* an (optional) semicolon.
*
* PostCSS cleans selectors from comments and extra spaces,
* but it stores origin content in raws properties.
* As such, if you don’t change a declaration’s value,
* PostCSS will use the raw value with comments.
*
* @example
* const root = postcss.parse('a {\n color:black\n}')
* root.first.first.raws //=> { before: '', between: ' ', after: '\n' }
*/
}]);
return Rule;
}(Container);
//
/**
* Represents a plugin’s warning. It can be created using {@link Node#warn}.
*
* @example
* if ( decl.important ) {
* decl.warn(result, 'Avoid !important', { word: '!important' });
* }
*/
var Warning = function () {
/**
* @param {string} text - warning message
* @param {Object} [opts] - warning options
* @param {Node} opts.node - CSS node that caused the warning
* @param {string} opts.word - word in CSS source that caused the warning
* @param {number} opts.index - index in CSS node string that caused
* the warning
* @param {string} opts.plugin - name of the plugin that created
* this warning. {@link Result#warn} fills
* this property automatically.
*/
function Warning(text) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
classCallCheck(this, Warning);
/**
* @member {string} - Type to filter warnings from
* {@link Result#messages}. Always equal
* to `"warning"`.
*
* @example
* const nonWarning = result.messages.filter(i => i.type !== 'warning')
*/
this.type = 'warning';
/**
* @member {string} - The warning message.
*
* @example
* warning.text //=> 'Try to avoid !important'
*/
this.text = text;
if (opts.node && opts.node.source) {
var pos = opts.node.positionBy(opts);
/**
* @member {number} - Line in the input file
* with this warning’s source
*
* @example
* warning.line //=> 5
*/
this.line = pos.line;
/**
* @member {number} - Column in the input file
* with this warning’s source.
*
* @example
* warning.column //=> 6
*/
this.column = pos.column;
}
for (var opt in opts) {
this[opt] = opts[opt];
}
}
/**
* Returns a warning position and message.
*
* @example
* warning.toString() //=> 'postcss-lint:a.css:10:14: Avoid !important'
*
* @return {string} warning position and message
*/
Warning.prototype.toString = function toString() {
if (this.node) {
return this.node.error(this.text, {
plugin: this.plugin,
index: this.index,
word: this.word
}).message;
} else if (this.plugin) {
return this.plugin + ': ' + this.text;
} else {
return this.text;
}
};
/**
* @memberof Warning#
* @member {string} plugin - The name of the plugin that created
* it will fill this property automatically.
* this warning. When you call {@link Node#warn}
*
* @example
* warning.plugin //=> 'postcss-important'
*/
/**
* @memberof Warning#
* @member {Node} node - Contains the CSS node that caused the warning.
*
* @example
* warning.node.toString() //=> 'color: white !important'
*/
return Warning;
}();
//
/**
* @typedef {object} Message
* @property {string} type - message type
* @property {string} plugin - source PostCSS plugin name
*/
/**
* Provides the result of the PostCSS transformations.
*
* A Result instance is returned by {@link LazyResult#then}
* or {@link Root#toResult} methods.
*
* @example
* postcss([cssnext]).process(css).then(function (result) {
* console.log(result.css);
* });
*
* @example
* var result2 = postcss.parse(css).toResult();
*/
var Result = function () {
/**
* @param {Processor} processor - processor used for this transformation.
* @param {Root} root - Root node after all transformations.
* @param {processOptions} opts - options from the {@link Processor#process}
* or {@link Root#toResult}
*/
function Result(processor, root, opts) {
classCallCheck(this, Result);
/**
* @member {Processor} - The Processor instance used
* for this transformation.
*
* @example
* for ( let plugin of result.processor.plugins) {
* if ( plugin.postcssPlugin === 'postcss-bad' ) {
* throw 'postcss-good is incompatible with postcss-bad';
* }
* });
*/
this.processor = processor;
/**
* @member {Message[]} - Contains messages from plugins
* (e.g., warnings or custom messages).
* Each message should have type
* and plugin properties.
*
* @example
* postcss.plugin('postcss-min-browser', () => {
* return (root, result) => {
* var browsers = detectMinBrowsersByCanIUse(root);
* result.messages.push({
* type: 'min-browser',
* plugin: 'postcss-min-browser',
* browsers: browsers
* });
* };
* });
*/
this.messages = [];
/**
* @member {Root} - Root node after all transformations.
*
* @example
* root.toResult().root == root;
*/
this.root = root;
/**
* @member {processOptions} - Options from the {@link Processor#process}
* or {@link Root#toResult} call
* that produced this Result instance.
*
* @example
* root.toResult(opts).opts == opts;
*/
this.opts = opts;
/**
* @member {string} - A CSS string representing of {@link Result#root}.
*
* @example
* postcss.parse('a{}').toResult().css //=> "a{}"
*/
this.css = undefined;
/**
* @member {SourceMapGenerator} - An instance of `SourceMapGenerator`
* class from the `source-map` library,
* representing changes
* to the {@link Result#root} instance.
*
* @example
* result.map.toJSON() //=> { version: 3, file: 'a.css', … }
*
* @example
* if ( result.map ) {
* fs.writeFileSync(result.opts.to + '.map', result.map.toString());
* }
*/
this.map = undefined;
}
/**
* Returns for @{link Result#css} content.
*
* @example
* result + '' === result.css
*
* @return {string} string representing of {@link Result#root}
*/
Result.prototype.toString = function toString() {
return this.css;
};
/**
* Creates an instance of {@link Warning} and adds it
* to {@link Result#messages}.
*
* @param {string} text - warning message
* @param {Object} [opts] - warning options
* @param {Node} opts.node - CSS node that caused the warning
* @param {string} opts.word - word in CSS source that caused the warning
* @param {number} opts.index - index in CSS node string that caused
* the warning
* @param {string} opts.plugin - name of the plugin that created
* this warning. {@link Result#warn} fills
* this property automatically.
*
* @return {Warning} created warning
*/
Result.prototype.warn = function warn(text) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (!opts.plugin) {
if (this.lastPlugin && this.lastPlugin.postcssPlugin) {
opts.plugin = this.lastPlugin.postcssPlugin;
}
}
var warning = new Warning(text, opts);
this.messages.push(warning);
return warning;
};
/**
* Returns warnings from plugins. Filters {@link Warning} instances
* from {@link Result#messages}.
*
* @example
* result.warnings().forEach(warn => {
* console.warn(warn.toString());
* });
*
* @return {Warning[]} warnings from plugins
*/
Result.prototype.warnings = function warnings() {
return this.messages.filter(function (i) {
return i.type === 'warning';
});
};
/**
* An alias for the {@link Result#css} property.
* Use it with syntaxes that generate non-CSS output.
* @type {string}
*
* @example
* result.css === result.content;
*/
createClass(Result, [{
key: 'content',
get: function get$$1() {
return this.css;
}
}]);
return Result;
}();
//
function isPromise(obj) {
return (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.then === 'function';
}
/**
* @callback onFulfilled
* @param {Result} result
*/
/**
* @callback onRejected
* @param {Error} error
*/
/**
* A Promise proxy for the result of PostCSS transformations.
*
* A `LazyResult` instance is returned by {@link Processor#process}.
*
* @example
* const lazy = postcss([cssnext]).process(css);
*/
var LazyResult = function () {
function LazyResult(processor, css, opts) {
classCallCheck(this, LazyResult);
this.stringified = false;
this.processed = false;
var root = void 0;
if ((typeof css === 'undefined' ? 'undefined' : _typeof(css)) === 'object' && css.type === 'root') {
root = css;
} else if (css instanceof LazyResult || css instanceof Result) {
root = css.root;
if (css.map) {
if (typeof opts.map === 'undefined') opts.map = {};
if (!opts.map.inline) opts.map.inline = false;
opts.map.prev = css.map;
}
} else {
var parser = parse;
if (opts.syntax) parser = opts.syntax.parse;
if (opts.parser) parser = opts.parser;
if (parser.parse) parser = parser.parse;
try {
root = parser(css, opts);
} catch (error) {
this.error = error;
}
}
this.result = new Result(processor, root, opts);
}
/**
* Returns a {@link Processor} instance, which will be used
* for CSS transformations.
* @type {Processor}
*/
/**
* Processes input CSS through synchronous plugins
* and calls {@link Result#warnings()}.
*
* @return {Warning[]} warnings from plugins
*/
LazyResult.prototype.warnings = function warnings() {
return this.sync().warnings();
};
/**
* Alias for the {@link LazyResult#css} property.
*
* @example
* lazy + '' === lazy.css;
*
* @return {string} output CSS
*/
LazyResult.prototype.toString = function toString() {
return this.css;
};
/**
* Processes input CSS through synchronous and asynchronous plugins
* and calls `onFulfilled` with a Result instance. If a plugin throws
* an error, the `onRejected` callback will be executed.
*
* It implements standard Promise API.
*
* @param {onFulfilled} onFulfilled - callback will be executed
* when all plugins will finish work
* @param {onRejected} onRejected - callback will be execited on any error
*
* @return {Promise} Promise API to make queue
*
* @example
* postcss([cssnext]).process(css).then(result => {
* console.log(result.css);
* });
*/
LazyResult.prototype.then = function then(onFulfilled, onRejected) {
return this.async().then(onFulfilled, onRejected);
};
/**
* Processes input CSS through synchronous and asynchronous plugins
* and calls onRejected for each error thrown in any plugin.
*
* It implements standard Promise API.
*
* @param {onRejected} onRejected - callback will be execited on any error
*
* @return {Promise} Promise API to make queue
*
* @example
* postcss([cssnext]).process(css).then(result => {
* console.log(result.css);
* }).catch(error => {
* console.error(error);
* });
*/
LazyResult.prototype.catch = function _catch(onRejected) {
return this.async().catch(onRejected);
};
LazyResult.prototype.handleError = function handleError(error, plugin) {
try {
this.error = error;
if (error.name === 'CssSyntaxError' && !error.plugin) {
error.plugin = plugin.postcssPlugin;
error.setMessage();
} else if (plugin.postcssVersion) {
var pluginName = plugin.postcssPlugin;
var pluginVer = plugin.postcssVersion;
var runtimeVer = this.result.processor.version;
var a = pluginVer.split('.');
var b = runtimeVer.split('.');
if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) {
warnOnce('' + ('Your current PostCSS version ' + 'is ') + runtimeVer + ', but ' + pluginName + ' ' + ('uses ' + pluginVer + '. Perhaps this is ') + 'the source of the error below.');
}
}
} catch (err) {
if (console && console.error) console.error(err);
}
};
LazyResult.prototype.asyncTick = function asyncTick(resolve, reject) {
var _this = this;
if (this.plugin >= this.processor.plugins.length) {
this.processed = true;
return resolve();
}
try {
var plugin = this.processor.plugins[this.plugin];
var promise = this.run(plugin);
this.plugin += 1;
if (isPromise(promise)) {
promise.then(function () {
_this.asyncTick(resolve, reject);
}).catch(function (error) {
_this.handleError(error, plugin);
_this.processed = true;
reject(error);
});
} else {
this.asyncTick(resolve, reject);
}
} catch (error) {
this.processed = true;
reject(error);
}
};
LazyResult.prototype.async = function async() {
var _this2 = this;
if (this.processed) {
return new Promise(function (resolve, reject) {
if (_this2.error) {
reject(_this2.error);
} else {
resolve(_this2.stringify());
}
});
}
if (this.processing) {
return this.processing;
}
this.processing = new Promise(function (resolve, reject) {
if (_this2.error) return reject(_this2.error);
_this2.plugin = 0;
_this2.asyncTick(resolve, reject);
}).then(function () {
_this2.processed = true;
return _this2.stringify();
});
return this.processing;
};
LazyResult.prototype.sync = function sync() {
var _this3 = this;
if (this.processed) return this.result;
this.processed = true;
if (this.processing) {
throw new Error('Use process(css).then(cb) to work with async plugins');
}
if (this.error) throw this.error;
this.result.processor.plugins.forEach(function (plugin) {
var promise = _this3.run(plugin);
if (isPromise(promise)) {
throw new Error('Use process(css).then(cb) to work with async plugins');
}
});
return this.result;
};
LazyResult.prototype.run = function run(plugin) {
this.result.lastPlugin = plugin;
try {
return plugin(this.result.root, this.result);
} catch (error) {
this.handleError(error, plugin);
throw error;
}
};
LazyResult.prototype.stringify = function stringify$$1() {
if (this.stringified) return this.result;
this.stringified = true;
this.sync();
var opts = this.result.opts;
var str = stringify;
if (opts.syntax) str = opts.syntax.stringify;
if (opts.stringifier) str = opts.stringifier;
if (str.stringify) str = str.stringify;
var result = '';
str(this.root, function (i) {
result += i;
});
this.result.css = result;
return this.result;
};
createClass(LazyResult, [{
key: 'processor',
get: function get$$1() {
return this.result.processor;
}
/**
* Options from the {@link Processor#process} call.
* @type {processOptions}
*/
}, {
key: 'opts',
get: function get$$1() {
return this.result.opts;
}
/**
* Processes input CSS through synchronous plugins, converts `Root`
* to a CSS string and returns {@link Result#css}.
*
* This property will only work with synchronous plugins.
* If the processor contains any asynchronous plugins
* it will throw an error. This is why this method is only
* for debug purpose, you should always use {@link LazyResult#then}.
*
* @type {string}
* @see Result#css
*/
}, {
key: 'css',
get: function get$$1() {
return this.stringify().css;
}
/**
* An alias for the `css` property. Use it with syntaxes
* that generate non-CSS output.
*
* This property will only work with synchronous plugins.
* If the processor contains any asynchronous plugins
* it will throw an error. This is why this method is only
* for debug purpose, you should always use {@link LazyResult#then}.
*
* @type {string}
* @see Result#content
*/
}, {
key: 'content',
get: function get$$1() {
return this.stringify().content;
}
/**
* Processes input CSS through synchronous plugins
* and returns {@link Result#map}.
*
* This property will only work with synchronous plugins.
* If the processor contains any asynchronous plugins
* it will throw an error. This is why this method is only
* for debug purpose, you should always use {@link LazyResult#then}.
*
* @type {SourceMapGenerator}
* @see Result#map
*/
}, {
key: 'map',
get: function get$$1() {
return this.stringify().map;
}
/**
* Processes input CSS through synchronous plugins
* and returns {@link Result#root}.
*
* This property will only work with synchronous plugins. If the processor
* contains any asynchronous plugins it will throw an error.
*
* This is why this method is only for debug purpose,
* you should always use {@link LazyResult#then}.
*
* @type {Root}
* @see Result#root
*/
}, {
key: 'root',
get: function get$$1() {
return this.sync().root;
}
/**
* Processes input CSS through synchronous plugins
* and returns {@link Result#messages}.
*
* This property will only work with synchronous plugins. If the processor
* contains any asynchronous plugins it will throw an error.
*
* This is why this method is only for debug purpose,
* you should always use {@link LazyResult#then}.
*
* @type {Message[]}
* @see Result#messages
*/
}, {
key: 'messages',
get: function get$$1() {
return this.sync().messages;
}
}]);
return LazyResult;
}();
//
/**
* @callback builder
* @param {string} part - part of generated CSS connected to this node
* @param {Node} node - AST node
* @param {"start"|"end"} [type] - node’s part type
*/
/**
* @callback parser
*
* @param {string|toString} css - string with input CSS or any object
* with toString() method, like a Buffer
* @param {processOptions} [opts] - options with only `from` and `map` keys
*
* @return {Root} PostCSS AST
*/
/**
* @callback stringifier
*
* @param {Node} node - start node for stringifing. Usually {@link Root}.
* @param {builder} builder - function to concatenate CSS from node’s parts
* or generate string and source map
*
* @return {void}
*/
/**
* @typedef {object} syntax
* @property {parser} parse - function to generate AST by string
* @property {stringifier} stringify - function to generate string by AST
*/
/**
* @typedef {object} toString
* @property {function} toString
*/
/**
* @callback pluginFunction
* @param {Root} root - parsed input CSS
* @param {Result} result - result to set warnings or check other plugins
*/
/**
* @typedef {object} Plugin
* @property {function} postcss - PostCSS plugin function
*/
/**
* @typedef {object} processOptions
* @property {string} from - the path of the CSS source file.
* You should always set `from`,
* because it is used in source map
* generation and syntax error messages.
* @property {string} to - the path where you’ll put the output
* CSS file. You should always set `to`
* to generate correct source maps.
* @property {parser} parser - function to generate AST by string
* @property {stringifier} stringifier - class to generate string by AST
* @property {syntax} syntax - object with `parse` and `stringify`
* @property {object} map - source map options
* @property {boolean} map.inline - does source map should
* be embedded in the output
* CSS as a base64-encoded
* comment
* @property {string|object|false|function} map.prev - source map content
* from a previous
* processing step
* (for example, Sass).
* PostCSS will try to find
* previous map
* automatically, so you
* could disable it by
* `false` value.
* @property {boolean} map.sourcesContent - does PostCSS should set
* the origin content to map
* @property {string|false} map.annotation - does PostCSS should set
* annotation comment to map
* @property {string} map.from - override `from` in map’s
* `sources`
*/
/**
* Contains plugins to process CSS. Create one `Processor` instance,
* initialize its plugins, and then use that instance on numerous CSS files.
*
* @example
* const processor = postcss([autoprefixer, precss]);
* processor.process(css1).then(result => console.log(result.css));
* processor.process(css2).then(result => console.log(result.css));
*/
var Processor = function () {
/**
* @param {Array.