Files
postcss/API.md
T
2015-02-14 10:59:59 +03:00

25 KiB
Raw Permalink Blame History

PostCSS API

postcss function

The postcss function is the main entry point for PostCSS.

var postcss = require('postcss');

postcss(plugins)

Returns a new PostCSS instance that will apply plugins as CSS processors.

postcss([autoprefixer, cssnext, cssgrace]).process(css).css;

You can also set plugins with the PostCSS#use method.

See PostCSS#use below for details about plugin formats.

postcss.parse(css, opts)

Parses source css and returns a new Root node, which contains the source CSS nodes.

// Simple CSS concatenation with source map support
var root1 = postcss.parse(css1, { from: file1 });
var root2 = postcss.parse(css2, { from: file2 });
root1.append(root2).toResult().css;

Options:

  • from: the path to the source CSS file. You should always set from, because it is used in map generation and in syntax error messages.
  • safe: enable Safe Mode, in which PostCSS will try to fix CSS syntax errors.
  • map: an object of source map options. Only map.prev is used in parse.

postcss.root(props)

Creates a new Root node.

postcss.root({ after: '\n' }).toString() //=> "\n"

postcss.atRule(props)

Creates a new AtRule node.

postcss.atRule({ name: 'charset' }).toString() //=> "@charset"

postcss.rule(props)

Creates a new Rule node.

postcss.rule({ selector: 'a' }).toString() //=> "a {\n}"

postcss.decl(props)

Creates a new Declaration node.

postcss.decl({ prop: 'color', value: 'black' }).toString() //=> "color: black"

postcss.comment(props)

Creates a new Comment node.

postcss.comment({ text: 'test' }).toString() //=> "/* test */"

PostCSS class

A PostCSS instance contains plugins to process CSS. You can create one PostCSS instance, initialize its plugins, and then use that instance on many CSS files.

var processor = postcss([autoprefixer, cssnext, cssgrace]);
processor.process(css1).css;
processor.process(css2).css;

use(plugin)

Adds a plugin to be used as a CSS processor.

var processor = postcss();
processor.use(autoprefixer).use(cssnext).use(cssgrace);

Plugins can also be added by passing them as arguments when creating a postcss instance (cf. postcss(plugins)).

Plugins can come in three formats:

  1. A function. PostCSS will pass the function a Root node as the first argument.
  2. An object with a postcss method. PostCSS will use that method as described in #1.
  3. Another PostCSS instance. PostCSS will copy plugins from that instance to this one.

Plugin functions should mutate the passed Root node and return nothing, or return a new Root node.

processor.use(function (css) {
    css.prepend({ name: 'charset', params: '"UTF-8"' });
});
processor.use(function (css) {
    return postcss.root();
});

process(css, opts)

This is the main method of PostCSS. It will parse the source CSS and create a Root node; send this Root to each plugin successively, for transformations; and then return a Result instance created from the transformed Root.

var result = processor.process(css, { from: 'a.css', to: 'a.out.css' });

Input CSS formats are:

  • A string of CSS.
  • A Result instance from another PostCSS processor. PostCSS will accept the already parsed Root from it.
  • Any object with a toString() method -- for example, a file stream.

Options:

  • from: the path of the CSS source file. You should always set from, because it is used in source map generation and syntax error messages.
  • to: the path where you’ll put the output CSS file. You should always set to to generate correct source maps.
  • safe: enable Safe Mode, in which PostCSS will try to fix CSS syntax errors.
  • map: an object of source map options.

Result class

There is a two way to get Result instance. PostCSS#process(css, opts) returns it or you can call Root#toResult(opts).

var result1 = postcss().process(css);
var result2 = postcss.parse(css).toResult();

root

This property contains source Root instance.

root.toResult().root == root;

opts

Options from PostCSS#process(css, opts) or Root#toResult(opts) call.

postcss().process(css, opts).opts == opts;

css

Lazy method, that will stringify Root instance to CSS string on first call and generates source map to map property if it is necessary.

postcss().process('a{}').css //=> "a{}"

map

Lazy method, that will generates source map for Root changes and stringify CSS to css property.

It contains instance of SourceMapGenerator class from source-map library.

result.map.toJSON() //=> { version: 3, file: 'a.css', sources: ['a.css'], … }

