Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

postcss

Package Overview
Dependencies
Maintainers
1
Versions
263
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss - npm Package Compare versions

Comparing version 4.0.3 to 4.0.4

API.md

3

ChangeLog.md

@@ -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);

77

lib/container.js
"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": {

@@ -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)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc