Comparing version 4.0.3 to 4.0.4
@@ -0,1 +1,4 @@ | ||
## 4.0.4 | ||
* Fix indent detection in some rare cases. | ||
## 4.0.3 | ||
@@ -2,0 +5,0 @@ * Faster API with 6to5 Loose mode. |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
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) subClass.__proto__ = superClass; }; | ||
var Container = require("./container"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Container = _interopRequire(require("./container")); | ||
// CSS at-rule like “this.keyframes name { }”. | ||
@@ -12,2 +16,4 @@ // | ||
function AtRule(defaults) { | ||
_classCallCheck(this, AtRule); | ||
this.type = "atrule"; | ||
@@ -14,0 +20,0 @@ Container.call(this, defaults); |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
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) subClass.__proto__ = superClass; }; | ||
var Node = require("./node"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Node = _interopRequire(require("./node")); | ||
// CSS comment between declarations or rules | ||
var Comment = (function (Node) { | ||
function Comment(defaults) { | ||
_classCallCheck(this, Comment); | ||
this.type = "comment"; | ||
@@ -11,0 +17,0 @@ Node.call(this, defaults); |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; | ||
@@ -7,9 +9,15 @@ | ||
var Node = require("./node"); | ||
var Comment = require("./comment"); | ||
var Declaration = require("./declaration"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Declaration = _interopRequire(require("./declaration")); | ||
var Comment = _interopRequire(require("./comment")); | ||
var Node = _interopRequire(require("./node")); | ||
// CSS node, that contain another nodes (like at-rules or rules with selectors) | ||
var Container = (function (Node) { | ||
function Container() { | ||
_classCallCheck(this, Container); | ||
if (Node != null) { | ||
@@ -259,15 +267,14 @@ Node.apply(this, arguments); | ||
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
this.nodes.push(node); | ||
} | ||
return this; | ||
}return this; | ||
}; | ||
@@ -285,15 +292,14 @@ | ||
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
this.nodes.unshift(node); | ||
} | ||
for (var id in this.indexes) { | ||
}for (var id in this.indexes) { | ||
this.indexes[id] = this.indexes[id] + nodes.length; | ||
@@ -319,15 +325,14 @@ } | ||
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
this.nodes.splice(exist, 0, node); | ||
} | ||
var index; | ||
}var index; | ||
for (var id in this.indexes) { | ||
@@ -356,15 +361,14 @@ index = this.indexes[id]; | ||
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
this.nodes.splice(exist + 1, 0, node); | ||
} | ||
var index; | ||
}var index; | ||
for (var id in this.indexes) { | ||
@@ -404,15 +408,14 @@ index = this.indexes[id]; | ||
for (var _iterator = this.nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
node.parent = undefined; | ||
} | ||
this.nodes = []; | ||
}this.nodes = []; | ||
return this; | ||
@@ -482,6 +485,8 @@ }; | ||
} else if (nodes.selector) { | ||
var Rule = require("./rule"); | ||
var Rule = _interopRequire(require("./rule")); | ||
nodes = [new Rule(nodes)]; | ||
} else if (nodes.name) { | ||
var AtRule = require("./at-rule"); | ||
var AtRule = _interopRequire(require("./at-rule")); | ||
nodes = [new AtRule(nodes)]; | ||
@@ -515,3 +520,2 @@ } else if (nodes.text) { | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
@@ -526,3 +530,2 @@ }, | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
@@ -529,0 +532,0 @@ } |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
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) subClass.__proto__ = superClass; }; | ||
var PreviousMap = require("./previous-map"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var path = require("path"); | ||
var PreviousMap = _interopRequire(require("./previous-map")); | ||
var path = _interopRequire(require("path")); | ||
// Error while CSS parsing | ||
var CssSyntaxError = (function (SyntaxError) { | ||
function CssSyntaxError(message, line, column, source, file) { | ||
_classCallCheck(this, CssSyntaxError); | ||
this.reason = message; | ||
@@ -79,4 +85,5 @@ | ||
CssSyntaxError.prototype.name = "CssSyntaxError"; | ||
module.exports = CssSyntaxError; | ||
module.exports = CssSyntaxError; | ||
CssSyntaxError.prototype.name = "CssSyntaxError"; |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
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) subClass.__proto__ = superClass; }; | ||
var Node = require("./node"); | ||
var vendor = require("./vendor"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var vendor = _interopRequire(require("./vendor")); | ||
var Node = _interopRequire(require("./node")); | ||
// CSS declaration like “color: black” in rules | ||
var Declaration = (function (Node) { | ||
function Declaration(defaults) { | ||
_classCallCheck(this, Declaration); | ||
this.type = "decl"; | ||
@@ -12,0 +19,0 @@ Node.call(this, defaults); |
"use strict"; | ||
var CssSyntaxError = require("./css-syntax-error"); | ||
var PreviousMap = require("./previous-map"); | ||
var Parser = require("./parser"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var path = require("path"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var CssSyntaxError = _interopRequire(require("./css-syntax-error")); | ||
var PreviousMap = _interopRequire(require("./previous-map")); | ||
var Parser = _interopRequire(require("./parser")); | ||
var path = _interopRequire(require("path")); | ||
var sequence = 0; | ||
@@ -14,2 +20,4 @@ | ||
var opts = arguments[1] === undefined ? {} : arguments[1]; | ||
_classCallCheck(this, Input); | ||
this.css = css.toString(); | ||
@@ -16,0 +24,0 @@ |
"use strict"; | ||
// Methods to parse list and split it to array | ||
var list = { | ||
module.exports = { | ||
@@ -75,4 +75,2 @@ // Split string to array by separator symbols with function and inside strings | ||
}; | ||
module.exports = list; | ||
}; |
"use strict"; | ||
var Result = require("./result"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var mozilla = require("source-map"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Result = _interopRequire(require("./result")); | ||
var Base64 = require("js-base64").Base64; | ||
var path = require("path"); | ||
var mozilla = _interopRequire(require("source-map")); | ||
var path = _interopRequire(require("path")); | ||
// All tools to generate source maps | ||
var MapGenerator = (function () { | ||
function MapGenerator(root, opts) { | ||
_classCallCheck(this, MapGenerator); | ||
this.root = root; | ||
@@ -112,11 +119,12 @@ this.opts = opts; | ||
for (var _iterator = this.previous(), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var prev; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
prev = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
prev = _i.value; | ||
_ref = _i.value; | ||
} | ||
var prev = _ref; | ||
var from = this.relative(prev.file); | ||
@@ -123,0 +131,0 @@ var root = prev.root || path.dirname(prev.file); |
"use strict"; | ||
var CssSyntaxError = require("./css-syntax-error"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var CssSyntaxError = _interopRequire(require("./css-syntax-error")); | ||
// Recursivly clone objects | ||
@@ -34,2 +38,4 @@ var clone = function (obj, parent) { | ||
var defaults = arguments[0] === undefined ? {} : arguments[0]; | ||
_classCallCheck(this, Node); | ||
for (var name in defaults) { | ||
@@ -285,3 +291,3 @@ this[name] = defaults[name]; | ||
var p = i.parent; | ||
if (p != root && p.parent && p.parent == root) { | ||
if (p && p != root && p.parent && p.parent == root) { | ||
if (typeof i.before != "undefined") { | ||
@@ -413,11 +419,12 @@ var parts = i.before.split("\n"); | ||
for (var _iterator = this.nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
node.cleanStyles(keepBetween); | ||
@@ -442,2 +449,5 @@ } | ||
module.exports = Node; | ||
// Default code style | ||
@@ -456,4 +466,2 @@ Node.prototype.defaultStyle = { | ||
commentRight: " " | ||
}; | ||
module.exports = Node; | ||
}; |
"use strict"; | ||
var Parser = require("./parser"); | ||
var Input = require("./input"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var Parser = _interopRequire(require("./parser")); | ||
var Input = _interopRequire(require("./input")); | ||
module.exports = function (css, opts) { | ||
@@ -7,0 +10,0 @@ var input = new Input(css, opts); |
"use strict"; | ||
var Declaration = require("./declaration"); | ||
var tokenize = require("./tokenize"); | ||
var Comment = require("./comment"); | ||
var AtRule = require("./at-rule"); | ||
var Root = require("./root"); | ||
var Rule = require("./rule"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Declaration = _interopRequire(require("./declaration")); | ||
var tokenize = _interopRequire(require("./tokenize")); | ||
var Comment = _interopRequire(require("./comment")); | ||
var AtRule = _interopRequire(require("./at-rule")); | ||
var Root = _interopRequire(require("./root")); | ||
var Rule = _interopRequire(require("./rule")); | ||
// CSS parser | ||
var Parser = (function () { | ||
function Parser(input) { | ||
_classCallCheck(this, Parser); | ||
this.input = input; | ||
@@ -439,3 +450,2 @@ | ||
} | ||
if (!clean) { | ||
@@ -453,5 +463,3 @@ var origin = ""; | ||
origin += token[1]; | ||
} | ||
node["_" + prop] = { value: value, raw: origin }; | ||
}node["_" + prop] = { value: value, raw: origin }; | ||
} | ||
@@ -458,0 +466,0 @@ node[prop] = value; |
"use strict"; | ||
var Declaration = require("./declaration"); | ||
var Comment = require("./comment"); | ||
var AtRule = require("./at-rule"); | ||
var Result = require("./result"); | ||
var Rule = require("./rule"); | ||
var Root = require("./root"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Declaration = _interopRequire(require("./declaration")); | ||
var Comment = _interopRequire(require("./comment")); | ||
var AtRule = _interopRequire(require("./at-rule")); | ||
var Result = _interopRequire(require("./result")); | ||
var parse = _interopRequire(require("./parse")); | ||
var Rule = _interopRequire(require("./rule")); | ||
var Root = _interopRequire(require("./root")); | ||
// List of functions to process CSS | ||
@@ -15,2 +26,4 @@ var PostCSS = (function () { | ||
var plugins = arguments[0] === undefined ? [] : arguments[0]; | ||
_classCallCheck(this, PostCSS); | ||
this.plugins = plugins.map(function (i) { | ||
@@ -48,11 +61,12 @@ return _this.normalize(i); | ||
for (var _iterator = this.plugins, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var plugin; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
plugin = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
plugin = _i.value; | ||
_ref = _i.value; | ||
} | ||
var plugin = _ref; | ||
var returned = plugin(parsed, opts); | ||
@@ -96,3 +110,3 @@ if (returned instanceof Root) parsed = returned; | ||
// Compile CSS to nodes | ||
postcss.parse = require("./parse"); | ||
postcss.parse = parse; | ||
@@ -99,0 +113,0 @@ // Nodes shortcuts |
"use strict"; | ||
var mozilla = require("source-map"); | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Base64 = require("js-base64").Base64; | ||
var path = require("path"); | ||
var fs = require("fs"); | ||
var mozilla = _interopRequire(require("source-map")); | ||
var path = _interopRequire(require("path")); | ||
var fs = _interopRequire(require("fs")); | ||
// Detect previous map | ||
var PreviousMap = (function () { | ||
function PreviousMap(css, opts) { | ||
_classCallCheck(this, PreviousMap); | ||
this.loadAnnotation(css); | ||
@@ -12,0 +20,0 @@ this.inline = this.startWith(this.annotation, "data:"); |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; | ||
var MapGenerator = require("./map-generator"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var MapGenerator = _interopRequire(require("./map-generator")); | ||
// Object with processed CSS | ||
@@ -11,2 +15,4 @@ var Result = (function () { | ||
var opts = arguments[1] === undefined ? {} : arguments[1]; | ||
_classCallCheck(this, Result); | ||
this.root = root; | ||
@@ -37,3 +43,2 @@ this.opts = opts; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
@@ -48,3 +53,2 @@ }, | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
@@ -51,0 +55,0 @@ } |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
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) subClass.__proto__ = superClass; }; | ||
var Declaration = require("./declaration"); | ||
var Container = require("./container"); | ||
var Comment = require("./comment"); | ||
var AtRule = require("./at-rule"); | ||
var Result = require("./result"); | ||
var Rule = require("./rule"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Declaration = _interopRequire(require("./declaration")); | ||
var Container = _interopRequire(require("./container")); | ||
var Comment = _interopRequire(require("./comment")); | ||
var AtRule = _interopRequire(require("./at-rule")); | ||
var Result = _interopRequire(require("./result")); | ||
var Rule = _interopRequire(require("./rule")); | ||
// Root of CSS | ||
var Root = (function (Container) { | ||
function Root(defaults) { | ||
_classCallCheck(this, Root); | ||
this.type = "root"; | ||
@@ -46,11 +57,12 @@ this.nodes = []; | ||
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var node; | ||
var _ref; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
node = _iterator[_i++]; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
node = _i.value; | ||
_ref = _i.value; | ||
} | ||
var node = _ref; | ||
if (this.first != sample) node.before = sample.before; | ||
@@ -57,0 +69,0 @@ } |
"use strict"; | ||
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; | ||
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; | ||
@@ -7,9 +9,15 @@ | ||
var Container = require("./container"); | ||
var Declaration = require("./declaration"); | ||
var list = require("./list"); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; | ||
var Declaration = _interopRequire(require("./declaration")); | ||
var Container = _interopRequire(require("./container")); | ||
var list = _interopRequire(require("./list")); | ||
// CSS rule like “a { }” | ||
var Rule = (function (Container) { | ||
function Rule(defaults) { | ||
_classCallCheck(this, Rule); | ||
this.type = "rule"; | ||
@@ -38,3 +46,2 @@ this.nodes = []; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
@@ -41,0 +48,0 @@ } |
"use strict"; | ||
// Methods to work with vendor prefixes | ||
var vendor = { | ||
module.exports = { | ||
@@ -32,4 +32,2 @@ // Return vendor prefix from property name, if it exists | ||
}; | ||
module.exports = vendor; | ||
}; |
{ | ||
"name": "postcss", | ||
"version": "4.0.3", | ||
"description": "Framework for CSS postprocessors with full source map support", | ||
"version": "4.0.4", | ||
"description": "Tool to transform CSS by JS plugins", | ||
"keywords": [ | ||
"css", | ||
"postproccessor", | ||
"parser", | ||
"postproccessor", | ||
"source map" | ||
"source map", | ||
"manipulation", | ||
"preprocess", | ||
"transform" | ||
], | ||
@@ -26,25 +29,25 @@ "author": "Andrey Sitnik <andrey@sitnik.ru>", | ||
"jshint-stylish": "1.0.0", | ||
"gulp-jshint": "1.9.0", | ||
"gonzales-pe": "3.0.0-13", | ||
"gulp-jshint": "1.9.2", | ||
"gonzales-pe": "3.0.0-26", | ||
"gulp-bench": "1.1.0", | ||
"gulp-mocha": "2.0.0", | ||
"gulp-util": "3.0.2", | ||
"node-sass": "2.0.1", | ||
"gulp-util": "3.0.3", | ||
"gulp-6to5": "3.0.0", | ||
"node-sass": "1.2.3", | ||
"execSync": "1.0.2", | ||
"fs-extra": "0.16.0", | ||
"fs-extra": "0.16.3", | ||
"gonzales": "1.0.7", | ||
"stylecow": "4.0.1", | ||
"through2": "0.6.3", | ||
"request": "2.51.0", | ||
"cssnext": "0.6.6", | ||
"stylecow": "4.2.4", | ||
"request": "2.53.0", | ||
"cssnext": "1.0.0", | ||
"rework": "1.0.1", | ||
"mensch": "0.3.1", | ||
"stylus": "0.49.3", | ||
"stylus": "0.50.0", | ||
"mocha": "2.1.0", | ||
"cssom": "0.3.0", | ||
"gulp": "3.8.10", | ||
"less": "2.3.0", | ||
"chai": "1.10.0", | ||
"6to5": "3.0.9" | ||
"gulp": "3.8.11", | ||
"less": "2.4.0", | ||
"chai": "2.0.0", | ||
"6to5": "3.6.4" | ||
}, | ||
@@ -51,0 +54,0 @@ "scripts": { |
1138
README.md
@@ -5,493 +5,283 @@ # PostCSS [![Build Status](https://travis-ci.org/postcss/postcss.svg)](https://travis-ci.org/postcss/postcss) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/postcss/postcss?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
PostCSS is a framework for CSS postprocessors, | ||
to modify CSS with JavaScript with full source map support. | ||
PostCSS is a tool to transform CSS by JS plugins. This plugins can add vendor | ||
prefixes, polyfill CSS 4 features, inline images, add variables | ||
and mixins support. PostCSS with most popular [Autoprefixer] plugin | ||
is used by Google, Twitter, Alibaba and Shopify. | ||
It takes care of the most common CSS tool tasks: | ||
PostCSS does same work as Sass, LESS or Stylus. But, instead of preprocessors, | ||
PostCSS is modular, 4—40 times faster and much powerful | ||
(Autoprefixer is impossible on preprocessors). | ||
1. parses CSS; | ||
2. provides a usable JS API to edit CSS node trees; | ||
3. dumps the modified node tree into a CSS string; | ||
4. generates a source map (or modifies an pre-existing source map) containing | ||
your changes; | ||
PostCSS is very small. It contains only CSS parser, CSS node tree API, | ||
source map generator and node tree stringifier. All features (like variables | ||
or nesting) are made by plugins. PostCSS plugin is just a JS function, that | ||
accepts CSS node tree, reads and transforms some of nodes in tree. | ||
You can use this framework to write your own: | ||
For example, with [Autoprefixer], [cssnext], [CSS Grace], | ||
[postcss-nested], [postcss-mixins] and [postcss-easings] plugins | ||
you will be able to write this CSS: | ||
* CSS minifier or beautifier. | ||
* CSS polyfills. | ||
* Grunt plugin to generate sprites, include `data-uri` images | ||
or any other work. | ||
* Text editor plugin to automate CSS routines. | ||
* Command-line CSS tool. | ||
Twitter account for news, releases and new plugins: [@postcss]. | ||
Weibo account: [postcss]. | ||
<a href="https://evilmartians.com/?utm_source=postcss"> | ||
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"> | ||
</a> | ||
[@postcss]: https://twitter.com/postcss | ||
[postcss]: http://weibo.com/postcss | ||
## Built with PostCSS | ||
### Tools | ||
* [Autoprefixer] adds vendor prefixes by Can I Use data. | ||
* [BEM linter] lints CSS for SUIT CSS methodology. | ||
* [CSS MQPacker] joins same media queries. | ||
* [css2modernizr] analyzes your CSS and output only used Modernizr’s settings. | ||
* [cssnext] is a transpiler (CSS 4+ to CSS 3) that allow you to use tomorrow’s | ||
CSS syntax today. | ||
* [CSSWring] is a CSS minifier with full source map support. | ||
* [data-separator] splits data-uri into a separate CSS file. | ||
* [pixrem] is a `rem` unit polyfill. | ||
* [webpcss] to duplicate images in CSS to WebP for supported browsers. | ||
* [Pleeease] is a pack of various postprocessors. | ||
* [Pleeease Filters] converts WebKit filters to SVG filter for other browsers. | ||
* [RTLCSS] mirrors styles for right-to-left locales. | ||
* [CSS Byebye] explicitly removes the CSS rules that you don’t want. | ||
* [postcss-epub] to prefix ePub3 properties. | ||
* [doiuse] to lint your CSS on unsupported properties by Can I Use. | ||
* [postcss-assets] to inline files and insert image width and height. | ||
* [ACSS] Annotations based CSS processor. | ||
* [CSS Grace] to CSS 3 polyfills for IE and other old browsers. | ||
* [mq4-hover-hover-shim] is a shim for the `hover` media feature from Media | ||
Queries Level 4. | ||
[Autoprefixer]: https://github.com/postcss/autoprefixer | ||
[BEM linter]: https://github.com/necolas/postcss-bem-linter | ||
[CSS MQPacker]: https://github.com/hail2u/node-css-mqpacker | ||
[css2modernizr]: https://github.com/vovanbo/css2modernizr | ||
[cssnext]: https://github.com/putaindecode/cssnext | ||
[CSSWring]: https://github.com/hail2u/node-csswring | ||
[data-separator]: https://github.com/Sebastian-Fitzner/grunt-data-separator | ||
[pixrem]: https://github.com/robwierzbowski/node-pixrem | ||
[webpcss]: https://github.com/lexich/webpcss | ||
[Pleeease]: http://pleeease.io/ | ||
[Pleeease Filters]: https://github.com/iamvdo/pleeease-filters | ||
[RTLCSS]: https://github.com/MohammadYounes/rtlcss | ||
[CSS Byebye]: https://github.com/AoDev/css-byebye | ||
[postcss-epub]: https://github.com/Rycochet/postcss-epub | ||
[doiuse]: https://github.com/anandthakker/doiuse | ||
[postcss-assets]: https://github.com/borodean/postcss-assets | ||
[ACSS]: https://github.com/morishitter/acss | ||
[CSS Grace]: https://github.com/cssdream/cssgrace | ||
[mq4-hover-hover-shim]: https://github.com/cvrebert/mq4-hover-hover-shim | ||
### Plugins | ||
* [postcss-calc] to reduce `calc()` usage | ||
(recommended with `postcss-custom-properties`). | ||
* [postcss-color-function] to transform `color()` function. | ||
* [postcss-color-gray] to transform `gray()` function. | ||
* [postcss-color-hex-alpha] to transform hexadecimal notations with alpha | ||
(`#rrggbbaa` or `#rgba`). | ||
* [postcss-color-hwb] to transform `hwb()` function. | ||
* [postcss-color-rebeccapurple] to transform `rebeccapurple` color. | ||
* [postcss-import] to transform `@import` rules by inlining content. | ||
* [postcss-custom-media] to add names for Media Queries. | ||
* [postcss-custom-properties] to transform Custom Properties | ||
for cascading variables. | ||
* [postcss-url] to rebase or inline on `url()`. | ||
* [postcss-font-variant] to set `font-feature-settings` by readable properties. | ||
* [postcss-nested] to unwrap rules in other rules, like you can write in Sass. | ||
* [postcss-custom-selector] to add custom alias for selectors. | ||
* [postcss-media-minmax] to use `<=` or `>=` in CSS Media Queries. | ||
* [postcss-data-packer] to move an embedded data into a separate file. | ||
* [postcss-color-palette] to transform CSS2 color keywords to a custom palette. | ||
* [postcss-color-hex] to transform rgb() and rgba() to hex. | ||
* [postcss-single-charset] to pop first `@charset` rule. | ||
* [postcss-simple-extend] to add selectors to a previously defined rule set. | ||
* [postcss-simple-mixin] to clone declarations from abstract definitions into any rule sets that follow. | ||
[postcss-calc]: https://github.com/postcss/postcss-calc | ||
[postcss-color-function]: https://github.com/postcss/postcss-color-function | ||
[postcss-color-gray]: https://github.com/postcss/postcss-color-gray | ||
[postcss-color-hex-alpha]: https://github.com/postcss/postcss-color-hex-alpha | ||
[postcss-color-hwb]: https://github.com/postcss/postcss-color-hwb | ||
[postcss-color-rebeccapurple]: https://github.com/postcss/postcss-color-rebeccapurple | ||
[postcss-import]: https://github.com/postcss/postcss-import | ||
[postcss-custom-media]: https://github.com/postcss/postcss-custom-media | ||
[postcss-custom-properties]: https://github.com/postcss/postcss-custom-properties | ||
[postcss-url]: https://github.com/postcss/postcss-url | ||
[postcss-font-variant]: https://github.com/postcss/postcss-font-variant | ||
[postcss-nested]: https://github.com/postcss/postcss-nested | ||
[postcss-custom-selector]: https://github.com/postcss/postcss-custom-selector | ||
[postcss-media-minmax]: https://github.com/postcss/postcss-media-minmax | ||
[postcss-data-packer]: https://github.com/Ser-Gen/postcss-data-packer | ||
[postcss-color-palette]: https://github.com/zaim/postcss-color-palette | ||
[postcss-color-hex]: https://github.com/TrySound/postcss-color-hex | ||
[postcss-single-charset]: https://github.com/hail2u/postcss-single-charset | ||
[postcss-simple-extend]: https://github.com/davidtheclark/postcss-simple-extend | ||
[postcss-simple-mixin]: https://github.com/davidtheclark/postcss-simple-mixin | ||
## Quick Example | ||
Let’s fix a forgotten `content` property in `::before` and `::after`: | ||
```js | ||
var postcss = require('postcss'); | ||
var contenter = postcss(function (css) { | ||
css.eachRule(function (rule) { | ||
if ( rule.selector.match(/::(before|after)/) ) { | ||
// In each ::before/::after rule | ||
// Did we forget the content property? | ||
var good = rule.some(function (i) { return i.prop == 'content'; }); | ||
if ( !good ) { | ||
// Add content: "" if we forget it | ||
rule.prepend({ prop: 'content', value: '""' }); | ||
} | ||
```css | ||
@define-mixin social-icon $color { | ||
& { | ||
background: $color; | ||
&:hover { | ||
background: color($color whiteness(+10%)) | ||
} | ||
}); | ||
}); | ||
``` | ||
} | ||
} | ||
And the CSS with a forgotten `content` property: | ||
```css | ||
a::before { | ||
width: 10px; | ||
height: 10px | ||
.social-icon { | ||
transition: background 200ms ease-in-sine; | ||
font-variant-caps: small-caps; | ||
&.is-twitter { | ||
@mixin social-icon #55acee; | ||
} | ||
&.is-facebook { | ||
@mixin social-icon #3b5998; | ||
} | ||
&:active { | ||
opacity: 0.6; | ||
} | ||
} | ||
``` | ||
will be fixed by our new `contenter`: | ||
@custom-media --mobile (width <= 640px); | ||
```js | ||
var fixed = contenter.process(css).css; | ||
``` | ||
@custom-selector --heading h1, h2, h3, h4, h5, h6; | ||
to: | ||
```css | ||
a::before { | ||
content: ""; | ||
width: 10px; | ||
height: 10px | ||
.post-article --heading { | ||
margin-top: 10rem; | ||
@media (--mobile) { | ||
margin-top: 0; | ||
} | ||
} | ||
``` | ||
## Features | ||
Twitter account for articles, releases and new plugins: [@postcss]. | ||
Weibo account: [postcss]. | ||
### Source Map | ||
<a href="https://evilmartians.com/?utm_source=postcss"> | ||
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"> | ||
</a> | ||
PostCSS generates a source map of its changes: | ||
```js | ||
result = processor.process(css, { map: true, from: 'from.css', to: 'to.css' }); | ||
result.css // String with processed CSS and inlined source map | ||
``` | ||
And modifies a source map from previous steps (for example, Sass preprocessor): | ||
```js | ||
var sass = compiler.compile(sass); | ||
processor.process(sass.css, { | ||
map: { prev: sass.map }, | ||
from: 'from.sass.css', | ||
to: 'to.css' | ||
}); | ||
``` | ||
### Preserves code formatting and indentations | ||
PostCSS will not change any byte of a rule, if you do not modify its node: | ||
```js | ||
postcss(function (css) { }).process(css).css == css; | ||
``` | ||
And when you modify CSS nodes, PostCSS will try to copy the coding style: | ||
```js | ||
contenter.process("a::before{color:black}") | ||
// a::before{content:'';color:black} | ||
contenter.process("a::before {\n color: black;\n }") | ||
// a::before { | ||
// content: ''; | ||
// color: black; | ||
// } | ||
``` | ||
Which allows you to use PostCSS in text editor plugins while preserving | ||
the user’s code style. | ||
## Why PostCSS Better Than … | ||
### Preprocessors | ||
Preprocessors (like Sass or Stylus) give us special languages with variables, | ||
mixins, and statements, which are compiled to CSS. Compass, nib and other mixins | ||
libraries use these languages to work with prefixes, sprites and inline images. | ||
But the Sass and Stylus languages were created to be syntax-sugar for CSS. | ||
Writing complicated programs using preprocessor languages can be very difficult. | ||
For example, it would be impossible to implement [Autoprefixer] on top of Sass. | ||
PostCSS gives you the comfort and power of JS or CoffeeScript while | ||
you are working with CSS. Applying the depth and variety of [npm]’s libraries | ||
allows you to perform quite magical things using PostCSS. | ||
An important point is that postprocessors are not the enemies of preprocessors. | ||
Preprocessors and postprocessors can be easily combined, so that you can take | ||
advantage of the readability and syntactical sugar offered by Sass and Stylus; | ||
and PostCSS will preserve their source maps. | ||
[Autoprefixer]: https://github.com/postcss/autoprefixer | ||
[npm]: https://npmjs.org/ | ||
[CSS Grace]: https://github.com/cssdream/cssgrace | ||
[@postcss]: https://twitter.com/postcss | ||
[postcss]: http://weibo.com/postcss | ||
[cssnext]: https://github.com/cssnext/cssnext | ||
### Regular Expressions | ||
## Differences with preprocessors | ||
Some Grunt plugins modify CSS with regular expressions, however a parser | ||
and its node tree provide a much safer interface to edit CSS. Furthermore, | ||
regular expressions typically break the source maps generated by preprocessors. | ||
1. With preprocessors you write your CSS on special programming language. | ||
It is like a PHP, but you mix control statement with styles. As result your | ||
styles is slow, because programming language is too compilcated. With PostCSS | ||
you write styles on normal CSS, just with custom at-rules and functions. | ||
2. Preprocessors tools (like Compass) is written mainly in same | ||
preprocessors language. As result this tools is very limited. The libraries | ||
adds only a custom functions, variables or mixins. There is no way to add new | ||
syntax for CSS 4 polyfills. In PostCSS all magic is written on JS and uses | ||
big universe of npm packages. So you have better and smarter tools. | ||
3. All features is built in this preprocessor’s language. Adding new features | ||
is very difficult for developers, so languages develop slow. All features | ||
of PostCSS is just a small JS functions, which transform CSS nodes tree. | ||
Many developers create new features and you have bigger choice. | ||
### CSS Parsers | ||
## Features | ||
There are a lot of good CSS parsers, such as [Gonzales], but they only help you | ||
to read in the CSS. PostCSS provides you with full source map support and a | ||
high level API. Safe iterators, and other features, are unique to PostCSS. | ||
### Modularity | ||
[Gonzales]: https://github.com/css/gonzales | ||
Without a plugins, PostCSS just parse your CSS and stringify it back without | ||
change of any byte. All features is made by small JS funcions | ||
from PostCSS plugins. You can choose only features, that you need. | ||
### Rework | ||
Variables is a nice example. There are 2 different plugins for variables. | ||
[postcss-simple-vars] has Sass like syntax: | ||
[Rework] and PostCSS are very similar, but they have different targets. | ||
Rework was created to build a new CSS sublanguage that replaced Stylus | ||
(like [Myth]). PostCSS was created for CSS tools which work with legacy CSS code | ||
(one such tool is Autoprefixer). | ||
Because of this fundamental difference, PostCSS: | ||
* Handles source map better, because it updates the map from the previous step | ||
(for example, Sass compilation). | ||
* Preserves all your spaces and code style, so that it can function | ||
in text editor plugins. | ||
* Has a safer parser, so that it can be used for legacy code. Only PostCSS can | ||
parse all of the hacks from [Browserhacks.com](http://browserhacks.com/). | ||
* Has a high level API to provide an simple interface for your processor to | ||
perform typical tasks. | ||
[Myth]: http://www.myth.io/ | ||
[Rework]: https://github.com/visionmedia/rework | ||
## Usage | ||
### Grunt | ||
Grunt plugin [grunt-postcss] allows you to pipe your CSS files through | ||
an array of PostCSS processors. | ||
```js | ||
grunt.initConfig({ | ||
postcss: { | ||
options: { | ||
map: true, | ||
processors: [ | ||
require('autoprefixer-core').postcss, | ||
require('csswring').postcss | ||
] | ||
}, | ||
dist: { | ||
src: 'css/*.css' | ||
} | ||
} | ||
}); | ||
grunt.loadNpmTasks('grunt-postcss'); | ||
```css | ||
a { | ||
color: $link-color; | ||
} | ||
``` | ||
[grunt-postcss]: https://github.com/nDmitry/grunt-postcss | ||
[postcss-custom-properties] is a polyfill for [W3C CSS Custom Properties] draft: | ||
### Gulp | ||
There is a Gulp plugin for PostCSS called [gulp-postcss] that allows you | ||
to pipe your CSS files through an array of PostCSS processors. | ||
Support for external source maps is provided by [gulp-sourcemaps]. | ||
```js | ||
var postcss = require('gulp-postcss'); | ||
var sourcemaps = require('gulp-sourcemaps'); | ||
gulp.task('css', function () { | ||
var processors = [ | ||
require('autoprefixer-core'), | ||
require('csswring') | ||
]; | ||
return gulp.src('./src/*.css') | ||
.pipe(sourcemaps.init()) | ||
.pipe(postcss(processors)) | ||
.pipe(sourcemaps.write('.')) | ||
.pipe(gulp.dest('./dest')); | ||
}); | ||
``` | ||
[gulp-postcss]: https://github.com/w0rm/gulp-postcss | ||
[gulp-sourcemaps]: https://github.com/floridoo/gulp-sourcemaps | ||
### Webpack | ||
In [webpack] you can use [postcss-loader] to process CSS files through | ||
an array of PostCSS processors. | ||
```js | ||
module.exports = { | ||
module: { | ||
loaders: [ | ||
{ | ||
test: /\.css$/, | ||
loader: "style-loader!css-loader!postcss-loader" | ||
} | ||
] | ||
}, | ||
postcss: [require('autoprefixer-core'), require('csswring')] | ||
```css | ||
a { | ||
color: var(--link-color); | ||
} | ||
``` | ||
[postcss-loader]: https://github.com/postcss/postcss-loader | ||
[webpack]: http://webpack.github.io/ | ||
In PostCSS you can choose what variables syntax you want or even take both. | ||
## Write Own Processor | ||
[W3C CSS Custom Properties]: http://www.w3.org/TR/css-variables/ | ||
[postcss-custom-properties]: https://github.com/postcss/postcss-custom-properties | ||
[postcss-simple-vars]: https://github.com/postcss/postcss-simple-vars | ||
You can parse CSS with the `postcss.parse()` method, which returns a CSS AST: | ||
### Perfomance | ||
```js | ||
var postcss = require('postcss'); | ||
PostCSS is one of the fastest CSS parsers written on JS. Only [CSSOM] is 10% | ||
faster and only because it parses CSS not so accurate as PostCSS does. | ||
Modular architecture makes PostCSS code is simple and easy to maintain. | ||
var css = postcss.parse('a { color: black }'); | ||
``` | ||
As result PostCSS is incredible fast. PostCSS is written on JS, but even with | ||
big [cssnext] plugin pack, it is 4 times faster than [libsass] written on C++. | ||
You can easily make changes to this AST. Use `css.nodes` to get children. | ||
Properties `rule.selector`, `decl.prop`, `decl.value`, `atrule.name` | ||
and `atrule.params` contain data. | ||
If you uses Ruby Sass right now, you will be excited with PostCSS developing | ||
process, because PostCSS is 40 times faster that Ruby Sass. | ||
```js | ||
css.nodes[0].value = 'white'; | ||
``` | ||
[cssnext]: https://github.com/cssnext/cssnext | ||
[libsass]: https://github.com/sass/libsass | ||
[CSSOM]: https://github.com/NV/CSSOM | ||
After changes have been made you can get the new CSS and a source map reflecting | ||
the modifications: | ||
### Powerful Tools | ||
```js | ||
var result = css.toResult(options); | ||
PostCSS plugins can read and rebuild entire CSS node tree. | ||
As result PostCSS has many powerful tools that would be impossible | ||
on preprocessors. Autoprefixer is a good example of how PostCSS plugin could | ||
be useful. | ||
result.css //=> 'a { color: white }' | ||
result.map //=> '{"version":3, … }' | ||
``` | ||
PostCSS allows you to build linters (like [doiuse] or [BEM Linter]), | ||
code review tools (like [list-selectors]) or minifiers (like [CSSWring]). | ||
With [postcss-data-packer] plugin you can create a “sprite” from inlined images | ||
by moving all `data:uri` values to separated file. | ||
The methods `postcss.parse()` and `CSS#toResult()` are part of a low level API, | ||
and - in most cases - it will be better to create processors with a simpler API | ||
and chaining. | ||
But my favorite example of PostCSS power is [RTLCSS]. As you know Jews and Arabs | ||
has right-to-left writing. Because writing affects to people perspective | ||
you need to change your site design (check out [Arabic Wikipedia]). | ||
RTLCSS plugin mirrors you design, replace `left` to `right` in your styles, | ||
change values order in `margin`, etc. | ||
### Processor | ||
[postcss-data-packer]: https://github.com/Ser-Gen/postcss-data-packer | ||
[Arabic Wikipedia]: https://ar.wikipedia.org/wiki/%D9%84%D8%BA%D8%A9_%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9 | ||
[list-selectors]: https://github.com/davidtheclark/list-selectors | ||
[BEM Linter]: https://github.com/necolas/postcss-bem-linter | ||
[CSSWring]: https://github.com/hail2u/node-csswring | ||
[doiuse]: https://github.com/anandthakker/doiuse | ||
[RTLCSS]: https://github.com/MohammadYounes/rtlcss | ||
The function `postcss(fn)` creates a processor from your function: | ||
## Quick Start | ||
```js | ||
var postcss = require('postcss'); | ||
1. Add PostCSS to your build tool. See [Grunt], [Gulp] and [webpack] plugins | ||
for further instructions. | ||
2. Select plugins from list below and add them to your PostCSS. | ||
3. Make awesome products. | ||
var processor = postcss(function (css, opts) { | ||
// Code to modify CSS | ||
}); | ||
``` | ||
[webpack]: https://github.com/postcss/postcss-loader | ||
[Grunt]: https://github.com/nDmitry/grunt-postcss | ||
[Gulp]: https://github.com/w0rm/gulp-postcss | ||
If you want to combine multiple processors (and parse the CSS only once), | ||
you can add several functions using the `use(fn)` method: | ||
## Plugins Packs | ||
```js | ||
var all = postcss(). | ||
use(prefixer). | ||
use(minifing); | ||
``` | ||
* [cssnext] is a pack of CSS 4 polyfills plugins. | ||
* [ACSS] contains plugins to control your CSS by special annotation comments. | ||
You can also add processor objects with the `postcss` function: | ||
[cssnext]: https://github.com/putaindecode/cssnext | ||
[ACSS]: https://github.com/morishitter/acss | ||
```js | ||
postcss().use( autoprefixer.postcss ); // via function | ||
postcss().use( autoprefixer ); // via object | ||
``` | ||
## Plugins | ||
A processor function can change the current CSS node tree: | ||
* [Autoprefixer] adds vendor prefixes to rules by Can I Use. | ||
* [cssgrace] with helpers and CSS 3 polyfills for IE and other old browsers. | ||
* [csswring] is a CSS minifier. | ||
* [rtlcss] mirrors styles for right-to-left locales. | ||
* [pixrem] is a `rem` unit polyfill. | ||
* [css-mqpacker] joins same CSS media queries into one rule. | ||
* [postcss-assets] inlines files and inserts image width and height. | ||
* [css2modernizr] analyzes your CSS and output only used Modernizr’s settings. | ||
* [postcss-bem-linter] lints CSS for SUIT CSS methodology. | ||
* [pleeease-filters] converts WebKit filters to SVG filter for other browsers. | ||
* [postcss-custom-selectors] to add custom alias for selectors. | ||
* [doiuse] lints CSS for browser support against Can I Use database. | ||
* [webpcss] adds links to WebP images for browsers that support it. | ||
* [postcss-import] inlines `@import` rules content. | ||
* [postcss-nested] unwraps nested rules. | ||
* [postcss-media-minmax] adds `<=` and `=>` statements to CSS media queries. | ||
* [postcss-mixins] to use mixins. | ||
* [postcss-easings] replaces easing name to `cubic-bezier()`. | ||
* [postcss-url] rebases or inlines `url()`. | ||
* [postcss-epub] adds `-epub-` prefix. | ||
* [postcss-custom-properties] is a polyfill for W3C CSS variables spec. | ||
* [mq4-hover-shim] is a shim for the `@media (hover: hover)` feature. | ||
* [postcss-color-palette] transforms CSS 2 color keywords to a custom palette. | ||
* [postcss-custom-media] to add custom alias for media queries. | ||
* [css-byebye] removes CSS rules by some criteria. | ||
* [postcss-simple-vars] adds Sass-style variables support. | ||
* [postcss-data-packer] moves an inlined data into a separate file. | ||
* [postcss-color-gray] adds `gray()` function. | ||
* [postcss-brand-colors] inserts branding colors by companies name. | ||
* [list-selectors] is a code review tool for your CSS. | ||
* [postcss-calc] reduce `calc()` with same units. | ||
* [postcss-font-variant] adds readable front variant properies support. | ||
* [postcss-simple-extend] adds `@extend` support. | ||
* [postcss-size] adds `size` shorcut to set width and height in one property. | ||
* [postcss-color-hex] transforms `rgb()` and `rgba()` to hex. | ||
* [postcss-host] make `:host` selectors work properly with pseudo-classes. | ||
* [postcss-color-rebeccapurple] is a `rebeccapurple` color polyfill. | ||
* [postcss-color-function] adds functions to transform colors. | ||
* [postcss-color-hex-alpha] adds `#rrggbbaa` and `#rgba` notation support. | ||
* [postcss-color-hwb] transforms `hwb()` to `rgb()`. | ||
* [postcss-single-charset] pops first `@charset` rule. | ||
```js | ||
postcss(function (css) { | ||
css.append( /* new rule */ ) | ||
}); | ||
``` | ||
[postcss-color-rebeccapurple]: https://github.com/postcss/postcss-color-rebeccapurple | ||
[postcss-custom-properties]: https://github.com/postcss/postcss-custom-properties | ||
[postcss-custom-selectors]: https://github.com/postcss/postcss-custom-selectors | ||
[postcss-color-hex-alpha]: https://github.com/postcss/postcss-color-hex-alpha | ||
[postcss-color-function]: https://github.com/postcss/postcss-color-function | ||
[postcss-single-charset]: https://github.com/hail2u/postcss-single-charset | ||
[postcss-color-palette]: https://github.com/zaim/postcss-color-palette | ||
[postcss-simple-extend]: https://github.com/davidtheclark/postcss-simple-extend | ||
[postcss-media-minmax]: https://github.com/postcss/postcss-media-minmax | ||
[postcss-custom-media]: https://github.com/postcss/postcss-custom-media | ||
[postcss-brand-colors]: https://github.com/postcss/postcss-brand-colors | ||
[postcss-font-variant]: https://github.com/postcss/postcss-font-variant | ||
[postcss-simple-vars]: https://github.com/postcss/postcss-simple-vars | ||
[postcss-data-packer]: https://github.com/Ser-Gen/postcss-data-packer | ||
[postcss-bem-linter]: https://github.com/necolas/postcss-bem-linter | ||
[postcss-color-gray]: https://github.com/postcss/postcss-color-gray | ||
[postcss-color-hex]: https://github.com/TrySound/postcss-color-hex | ||
[postcss-color-hwb]: https://github.com/postcss/postcss-color-hwb | ||
[pleeease-filters]: https://github.com/iamvdo/pleeease-filters | ||
[postcss-easings]: https://github.com/postcss/postcss-easings | ||
[postcss-assets]: https://github.com/borodean/postcss-assets | ||
[postcss-import]: https://github.com/postcss/postcss-import | ||
[postcss-nested]: https://github.com/postcss/postcss-nested | ||
[postcss-mixins]: https://github.com/postcss/postcss-mixins | ||
[mq4-hover-shim]: https://github.com/twbs/mq4-hover-shim | ||
[list-selectors]: https://github.com/davidtheclark/list-selectors | ||
[css2modernizr]: https://github.com/vovanbo/css2modernizr | ||
[Autoprefixer]: https://github.com/postcss/autoprefixer | ||
[css-mqpacker]: https://github.com/hail2u/node-css-mqpacker | ||
[postcss-epub]: https://github.com/Rycochet/postcss-epub | ||
[postcss-calc]: https://github.com/postcss/postcss-calc | ||
[postcss-size]: https://github.com/postcss/postcss-size | ||
[postcss-host]: https://github.com/vitkarpov/postcss-host | ||
[postcss-url]: https://github.com/postcss/postcss-url | ||
[css-byebye]: https://github.com/AoDev/css-byebye | ||
[cssgrace]: https://github.com/cssdream/cssgrace | ||
[csswring]: https://github.com/hail2u/node-csswring | ||
[webpcss]: https://github.com/lexich/webpcss | ||
[rtlcss]: https://github.com/MohammadYounes/rtlcss | ||
[pixrem]: https://github.com/robwierzbowski/node-pixrem | ||
[doiuse]: https://github.com/anandthakker/doiuse | ||
or create a completely new CSS root node and return it instead: | ||
## Usage | ||
```js | ||
postcss(function (css) { | ||
var newCSS = postcss.root() | ||
// Add rules and declarations | ||
return newCSS; | ||
}); | ||
``` | ||
### JavaScript API | ||
This generated processor transforms some CSS using | ||
the `process(css, opts)` method: | ||
```js | ||
var doubler = postcss(function (css) { | ||
// Clone each declaration | ||
css.eachDecl(function (decl) { | ||
decl.parent.prepend( decl.clone() ); | ||
}); | ||
}); | ||
var postcss = require('postcss'); | ||
var processor = postcss([require('cssnext'), require('cssgrace')]); | ||
var css = "a { color: black; }"; | ||
var result = doubler.process(css); | ||
result.css //=> "a { color: black; color: black; }" | ||
var result = processor.process(css, { from: 'app.css', to: 'app.out.css' }); | ||
console.log(result.css); | ||
``` | ||
You can change the original CSS filename via the `from` option, which | ||
can make syntax error more helpful: | ||
Read [postcss function], [processor] and [Result] API docs for more details. | ||
```js | ||
var wrong = "a {"; | ||
processor.process(wrong, { from: 'main.css' }); | ||
//=> Can't parse CSS: Unclosed block at line 1:1 in main.css | ||
``` | ||
[postcss function]: https://github.com/postcss/postcss/blob/master/API.md#postcss-function | ||
[processor]: https://github.com/postcss/postcss/blob/master/API.md#postcss-class | ||
[Result]: https://github.com/postcss/postcss/blob/master/API.md#result-class | ||
Options from `process(css, opts)` will be sent to processors | ||
as the second argument. | ||
### Source Maps | ||
You can also use the result from a previous postprocessor, or | ||
an already-parsed `Root`, as an argument to the next one: | ||
```js | ||
result = processor1.process(css) | ||
processor2.process(result) | ||
``` | ||
### Multiple Inputs | ||
The function `postcss()` generates a processor for only one input. | ||
If you need to process several inputs (for example, when concatenating files) | ||
you can use `postcss.parse()`. | ||
Let’s join two CSS strings with full source map support in only 5 lines of code: | ||
```js | ||
var file1 = postcss.parse(css1, { from: 'a.css' }); | ||
var file2 = postcss.parse(css2, { from: 'b.css' }); | ||
file1.append( file2 ); | ||
var result = file1.toResult({ to: 'app.css', map: true }); | ||
``` | ||
### Source Map | ||
By using [source maps], a browser’s development tools can indicate the | ||
@@ -528,7 +318,5 @@ original position of your styles before the css file was transformed. | ||
To generate a new source map with the default options, provide `map: true`. | ||
This will inline sourcemap with source content. | ||
This will inline sourcemap with source content. If you don’t want the map | ||
inlined, you can use `map.inline: false` option. | ||
If you don't want the map inlined, you can use `inline: false` | ||
in the options passed to `processor.process(css, opts)`. | ||
```js | ||
@@ -542,18 +330,4 @@ var result = processor.process(css, { | ||
result.map //=> '{"version":3,"file":"main.out.css","sources":["main.css"],"names":[],"mappings":"AAAA,KAAI"}' | ||
fs.writeFileSync('main.out.css', result.css); | ||
fs.writeFileSync('main.out.css.map', result.map); | ||
``` | ||
Or set `from` in `postcss.parse(css, opts)` and `to` in `root.toResult(opts)`: | ||
```js | ||
var root = postcss.parse(css, { from: 'main.css', { inline: false } }); | ||
root.last.removeSelf(); // Example transformation | ||
var result = root.toResult({ to: 'main.out.css' }); | ||
fs.writeFileSync('main.out.css', result.css); | ||
fs.writeFileSync('main.out.css.map', result.map); | ||
``` | ||
If PostCSS is handling CSS and finds source maps from previous transformations, | ||
@@ -610,3 +384,2 @@ it will automatically update the CSS with the same options. | ||
PostCSS will try to correct any syntax error that it finds in the CSS. | ||
For example, it will parse `a {` as `a {}`. | ||
@@ -622,462 +395,5 @@ ```js | ||
### Helpers | ||
## How to Develop PostCSS Plugin | ||
#### Vendor | ||
PostCSS contains height optimized code to split vendor prefix: | ||
```js | ||
var vendor = require('postcss/lib/vendor'); | ||
vendor.prefix('-moz-tab-size') //=> '-moz-' | ||
vendor.unprefixed('-moz-tab-size') //=> 'tab-size' | ||
``` | ||
#### List | ||
To safely split comma- or space-separated values (such as those | ||
in `background-image` or `transform`) with brackets and quotes support, | ||
you can use the `list` helper: | ||
```js | ||
var list = require('postcss/lib/list'); | ||
list.space(image.value) //=> ['linear-gradient(white, black)', 'blue'] | ||
list.comma(transform.value) //=> ['color 200ms', 'background 200ms'] | ||
``` | ||
### Nodes | ||
Processor functions receive a `Root` node which contains the CSS node tree. | ||
```js | ||
var processor = postcss(function (cssRoot) { | ||
}); | ||
``` | ||
There are 4 types of child nodes: `Comment`, `AtRule`, `Rule` and `Declaration`. | ||
All nodes possess `toString()` and `clone()` methods. | ||
You can parse CSS and get a `Root` node by calling | ||
the `postcss.parse(css, opts)` method: | ||
```js | ||
var cssRoot = postcss.parse('a { }'); | ||
``` | ||
Many of the methods on a node will return the current node, which enables | ||
you to build method chains: | ||
```js | ||
root.append( rule1 ).append( rule2 ).toString(); | ||
``` | ||
If some node broke you plugin syntax you can throw CSS syntax error: | ||
```js | ||
throw node.error('Bad variable syntax'); | ||
//=> CssSyntaxError: app.css:45:5: Bad variable syntax | ||
// var-name: 1 | ||
// ^ | ||
``` | ||
### Node Source | ||
Every node stores its origin file (if you provide the `from` option | ||
to the `process` or `parse` methods) and position: | ||
```js | ||
var root = postcss.parse(css, { from: 'main.css' }); | ||
var rule = root.nodes[0]; | ||
rule.source.input.file //=> 'main.css' | ||
rule.source.start //=> { line: 5, position: 1 } | ||
rule.source.end //=> { line: 10, position: 5 } | ||
``` | ||
### Whitespace | ||
All nodes (excluding the `Root`) have a `before` property which contains | ||
the indentation and any previous whitespace. | ||
Nodes with children (`Root`, `AtRule` and `Rule`) also contain an `after` | ||
property which indicates the spaces after the last child and before a `}` | ||
character or the end of the file. | ||
Every `Declaration` has a `between` property with colon, spaces and comments | ||
between the property name and value. `Rule` stores the spaces and comments | ||
between the selector and `{` in the `between` property. `AtRule` uses `between` | ||
to indicate the spaces and comments before either a `{` or `;`, if the at-rule | ||
is bodiless. | ||
```js | ||
var root = postcss.parse("a {\n color: black;\n}\n"); | ||
root.nodes[0].between //=> " " between selector and { | ||
root.nodes[0].nodes[0].before //=> "\n " before color: black | ||
root.nodes[0].nodes[0].between //=> ": " between property name and value | ||
root.nodes[0].after //=> "\n" before } | ||
root.after //=> "\n" from end of file | ||
``` | ||
The simplest way to minify CSS is to set `before`, `between` and `after` | ||
properties to an empty string: | ||
```js | ||
var minifier = postcss(function (css) { | ||
css.eachDecl(function (decl) { | ||
decl.before = ''; | ||
decl.between = ':'; | ||
}); | ||
css.eachRule(function (rule) { | ||
rule.before = ''; | ||
rule.between = ''; | ||
rule.after = ''; | ||
}); | ||
css.eachAtRule(function (atRule) { | ||
atRule.before = ''; | ||
atRule.between = ''; | ||
atRule.after = ''; | ||
}); | ||
css.eachComment(function (comment) { | ||
comment.removeSelf(); | ||
}); | ||
}); | ||
var css = "a {\n color:black\n}\n"; | ||
minifier.process(css).css //=> "a{color:black}" | ||
``` | ||
Note that nodes may have not `before` or `between` properties: | ||
* If node was created by hand via `postcss.rule()`. | ||
* `node.clone()` will clean all style properties to use the style | ||
for a new CSS root. | ||
### Raw Properties | ||
Some CSS values (selectors, comment text, at-rule params and declaration values) | ||
can contain comments. PostCSS will clean them to remove trailing spaces: | ||
```js | ||
var root = postcss.parse("a /**/ b {}"); | ||
var rule = root.first; | ||
rule.selector //=> 'a b' trimmed and cleaned from comments | ||
rule._selector.raw //=> 'a /**/ b' original raw value | ||
``` | ||
But PostCSS preservers the raw content in order to stringify it back to CSS, | ||
in case you don’t change the original value. In general, PostCSS tries | ||
to preserve the original CSS byte-to-byte whenever possible: | ||
```js | ||
rule.toString() //=> 'a /**/ b {}' with comment | ||
rule.selector = '.link b'; | ||
rule.toString() //=> '.link b {}' you change value and origin comment was gone | ||
``` | ||
### Containers | ||
`Root`, `AtRule` and `Rule` nodes can contain children in `nodes` property. | ||
There are some common methods to perform work on children: | ||
* `append(newChild)` adds a child at the end of the children list. | ||
* `prepend(newChild)` adds a child at the beginning of the children list. | ||
* `insertBefore(existsChild, newChild)` inserts a new child before a | ||
pre-existing child. | ||
* `insertAfter(existsChild, newChild)` inserts a new child after some | ||
pre-existing child. | ||
* `remove(existsChild)` removes a child. | ||
* `removeAll()` to remove all children. | ||
* `index(existsChild)` returns a child’s index. | ||
* `some(fn)` returns true if `fn` returns true for any child. | ||
* `every(fn)` returns true if `fn` returns true for all children. | ||
Methods `append`, `prepend`, `insertBefore` and `insertAfter` will also accept | ||
arrays and `Root` nodes as an argument. | ||
Methods `insertBefore`, `insertAfter` and `remove` will accept child nodes | ||
or indexes as the `existsChild` argument. Note that providing a child index will | ||
result in the method completing much faster. | ||
You can combine `node.clone()` and `node.parent.insertBefore()` | ||
by `node.cloneBefore()` and `node.cloneAfter()` methods. | ||
There are two shortcuts to provide the first and last child of a node: | ||
```js | ||
rule.first //=> First declaration in rule | ||
rule.last //=> Last declaration in rule | ||
``` | ||
### Children | ||
`Comment`, `AtRule`, `Rule` and `Declaration` nodes should be wrapped | ||
in other nodes. | ||
All children contain a `parent` property which indicates the parent node: | ||
```js | ||
rule.nodes[0].parent == rule; | ||
``` | ||
All children have a `removeSelf()` method: | ||
```js | ||
rule.nodes[0].removeSelf(); | ||
``` | ||
But invoking the `remove(index)` method on the parent is much faster: | ||
```js | ||
rule.each(function (decl, i) { | ||
rule.remove(i); | ||
}); | ||
``` | ||
You can move nodes between parents by `moveTo()`, `moveBefore()` | ||
and `moveAfter()` methods. | ||
To replace node by other one use `node.replaceWith(other)` method. | ||
Methods `prev()` and `next()` returns previous and next child in node parent. | ||
### Iterators | ||
All parent nodes have an `each` method which allows you to iterate over | ||
its child nodes: | ||
```js | ||
root = postcss.parse('a { color: black; display: none }'); | ||
root.each(function (rule, i) { | ||
if ( rule.type == 'rule' ) { | ||
console.log(rule.selector, i); // Will log "a 0" | ||
} | ||
}); | ||
root.first.each(function (decl, i) { | ||
if ( rule.type != 'comment' ) { | ||
console.log(decl.prop, i); // Will log "color 0" and "display 1" | ||
} | ||
}); | ||
``` | ||
Unlike `for {}`-cycle construct or `Array#forEach()` this iterator is safe. | ||
So you can mutate the children during iteration and PostCSS will fix | ||
the current index: | ||
```js | ||
rule.nodes.forEach(function (decl, i) { | ||
rule.prepend( decl.clone() ); | ||
// Will infinitely cycle as prepending the current declaration will | ||
// cause the second and successive indexes to interact with the | ||
// current declaration endlessly | ||
}); | ||
rule.each(function (decl, i) { | ||
rule.prepend( decl.clone() ); | ||
// Will work correctly (each declaration will be cloned only once), | ||
// because the iterator index will be recalculated only after the prepend | ||
}); | ||
``` | ||
Because CSS has a nested structure, PostCSS also features a recursive iterator | ||
`eachInside`: | ||
```js | ||
root.eachInside(function (node, i) { | ||
console.log(node.type + ' inside ' + node.parent.type); | ||
}); | ||
``` | ||
There are also shortcuts so that you can recursively iterate over nodes | ||
of a specific type: | ||
```js | ||
root.eachDecl(function (decl, i) { | ||
// Each declaration inside root | ||
}); | ||
root.eachRule(function (rule, i) { | ||
// Each rule inside root and any nested at-rules | ||
}); | ||
root.eachAtRule(function (atRule, i) { | ||
// Each at-rule inside root and any nested at-rules | ||
}); | ||
root.eachComment(function (comment, i) { | ||
// Each comment inside root | ||
}) | ||
``` | ||
Methods `eachDecl()` and `eachAtRule()` also accept a string or regexp | ||
filter to only iterate over declarations with some property name | ||
or for at-rules with some name. | ||
```js | ||
root.eachDecl(/^background/, function (decl) { | ||
inlineImages(decl); | ||
}); | ||
``` | ||
You can break out from the iteration by returning `false`. | ||
If you want to change values in all children, you can use very `replaceValues` | ||
method: | ||
```js | ||
root.replaceValues(/\d+(\.\d+)?rem/, | ||
{ props: ['width', 'height'], fast: 'rem' }, function (str) { | ||
var rem = parseFloat(str); | ||
return 16 * rem; | ||
}) | ||
``` | ||
Option `fast` will be used for fast precheck by `indexOf()`. | ||
### Root Node | ||
`Root` node contains the entire CSS tree. Its children can only be `Comment`, | ||
`AtRule`, or `Rule` nodes in the `nodes` property. | ||
You can create a new root using the shortcut: | ||
```js | ||
var root = postcss.root(); | ||
``` | ||
Method `toString()` stringifies the entire node tree and returns a CSS string: | ||
```js | ||
root = postcss.parse(css); | ||
root.toString() == css; | ||
``` | ||
If PostCSS found previous source map, it will save all the relevant information | ||
within `Root#prevMap`: | ||
``` | ||
root = postcss.parse(css); | ||
if (root.prevMap && root.prevMap.inline) { | ||
console.log('Inlined map: ' + root.prevMap.annotation) | ||
} | ||
``` | ||
### Comment Node | ||
```css | ||
/* Block comment */ | ||
``` | ||
PostCSS creates `Comment` nodes only for comments found between rules | ||
or declarations. Comments found within selectors, at-rules params, | ||
or declaration values will be stored in the Raw property. | ||
`Comment` has only one property: `text` which contains the trimmed text inside | ||
the comment. | ||
```js | ||
comment.text //=> "Block comment" | ||
``` | ||
You can create a new comment using a shortcut: | ||
```js | ||
var comment = postcss.comment({ text: 'New comment' }); | ||
``` | ||
### AtRule Node | ||
```css | ||
@charset 'utf-8'; | ||
@font-face { | ||
font-family: 'Cool' | ||
} | ||
@media print { | ||
img { display: none } | ||
} | ||
``` | ||
`AtRule` has two own properties: `name` and `params`. | ||
As illustrated above, some at-rules do not contain any children | ||
(for example, `@charset` or `@import`), some at-rules can only contain | ||
declarations (for example, `@font-face` or `@page`), but most of them | ||
can contain rules and nested at-rules (for example, `@media`, `@keyframes` | ||
and others). | ||
You can create a new at-rule using a shortcut: | ||
```js | ||
var atRule = postcss.atRule({ name: 'charset', params: 'utf-8' }); | ||
``` | ||
### Rule Node | ||
```css | ||
a { | ||
color: black; | ||
} | ||
``` | ||
`Rule` nodes have a `selector` property and contain their `Declaration` | ||
and `Comment` children within the `nodes` property. | ||
They also possess a `selectors` shortcut, which returns an array: | ||
```js | ||
rule.selector //=> "a, b" | ||
rule.selectors //=> ['a', 'b'] | ||
``` | ||
You can avoid using the `Declaration` constructor for `append` | ||
and other insert methods, by: | ||
```js | ||
rule.append({ prop: 'color', value: 'black' }); | ||
``` | ||
The property `semicolon` indicates if the last declaration within the rule has | ||
a semicolon or not: | ||
```js | ||
var root = postcss.parse('a { color: black }'); | ||
root.first.semicolon //=> false | ||
var root = postcss.parse('a { color: black; }'); | ||
root.first.semicolon //=> true | ||
``` | ||
You can create a new rule using a shortcut: | ||
```js | ||
var rule = postcss.rule({ selector: 'a' }); | ||
``` | ||
### Declaration Node | ||
```css | ||
color: black | ||
``` | ||
`Declaration` nodes have `prop`, `value` and `important` properties. | ||
You can create a new declaration using a shortcut: | ||
```js | ||
var decl = postcss.decl({ prop: 'color', value: 'black' }); | ||
``` | ||
Or you can use the short form available via a rule’s `append()` and other | ||
add methods: | ||
```js | ||
rule.append({ prop: 'color', value: 'black' }); | ||
``` | ||
* [PostCSS API](https://github.com/postcss/postcss/blob/master/API.md) | ||
* [Plugin Boilerplate](https://github.com/postcss/postcss-plugin-boilerplate) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
146955
23
2392
395