Result instance will contain map property only if PostCSS decide, that source map should be in separated file. If source map will be inlined to CSS, Result instance will not have this property.

if ( result.map ) {
    fs.writeFileSync(to + '.map', result.map.toString());
}

By default, PostCSS will inline map to CSS, so in most cases this property will be empty. PostCSS will create it only if user set map.inline = false option or if input source map was in separated file.

Vendor module

Contains helpers to work with vendor prefixes.

prefix

Returns vendor prefix.

vendor.prefix('-moz-tab-size') //=> '-moz-'

unprefixed

Returns value without vendor prefix.

vendor.unprefixed('-moz-tab-size') //=> 'tab-size'

List module

Contains helpers to safely split CSS values with brackets and quotes detection.

var list = require('postcss/lib/list');

list.space

Safely splits space-separated values (like background).

list.split('1px calc(10% + 1px) "border radius"')
//=> ['1px', 'calc(10% + 1px)', '"border radius"']

list.comma

Safely splits comma-separated values (like transition).

list.split('1px 2px, rgba(255, 0, 0, 0.9), "border, top"')
//=> ['1px 2px', 'rgba(255, 0, 0, 0.9)', '"border, top"']

Input class

Represents input source of CSS.

var root  = postcss.parse(css, { from: file });
var input = root.source.input;

file

Absolute path to CSS source file from from option.

var root  = postcss.parse(css, { from: 'a.css' });
root.source.input.file //=> '/home/ai/a.css'

id

Unique ID of CSS source if user missed from and we didn’t know file path.

var root  = postcss.parse(css);
root.source.input.file //=> undefined
root.source.input.id   //=> <input css 1>

from

Contains file if user set from option or id if he or she didn’t.

var root  = postcss.parse(css, { from: 'a.css' });
root.source.input.file //=> '/home/ai/a.css'

var root  = postcss.parse(css);
root.source.input.from //=> <input css 1>

map

Represents input source map from compilation step before PostCSS, (from example, from Sass compiler).

map.consumer() returns instance of SourceMapConsumer class from source-map library.

root.source.input.map.consumer().sources //=> ['a.sass']

origin(line, column)

Uses input source map and returns symbol position in origin source (for example, in Sass file):

root.source.input.origin(1, 1) //=> { source: 'a.css', line: 3, column: 1 }

Nodes common methods

All node classes have many common methods.

type

String with node’s type. It can be root, atrule, rule, decl or comment.

postcss.decl({ prop: 'color', value: 'black' }).type //=> 'decl'

parent

Link to parent node.

root.nodes[0].parent == root;

source

Origin source of node. It contains start and end positions and Input instance in source.input property.

decl.source.input.from //=> '/home/ai/a.sass'
decl.source.start      //=> { line: 10, column: 2 }
decl.source.end        //=> { line: 10, column: 12 }

The property is used in map generation. If you will create node manually (for example, by postcss.decl) node will not have a source property and will be missed in source map. So plugin developer should clone nodes (it saves source) or set source manually:

var rule = postcss.rule({ selector: 'a', source, atrule.source });
atrule.parent.insertBefore(atrule, rule);

toString()

Stringifys node to CSS string.

postcss.rule({ selector: 'a' }) //=> 'a {}''

error(message)

Returns CssSyntaxError instance with position of current node. It will use input source map to get origin position even from compiltion step before PostCSS (for example, in Sass file). Error message with also contains small example of source code.

if ( !variables[name] ) {
    throw decl.error('Unknown variable ' + name);
    // CssSyntaxError: a.sass:4:3: Unknown variable $black
    // a
    //   color: $black
    //   ^
    //   background: white
}

You can also use this method for better warning messages:

if ( oldSyntax.check(decl) ) {
    console.warn( decl.error('Old syntax for variables').message );
    // a.sass:4:3: Old syntax for variables
}

next() and prev()

Return next/previous children of node’s parent. Return undefined for first/last child.

var annotation = decl.prev();
if ( annotation.type == 'comment' ) {
    readAnnotation( annotation.text );
}

root()

Returns Root instance of current nodes tree.

root.nodes[0].nodes[0].root() == root

removeSelf()

Removes current node from parent and cleans parent property in this node and node’s children.

if ( decl.prop.match(/^-webkit-/) ) {
    decl.removeSelf();
}

