styled-components
Version:
Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅
1,681 lines (1,437 loc) • 220 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
(factory((global.styled = global.styled || {}),global.React));
}(this, (function (exports,React) { 'use strict';
var React__default = 'default' in React ? React['default'] : React;
//
var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
/* Some high number, usually 9-digit base-10. Map it to base-😎 */
var generateAlphabeticName = function generateAlphabeticName(code) {
var lastDigit = chars[code % chars.length];
return code > chars.length ? '' + generateAlphabeticName(Math.floor(code / chars.length)) + lastDigit : lastDigit;
};
//
var interleave = (function (strings, interpolations) {
return interpolations.reduce(function (array, interp, i) {
return array.concat(interp, strings[i + 1]);
}, [strings[0]]);
});
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*/
var _uppercasePattern = /([A-Z])/g;
/**
* Hyphenates a camelcased string, for example:
*
* > hyphenate('backgroundColor')
* < "background-color"
*
* For CSS style names, use `hyphenateStyleName` instead which works properly
* with all vendor prefixes, including `ms`.
*
* @param {string} string
* @return {string}
*/
function hyphenate$1(string) {
return string.replace(_uppercasePattern, '-$1').toLowerCase();
}
var hyphenate_1 = hyphenate$1;
var hyphenate = hyphenate_1;
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 hyphenate(string).replace(msPattern, '-ms-');
}
var hyphenateStyleName_1 = hyphenateStyleName;
/**
* Creates a unary function that invokes `func` with its argument transformed.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} transform The argument transform.
* @returns {Function} Returns the new function.
*/
function overArg$1(func, transform) {
return function (arg) {
return func(transform(arg));
};
}
var _overArg = overArg$1;
var overArg = _overArg;
/** Built-in value references. */
var getPrototype$1 = overArg(Object.getPrototypeOf, Object);
var _getPrototype = getPrototype$1;
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 asyncGenerator = function () {
function AwaitValue(value) {
this.value = value;
}
function AsyncGenerator(gen) {
var front, back;
function send(key, arg) {
return new Promise(function (resolve, reject) {
var request = {
key: key,
arg: arg,
resolve: resolve,
reject: reject,
next: null
};
if (back) {
back = back.next = request;
} else {
front = back = request;
resume(key, arg);
}
});
}
function resume(key, arg) {
try {
var result = gen[key](arg);
var value = result.value;
if (value instanceof AwaitValue) {
Promise.resolve(value.value).then(function (arg) {
resume("next", arg);
}, function (arg) {
resume("throw", arg);
});
} else {
settle(result.done ? "return" : "normal", result.value);
}
} catch (err) {
settle("throw", err);
}
}
function settle(type, value) {
switch (type) {
case "return":
front.resolve({
value: value,
done: true
});
break;
case "throw":
front.reject(value);
break;
default:
front.resolve({
value: value,
done: false
});
break;
}
front = front.next;
if (front) {
resume(front.key, front.arg);
} else {
back = null;
}
}
this._invoke = send;
if (typeof gen.return !== "function") {
this.return = undefined;
}
}
if (typeof Symbol === "function" && Symbol.asyncIterator) {
AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
return this;
};
}
AsyncGenerator.prototype.next = function (arg) {
return this._invoke("next", arg);
};
AsyncGenerator.prototype.throw = function (arg) {
return this._invoke("throw", arg);
};
AsyncGenerator.prototype.return = function (arg) {
return this._invoke("return", arg);
};
return {
wrap: function (fn) {
return function () {
return new AsyncGenerator(fn.apply(this, arguments));
};
},
await: function (value) {
return new AwaitValue(value);
}
};
}();
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 defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var get$1 = function get$1(object, property, receiver) {
if (object === null) object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return undefined;
} else {
return get$1(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
};
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 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 set$1 = function set$1(object, property, value, receiver) {
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent !== null) {
set$1(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
} else {
var setter = desc.set;
if (setter !== undefined) {
setter.call(receiver, value);
}
}
return value;
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike$1(value) {
return value != null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object';
}
var isObjectLike_1 = isObjectLike$1;
var getPrototype = _getPrototype;
var isObjectLike = isObjectLike_1;
/** `Object#toString` result references. */
var objectTag = '[object Object]';
/** Used for built-in method references. */
var funcProto = Function.prototype;
var objectProto = Object.prototype;
/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var objectToString = objectProto.toString;
/**
* Checks if `value` is a plain object, that is, an object created by the
* `Object` constructor or one with a `[[Prototype]]` of `null`.
*
* @static
* @memberOf _
* @since 0.8.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Foo() {
* this.a = 1;
* }
*
* _.isPlainObject(new Foo);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*
* _.isPlainObject(Object.create(null));
* // => true
*/
function isPlainObject(value) {
if (!isObjectLike(value) || objectToString.call(value) != objectTag) {
return false;
}
var proto = getPrototype(value);
if (proto === null) {
return true;
}
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
}
var isPlainObject_1 = isPlainObject;
//
var objToCss = function objToCss(obj) {
return Object.keys(obj).map(function (k) {
return hyphenateStyleName_1(k) + ': ' + obj[k] + ';';
}).join(' ');
};
var flatten = function flatten(chunks, executionContext) {
return chunks.reduce(function (array, chunk) {
/* Remove falsey values */
if (chunk === undefined || chunk === null || chunk === false || chunk === '') return array;
/* Flatten arrays */
if (Array.isArray(chunk)) return array.concat.apply(array, toConsumableArray(flatten(chunk, executionContext)));
/* Either execute or defer the function */
if (typeof chunk === 'function') {
return executionContext ? array.concat.apply(array, toConsumableArray(flatten([chunk(executionContext)], executionContext))) : array.concat(chunk);
}
/* Handle objects */
return array.concat(isPlainObject_1(chunk) ? objToCss(chunk) : chunk.toString());
}, []);
};
//
var css = (function (strings) {
for (var _len = arguments.length, interpolations = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
interpolations[_key - 1] = arguments[_key];
}
return flatten(interleave(strings, interpolations));
});
var printed = {};
function warnOnce(message) {
if (printed[message]) return;
printed[message] = true;
if (typeof console !== 'undefined' && console.warn) console.warn(message);
}
var process$1 = { argv: [], env: {} };
var index$2 = function index$2(flag, argv) {
argv = argv || process$1.argv;
var terminatorPos = argv.indexOf('--');
var prefix = /^--/.test(flag) ? '' : '--';
var pos = argv.indexOf(prefix + flag);
return pos !== -1 && (terminatorPos !== -1 ? pos < terminatorPos : true);
};
var hasFlag = index$2;
var support = function support(level) {
if (level === 0) {
return false;
}
return {
level: level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3
};
};
var supportLevel = function () {
if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) {
return 0;
}
if (hasFlag('color=16m') || hasFlag('color=full') || hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') || hasFlag('color=always')) {
return 1;
}
if (process$1.stdout && !process$1.stdout.isTTY) {
return 0;
}
if (process$1.platform === 'win32') {
return 1;
}
if ('COLORTERM' in process$1.env) {
return 1;
}
if (process$1.env.TERM === 'dumb') {
return 0;
}
if (/^xterm-256(?:color)?/.test(process$1.env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process$1.env.TERM)) {
return 1;
}
return 0;
}();
if (supportLevel === 0 && 'FORCE_COLOR' in process$1.env) {
supportLevel = 1;
}
var index$1 = process$1 && support(supportLevel);
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$1(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$1(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);
}
}
createClass(CssSyntaxError, [{
key: 'setMessage',
value: 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 : '<css input>';
if (typeof this.line !== 'undefined') {
this.message += ':' + this.line + ':' + this.column;
}
this.message += ': ' + this.reason;
}
/**
* Returns a few lines of CSS source that caused the error.
*
* If the CSS has an input source map without `sourceContent`,
* this method will return an empty string.
*
* @param {boolean} [color] whether arrow will be colored red by terminal
* color codes. By default, PostCSS will detect
* color support by `process.stdout.isTTY`
* and `process.env.NODE_DISABLE_COLORS`.
*
* @example
* error.showSourceCode() //=> " 4 | }
* // 5 | a {
* // > 6 | bad
* // | ^
* // 7 | }
* // 8 | b {"
*
* @return {string} few lines of CSS source that caused the error
*/
}, {
key: 'showSourceCode',
value: function showSourceCode(color) {
var _this = this;
if (!this.source) return '';
var css = this.source;
if (typeof color === 'undefined') color = index$1;
if (color) css = terminalHighlight(css);
var lines = css.split(/\r?\n/);
var start = Math.max(this.line - 3, 0);
var end = Math.min(this.line + 2, lines.length);
var maxWidth = String(end).length;
return lines.slice(start, end).map(function (line, index) {
var number = start + 1 + index;
var padded = (' ' + number).slice(-maxWidth);
var gutter = ' ' + padded + ' | ';
if (number === _this.line) {
var spacing = gutter.replace(/\d/g, ' ') + line.slice(0, _this.column - 1).replace(/[^\t]/g, ' ');
return '>' + gutter + line + '\n ' + spacing + '^';
} else {
return ' ' + gutter + line;
}
}).join('\n');
}
/**
* Returns error position, message and source code of the broken part.
*
* @example
* error.toString() //=> "CssSyntaxError: app.css:1:1: Unclosed block
* // > 1 | a {
* // | ^"
*
* @return {string} error position, message and source code
*/
}, {
key: 'toString',
value: function toString() {
var code = this.showSourceCode();
if (code) {
code = '\n\n' + code + '\n';
}
return this.name + ': ' + this.message + code;
}
}, {
key: 'generated',
get: function get() {
warnOnce('CssSyntaxError#generated is depreacted. Use input instead.');
return this.input;
}
/**
* @memberof CssSyntaxError#
* @member {Input} input - Input object with PostCSS internal information
* about input file. If input has source map
* from previous tool, PostCSS will use origin
* (for example, Sass) source. You can use this
* object to get PostCSS input source.
*
* @example
* error.input.file //=> 'a.css'
* error.file //=> 'a.sass'
*/
}]);
return CssSyntaxError;
}();
/* eslint-disable valid-jsdoc */
var defaultRaw = {
colon: ': ',
indent: ' ',
beforeDecl: '\n',
beforeRule: '\n',
beforeOpen: ' ',
beforeClose: '\n',
beforeComment: '\n',
after: '\n',
emptyBody: '',
commentLeft: ' ',
commentRight: ' '
};
function capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
}
var Stringifier = function () {
function Stringifier(builder) {
classCallCheck(this, Stringifier);
this.builder = builder;
}
createClass(Stringifier, [{
key: 'stringify',
value: function stringify(node, semicolon) {
this[node.type](node, semicolon);
}
}, {
key: 'root',
value: function root(node) {
this.body(node);
if (node.raws.after) this.builder(node.raws.after);
}
}, {
key: 'comment',
value: function comment(node) {
var left = this.raw(node, 'left', 'commentLeft');
var right = this.raw(node, 'right', 'commentRight');
this.builder('/*' + left + node.text + right + '*/', node);
}
}, {
key: 'decl',
value: function decl(node, semicolon) {
var between = this.raw(node, 'between', 'colon');
var string = node.prop + between + this.rawValue(node, 'value');
if (node.important) {
string += node.raws.important || ' !important';
}
if (semicolon) string += ';';
this.builder(string, node);
}
}, {
key: 'rule',
value: function rule(node) {
this.block(node, this.rawValue(node, 'selector'));
}
}, {
key: 'atrule',
value: function atrule(node, semicolon) {
var name = '@' + node.name;
var params = node.params ? this.rawValue(node, 'params') : '';
if (typeof node.raws.afterName !== 'undefined') {
name += node.raws.afterName;
} else if (params) {
name += ' ';
}
if (node.nodes) {
this.block(node, name + params);
} else {
var end = (node.raws.between || '') + (semicolon ? ';' : '');
this.builder(name + params + end, node);
}
}
}, {
key: 'body',
value: function body(node) {
var last = node.nodes.length - 1;
while (last > 0) {
if (node.nodes[last].type !== 'comment') break;
last -= 1;
}
var semicolon = this.raw(node, 'semicolon');
for (var i = 0; i < node.nodes.length; i++) {
var child = node.nodes[i];
var before = this.raw(child, 'before');
if (before) this.builder(before);
this.stringify(child, last !== i || semicolon);
}
}
}, {
key: 'block',
value: function block(node, start) {
var between = this.raw(node, 'between', 'beforeOpen');
this.builder(start + between + '{', node, 'start');
var after = void 0;
if (node.nodes && node.nodes.length) {
this.body(node);
after = this.raw(node, 'after');
} else {
after = this.raw(node, 'after', 'emptyBody');
}
if (after) this.builder(after);
this.builder('}', node, 'end');
}
}, {
key: 'raw',
value: function raw(node, own, detect) {
var value = void 0;
if (!detect) detect = own;
// Already had
if (own) {
value = node.raws[own];
if (typeof value !== 'undefined') return value;
}
var parent = node.parent;
// Hack for first rule in CSS
if (detect === 'before') {
if (!parent || parent.type === 'root' && parent.first === node) {
return '';
}
}
// Floating child without parent
if (!parent) return defaultRaw[detect];
// Detect style by other nodes
var root = node.root();
if (!root.rawCache) root.rawCache = {};
if (typeof root.rawCache[detect] !== 'undefined') {
return root.rawCache[detect];
}
if (detect === 'before' || detect === 'after') {
return this.beforeAfter(node, detect);
} else {
var method = 'raw' + capitalize(detect);
if (this[method]) {
value = this[method](root, node);
} else {
root.walk(function (i) {
value = i.raws[own];
if (typeof value !== 'undefined') return false;
});
}
}
if (typeof value === 'undefined') value = defaultRaw[detect];
root.rawCache[detect] = value;
return value;
}
}, {
key: 'rawSemicolon',
value: function rawSemicolon(root) {
var value = void 0;
root.walk(function (i) {
if (i.nodes && i.nodes.length && i.last.type === 'decl') {
value = i.raws.semicolon;
if (typeof value !== 'undefined') return false;
}
});
return value;
}
}, {
key: 'rawEmptyBody',
value: function rawEmptyBody(root) {
var value = void 0;
root.walk(function (i) {
if (i.nodes && i.nodes.length === 0) {
value = i.raws.after;
if (typeof value !== 'undefined') return false;
}
});
return value;
}
}, {
key: 'rawIndent',
value: function rawIndent(root) {
if (root.raws.indent) return root.raws.indent;
var value = void 0;
root.walk(function (i) {
var p = i.parent;
if (p && p !== root && p.parent && p.parent === root) {
if (typeof i.raws.before !== 'undefined') {
var parts = i.raws.before.split('\n');
value = parts[parts.length - 1];
value = value.replace(/[^\s]/g, '');
return false;
}
}
});
return value;
}
}, {
key: 'rawBeforeComment',
value: function rawBeforeComment(root, node) {
var value = void 0;
root.walkComments(function (i) {
if (typeof i.raws.before !== 'undefined') {
value = i.raws.before;
if (value.indexOf('\n') !== -1) {
value = value.replace(/[^\n]+$/, '');
}
return false;
}
});
if (typeof value === 'undefined') {
value = this.raw(node, null, 'beforeDecl');
}
return value;
}
}, {
key: 'rawBeforeDecl',
value: function rawBeforeDecl(root, node) {
var value = void 0;
root.walkDecls(function (i) {
if (typeof i.raws.before !== 'undefined') {
value = i.raws.before;
if (value.indexOf('\n') !== -1) {
value = value.replace(/[^\n]+$/, '');
}
return false;
}
});
if (typeof value === 'undefined') {
value = this.raw(node, null, 'beforeRule');
}
return value;
}
}, {
key: 'rawBeforeRule',
value: function rawBeforeRule(root) {
var value = void 0;
root.walk(function (i) {
if (i.nodes && (i.parent !== root || root.first !== i)) {
if (typeof i.raws.before !== 'undefined') {
value = i.raws.before;
if (value.indexOf('\n') !== -1) {
value = value.replace(/[^\n]+$/, '');
}
return false;
}
}
});
return value;
}
}, {
key: 'rawBeforeClose',
value: function rawBeforeClose(root) {
var value = void 0;
root.walk(function (i) {
if (i.nodes && i.nodes.length > 0) {
if (typeof i.raws.after !== 'undefined') {
value = i.raws.after;
if (value.indexOf('\n') !== -1) {
value = value.replace(/[^\n]+$/, '');
}
return false;
}
}
});
return value;
}
}, {
key: 'rawBeforeOpen',
value: function rawBeforeOpen(root) {
var value = void 0;
root.walk(function (i) {
if (i.type !== 'decl') {
value = i.raws.between;
if (typeof value !== 'undefined') return false;
}
});
return value;
}
}, {
key: 'rawColon',
value: function rawColon(root) {
var value = void 0;
root.walkDecls(function (i) {
if (typeof i.raws.between !== 'undefined') {
value = i.raws.between.replace(/[^\s:]/g, '');
return false;
}
});
return value;
}
}, {
key: 'beforeAfter',
value: function beforeAfter(node, detect) {
var value = void 0;
if (node.type === 'decl') {
value = this.raw(node, null, 'beforeDecl');
} else if (node.type === 'comment') {
value = this.raw(node, null, 'beforeComment');
} else if (detect === 'before') {
value = this.raw(node, null, 'beforeRule');
} else {
value = this.raw(node, null, 'beforeClose');
}
var buf = node.parent;
var depth = 0;
while (buf && buf.type !== 'root') {
depth += 1;
buf = buf.parent;
}
if (value.indexOf('\n') !== -1) {
var indent = this.raw(node, null, 'indent');
if (indent.length) {
for (var step = 0; step < depth; step++) {
value += indent;
}
}
}
return value;
}
}, {
key: 'rawValue',
value: function rawValue(node, prop) {
var value = node[prop];
var raw = node.raws[prop];
if (raw && raw.value === value) {
return raw.raw;
} else {
return value;
}
}
}]);
return Stringifier;
}();
function stringify$1(node, builder) {
var str = new Stringifier(builder);
str.stringify(node);
}
/**
* @typedef {object} position
* @property {number} line - source line in file
* @property {number} column - source column in file
*/
/**
* @typedef {object} source
* @property {Input} input - {@link Input} with input file
* @property {position} start - The starting position of the node’s source
* @property {position} end - The ending position of the node’s source
*/
var cloneNode = function cloneNode(obj, parent) {
var cloned = new obj.constructor();
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
var value = obj[i];
var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
if (i === 'parent' && type === 'object') {
if (parent) cloned[i] = parent;
} else if (i === 'source') {
cloned[i] = value;
} else if (value instanceof Array) {
cloned[i] = value.map(function (j) {
return cloneNode(j, cloned);
});
} else if (i !== 'before' && i !== 'after' && i !== 'between' && i !== 'semicolon') {
if (type === 'object' && value !== null) value = cloneNode(value);
cloned[i] = value;
}
}
return cloned;
};
/**
* All node classes inherit the following common methods.
*
* @abstract
*/
var Node = function () {
/**
* @param {object} [defaults] - value for node properties
*/
function Node() {
var defaults$$1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
classCallCheck(this, Node);
this.raws = {};
for (var name in defaults$$1) {
this[name] = defaults$$1[name];
}
}
/**
* Returns a CssSyntaxError instance containing the original position
* of the node in the source, showing line and column numbers and also
* a small excerpt to facilitate debugging.
*
* If present, an input source map will be used to get the original position
* of the source, even from a previous compilation step
* (e.g., from Sass compilation).
*
* This method produces very useful error messages.
*
* @param {string} message - error description
* @param {object} [opts] - options
* @param {string} opts.plugin - plugin name that created this error.
* PostCSS will set it automatically.
* @param {string} opts.word - a word inside a node’s string that should
* be highlighted as the source of the error
* @param {number} opts.index - an index inside a node’s string that should
* be highlighted as the source of the error
*
* @return {CssSyntaxError} error object to throw it
*
* @example
* if ( !variables[name] ) {
* throw decl.error('Unknown variable ' + name, { word: name });
* // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black
* // color: $black
* // a
* // ^
* // background: white
* }
*/
createClass(Node, [{
key: 'error',
value: function error(message) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (this.source) {
var pos = this.positionBy(opts);
return this.source.input.error(message, pos.line, pos.column, opts);
} else {
return new CssSyntaxError(message);
}
}
/**
* This method is provided as a convenience wrapper for {@link Result#warn}.
*
* @param {Result} result - the {@link Result} instance
* that will receive the warning
* @param {string} text - warning message
* @param {object} [opts] - options
* @param {string} opts.plugin - plugin name that created this warning.
* PostCSS will set it automatically.
* @param {string} opts.word - a word inside a node’s string that should
* be highlighted as the source of the warning
* @param {number} opts.index - an index inside a node’s string that should
* be highlighted as the source of the warning
*
* @return {Warning} created warning object
*
* @example
* const plugin = postcss.plugin('postcss-deprecated', () => {
* return (root, result) => {
* root.walkDecls('bad', decl => {
* decl.warn(result, 'Deprecated property bad');
* });
* };
* });
*/
}, {
key: 'warn',
value: function warn(result, text, opts) {
var data = { node: this };
for (var i in opts) {
data[i] = opts[i];
}return result.warn(text, data);
}
/**
* Removes the node from its parent and cleans the parent properties
* from the node and its children.
*
* @example
* if ( decl.prop.match(/^-webkit-/) ) {
* decl.remove();
* }
*
* @return {Node} node to make calls chain
*/
}, {
key: 'remove',
value: function remove() {
if (this.parent) {
this.parent.removeChild(this);
}
this.parent = undefined;
return this;
}
/**
* Returns a CSS string representing the node.
*
* @param {stringifier|syntax} [stringifier] - a syntax to use
* in string generation
*
* @return {string} CSS string of this node
*
* @example
* postcss.rule({ selector: 'a' }).toString() //=> "a {}"
*/
}, {
key: 'toString',
value: function toString() {
var stringifier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : stringify$1;
if (stringifier.stringify) stringifier = stringifier.stringify;
var result = '';
stringifier(this, function (i) {
result += i;
});
return result;
}
/**
* Returns a clone of the node.
*
* The resulting cloned node and its (cloned) children will have
* a clean parent and code style properties.
*
* @param {object} [overrides] - new properties to override in the clone.
*