replaceWith(otherNode)

Inserts other node before and removes current node.

if ( atrule.name == 'mixin' ) {
    atrule.replaceWith(mixinRules[atrule.params]);
}

clone(props)

Clones node, cleans parent and code style propeties in current node and node’s children.. You can override some properties in clone by props argument.

var clonded = decl.clone({ prop: '-moz-' + decl.prop });
cloned.before     //=> undefined
cloned.parent     //=> undefined
cloned.toString() //=> -moz-transform: scale(0)

cloneBefore(props) and cloneAfter(props)

Shortcuts to clone node and insert clone before/after current node.

decl.cloneBefore({ prop: '-moz-' + decl.prop });

moveTo(newParent)

Removes node from current parent and inserts node to the end of newParent.

It will clean before and after code style properties to use new indentation in new parent. If will clean between property if new parent is in other root.

atrule.moveTo(atrule.parent.parent);

moveBefore(otherNode) and moveAfter(otherNode)

Remove node from current parent and insert it to new parent before/after otherNode.

It will also clean code style properties as moveTo(newParent) does.

style(prop, defaultType)

Returns code style property value. If node code style property will be missed (like from manually built nodes or from clones), PostCSS will try to autodetect it by other nodes in tree.

var root = postcss.parse('a { background: white }');
root.nodes[0].append({ prop: 'color', value: 'black' });
root.nodes[0].nodes[1].style('before') //=> ' '

If PostCSS can’t find any nodes to copy a code style, it will use defaultType value from node.defaultStyle object.

postcss.decl({ prop: 'color', value: 'black' }).style('before') //=> '\n    '

Containers common methods

Root, AtRule and Rule classes has some common methods to works with children.

Note, that all containers can store any content. If you will write rule inside rule, PostCSS will parse it.

nodes

Array with node’s children.

var root = postcss.parse('a { color: black }');
root.nodes.length           //=> 1
root.nodes[0].selector      //=> 'a'
root.nodes[0].nodes[0].prop //=> 'color'

first

Shortcut to get first child.

rule.first == rules.nodes[0];

last

Shortcut to get last child.

rule.last == rule.nodes[rule.nodes.length - 1];

index(child)

Returns child’d index in parent nodes:

rule.index( rule.nodes[2] ) //=> 2

every(callback) and some(callback)

Return true if callback will return true on all/one children.

var noPrefixes = rule.every(function (decl) {
    return decl.prop[0] != '-';
});
var hasPrefix = rule.some(function (decl) {
    return decl.prop[0] == '-';
});

each(callback)

Iterates through container’s children. Returning false will break iteration.

var color;
rule.each(function (decl) {
    if ( decl.prop == 'color' ) {
        color = decl.value;
        return false;
    }
});

Unlike for {}-cycle or Array#forEach() this iterator is safe. So you can mutate the children during iteration and PostCSS will fix the current index:

var root = postcss.parse('a { color: black; z-index: 1 }');
var rule = root.first;

for ( var i = 0; i < rule.nodes.length; i++ ) {
    var decl = rule.nodes[i];
    decl.cloneBefore({ prop: '-webkit-' + decl.prop });
    // Cycle will be infinite, because cloneBefore move current node
    // to next index
}

rule.each(function (decl) {
    decl.cloneBefore({ prop: '-webkit-' + decl.prop });
    // Will be executed only for color and z-index
});

Callback will receive 2 arguments with child instance and child index number.

eachInside(callback)

Recursive iterates through children and children of children.

root.eachInside(function (node) {
    // Will be iterate through all nodes
});

This method is also safe as each() method.

eachDecl(prop, callback)

Recursive iterates through all declaration inside container.

root.eachDecl(function (decl) {
    if ( decl.prop.match(/^-webkit-/) ) {
        decl.removeSelf();
    }
});

You can filter declarations by property name with string or regexp.

// Make flat design
root.eachDecl('border-radius', function (decl) {
    decl.removeSelf();
});
root.eachDecl(/^background/, function (decl) {
    decl.value = takeFirstColorFromGradient(decl.value);
});

This method is also safe as each() method.

eachAtRule(name, calllback)

Recursive iterates through all at-rules inside container.

root.eachAtRule(function (rule) {
    if ( rule.name.match(/^-webkit-/) ) rule.removeSelf();
});

You can filter at-rules by name with string or regexp.

var first = false;
root.eachAtRule('charset', function (rule) {
    if ( !first ) {
        first = true;
    } else {
        rule.removeSelf();
    }
});

This method is also safe as each() method.

eachRule(callback)

Recursive iterates through all rules inside container.

var selectors = [];
root.eachRule(function (rule) {
    selectors.push(rule.selector);
});
console.log('You CSS uses ' + selectors.length + ' selectors');

This method is also safe as each() method.

eachComment(callback)

Recursive iterates through all comments inside container.

root.eachComment(function (comment) {
    comment.removeSelf();
})

This method is also safe as each() method.

replaceValues(regexp, opts, callback)

Replaces regexp in all declaration’s values inside container. It is useful to add some custom unit or function. Callback will receive same arguments as in String#replace.

You can make it faster by fast option. PostCSS will execute slow regexp only after fast value.indexOf(opts.fast) check. Also you can set a property names array in props option.

root.replaceValues(/\d+rem/, { fast: 'rem' }, function (string) {
    return 15 * parseInt(string) + 'px';
});

prepend(node) and append(node)

Insert a new node to start/end.

var decl = postcss.decl({ prop: 'color', value: 'black' });
rule.append(decl);

Because each node class has unique properties, you can use these shortcuts:

root.append({ name: '@charset', params: '"UTF-8"' }); // at-rule
root.append({ selector: 'a' });                       // rule
rule.append({ prop: 'color', value: 'black' });       // declaration
rule.append({ text: 'Comment' })                      // comment

insertBefore(oldNode, newNew) and insertAftr(oldNode, newNew)

Insert newNode before/after oldNode (index or node instance).

rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop }));

You can also use shortcuts here like in append() method.

rule.insertBefore(decl, { prop: 'color', value: 'black' });

remove(node)

Removes node from container and clean parent properties in node and node’s children.

rule.nodes.length  //=> 5
rule.remove(decl);
rule.nodes.length  //=> 4
decl.parent        //=> undefined

You can use node instance or node index in node argument.

removeAll()

Removes all children from container and cleans their parent properties.

rule.removeAll();
rule.nodes.length //=> 0

Root node

Represents CSS file and contains all nodes inside.

var root = postcss.parse('a{color:black} b{z-index:2}');
root.type         //=> 'root'
root.nodes.length //=> 2

after

Stores space symbols after last child like \n from end of the file.

var root = parse('a {}\nb { color: black }\n');
root.after //=> '\n'

AtRule node

Represents at-rule. Node will have nodes property if it have {} in CSS.

var root = postcss.parse('@charset "UTF-8"; @media print {}');

var charset = root.first;
charset.type  //=> 'atrule'
charset.nodes //=> undefined

var media = root.last;
media.nodes   //=> []

name

Stores at-rule name.

var root  = postcss.parse('@media print {}');
var media = root.first;
media.name //=> 'media'

params

Stores at-rule parameters.

var root  = postcss.parse('@media print, screen {}');
var media = root.first;
media.params //=> 'print, screen'

Value will be cleaned from inner comments. Origin value with comments will be in _params.raw property.

var root  = postcss.parse('@media print, /**/ screen {}');
var media = root.first;
media.params      //=> 'print,  screen'
media._params.raw //=> 'print, /**/ screen'
media.toString()  //=> '@media print, /**/ screen {}'

If you will not change parameters, PostCSS will stringify origin raw value.

before

Code style property with space symbols before at-rule.

var root  = postcss.parse('@charset "UTF-8";\n@media print {}\n');
var media = root.last;
media.before //=> '\n'

Default value is \n, except first rule in root where before will be empty.

afterName

Code style property with space symbols between at-rule name and parameters.

var root  = postcss.parse('@media\n  print,\n  screen {}\n');
var media = root.first;
media.afterName //=> '\n  '

Default value is .

between

Code style property with spaces between parametes and {.

var root  = postcss.parse('@media print, screen\n{}\n');
var media = root.first;
media.before //=> '\n'

Default value is .

after

Code style property with spaces between last child and }.

var root  = postcss.parse('@media print {\n  a {}\n  }\n');
var media = root.first;
media.after //=> '\n  '

Default value is \n if at-rule has children and empty string if it doesn’t.

semicolon

Code style property for at-rules with declarations, that last children has optional ;.

postcss.parse('@page{color:black}').first.semicolon  //=> undefined
postcss.parse('@page{color:black;}').first.semicolon //=> true

Rule node

Represents CSS rule with selector.

var root = postcss.parse('a{}');
var rule = root.first;
rule.type       //=> 'rule'
rule.toString() //=> 'a{}'

selector

Stores rule’s selector string.

var root = postcss.parse('a, b { }');
var rule = root.first;
rule.selector //=> 'a, b'

Value will be cleaned from inner comments. Origin value with comments will be in _selector.raw property.

var root = postcss.parse('a /**/ b {}');
var rule = root.first;
rule.selector      //=> 'a  b'
rule._selector.raw //=> 'a /**/ b'
rule.toString()    //=> 'a /**/ b {}'

If you will not change selector, PostCSS will stringify origin raw value.

selectors

Dynamic property that will split selector by comma and return array.

var root = postcss.parse('a, b { }');
var rule = root.first;

rule.selector  //=> 'a, b'
rule.selectors //=> ['a', 'b']

rule.selectors = ['a', 'strong'];
rule.selector //=> 'a, strong'

before

Code style property with space symbols before rule.

var root = postcss.parse('a {}\nb {}\n');
var rule = root.last;
rule.before //=> '\n'

Default value is \n, except first rule in root where before will be empty.

after

Code style property with spaces between last child and }.

var root = postcss.parse('@a {\n  color: black\n  }\n');
var rule = root.first;
root.after //=> '\n  '

Default value is \n if rule has children and empty string if it doesn’t.

semicolon

Code style property, that last children has optional ;.

postcss.parse('a{color:black}').first.semicolon  //=> undefined
postcss.parse('a{color:black;}').first.semicolon //=> true

Declaration node

Represents CSS declaration.

var root = postcss.parse('a { color: black }');
var decl = root.first.first;
decl.type       //=> 'decl'
decl.toString() //=> ' color: black'

prop

Stores property name.

var root = postcss.parse('a { color: black }');
var decl = root.first.first;
decl.prop //=> 'color'

value

Stores declaration value.

var root = postcss.parse('a { color: black }');
var decl = root.first.first;
decl.value //=> 'black'

Value will be cleaned from inner comments. Origin value with comments will be in _value.raw property.

var root = postcss.parse('a { border-radius: 3px /**/ 0 }');
var decl = root.first.first;
decl.value      //=> '3px  0'
decl._value.raw //=> '3px /**/ 0'
decl.toString() //=> ' border-radius: 3px /**/ 0'

If you will not change value, PostCSS will stringify origin raw value.

before

Code style property with space symbols before declaration.

var root = postcss.parse('a {\n  color: black\n}\n');
var decl = root.first.first;
decl.before //=> '\n  '

Default value is \n .

between

Code style property with symbols between property and value.

var root = postcss.parse('a { color/**/: black }');
var decl = root.first.first;
decl.between //=> '/**/: '

Default value is : .

important

Property is true if declaration has !important statement.

var root = postcss.parse('a { color: black !important; color: white }');
root.first.first.important //=> true
root.first.last.important  //=> undefined

If value has comments before !important statement, they will be stored in _important property.

var root = postcss.parse('a { color: black /**/ !important }');
root.first.first._important //=> ' /**/ !important'

Comment node

Represents comment between declarations or rules. Comments inside selectors, at-rules params, or declaration values will be stored in the raw properties.

var root    = postcss.parse('a { color: /* inner */ black; /* outer */ }');
var decl    = root.first.first;
var comment = root.first.last;

comment.type //=> 'comment'
decl.between //=> ': /* inner */'

text

Stores comment text.

var root    = postcss.parse('/* Empty file */');
var comment = root.first;
var comment.text //=> 'Empty file'

left and right

Code style properties with spaces before/after comment’s text.

var root  = postcss.parse('/* long */ /*short*/');
var long  = root.first;
var short = root.last;

long.left  //=> ' '
short.left //=> ''

Default value is .

before

Code style property with space symbols before comment.

var root    = postcss.parse('a {\n  /**/}\n');
var comment = root.first.first;
comment.before //=> '\n  '

Default value is \n.