diff --git a/README.md b/README.md index fbb06cad6..61ea41f3b 100644 --- a/README.md +++ b/README.md @@ -261,7 +261,7 @@ Read the [PostCSS API documentation] for more details about the JS API. All PostCSS runners should pass [PostCSS Runner Guidelines]. [PostCSS Runner Guidelines]: https://github.com/postcss/postcss/blob/master/docs/guidelines/runner.md -[PostCSS API documentation]: https://github.com/postcss/postcss/blob/master/docs/api.md +[PostCSS API documentation]: http://api.postcss.org/postcss.html ### Options diff --git a/d.ts/at-rule.d.ts b/d.ts/at-rule.d.ts index 27fb33937..36057053e 100644 --- a/d.ts/at-rule.d.ts +++ b/d.ts/at-rule.d.ts @@ -1,5 +1,5 @@ import Container from './container'; -import postcss from './postcss'; +import * as postcss from './postcss'; export default class AtRule extends Container implements postcss.AtRule { /** * Returns a string representing the node's type. Possible values are diff --git a/d.ts/comment.d.ts b/d.ts/comment.d.ts index 8ab56e699..842c3923a 100644 --- a/d.ts/comment.d.ts +++ b/d.ts/comment.d.ts @@ -1,4 +1,4 @@ -import postcss from './postcss'; +import * as postcss from './postcss'; import Node from './node'; export default class Comment extends Node implements postcss.Comment { /** diff --git a/d.ts/container.d.ts b/d.ts/container.d.ts index 02816a12b..a044590dc 100644 --- a/d.ts/container.d.ts +++ b/d.ts/container.d.ts @@ -1,5 +1,5 @@ import Comment from './comment'; -import postcss from './postcss'; +import * as postcss from './postcss'; import AtRule from './at-rule'; import Node from './node'; import Rule from './rule'; diff --git a/d.ts/css-syntax-error.d.ts b/d.ts/css-syntax-error.d.ts index c5dcd2071..d551381c2 100644 --- a/d.ts/css-syntax-error.d.ts +++ b/d.ts/css-syntax-error.d.ts @@ -1,4 +1,4 @@ -import postcss from './postcss'; +import * as postcss from './postcss'; export default class CssSyntaxError implements postcss.CssSyntaxError, SyntaxError { /** * Contains full error text in the GNU error format. diff --git a/d.ts/declaration.d.ts b/d.ts/declaration.d.ts index ee2fdca2c..ee23a99ae 100644 --- a/d.ts/declaration.d.ts +++ b/d.ts/declaration.d.ts @@ -1,4 +1,4 @@ -import postcss from './postcss'; +import * as postcss from './postcss'; import Node from './node'; export default class Declaration extends Node implements postcss.Declaration { /** diff --git a/d.ts/input.d.ts b/d.ts/input.d.ts index 558a63dbd..414a7b9af 100644 --- a/d.ts/input.d.ts +++ b/d.ts/input.d.ts @@ -1,7 +1,7 @@ import CssSyntaxError from './css-syntax-error'; import PreviousMap from './previous-map'; import LazyResult from './lazy-result'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Result from './result'; export default class Input implements postcss.Input { /** diff --git a/d.ts/lazy-result.d.ts b/d.ts/lazy-result.d.ts index e86bc9f22..de04e5dfd 100644 --- a/d.ts/lazy-result.d.ts +++ b/d.ts/lazy-result.d.ts @@ -1,5 +1,5 @@ import Processor from './processor'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Result from './result'; import Root from './root'; export default class LazyResult implements postcss.LazyResult { diff --git a/d.ts/node.d.ts b/d.ts/node.d.ts index 0dbbe522a..dc35805aa 100644 --- a/d.ts/node.d.ts +++ b/d.ts/node.d.ts @@ -1,6 +1,6 @@ import Container from './container'; import CssSyntaxError from './css-syntax-error'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Result from './result'; export default class Node implements postcss.Node { /** diff --git a/d.ts/parse.d.ts b/d.ts/parse.d.ts index 5afc20d72..897c4fdfa 100644 --- a/d.ts/parse.d.ts +++ b/d.ts/parse.d.ts @@ -1,5 +1,5 @@ import LazyResult from './lazy-result'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Result from './result'; import Root from './root'; /** diff --git a/d.ts/postcss.d.ts b/d.ts/postcss.d.ts index fc9f898d9..5bb043026 100644 --- a/d.ts/postcss.d.ts +++ b/d.ts/postcss.d.ts @@ -1242,4 +1242,4 @@ declare module postcss { interface JsonComment extends JsonNode { } } -export default postcss; +export = postcss; diff --git a/d.ts/processor.d.ts b/d.ts/processor.d.ts index eca72b6b7..a7828206b 100644 --- a/d.ts/processor.d.ts +++ b/d.ts/processor.d.ts @@ -1,5 +1,5 @@ import LazyResult from './lazy-result'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Result from './result'; export default class Processor implements postcss.Processor { /** diff --git a/d.ts/result.d.ts b/d.ts/result.d.ts index be0e38d95..e3ed29156 100644 --- a/d.ts/result.d.ts +++ b/d.ts/result.d.ts @@ -1,5 +1,5 @@ import Processor from './processor'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Root from './root'; export default class Result implements postcss.Result { /** diff --git a/d.ts/root.d.ts b/d.ts/root.d.ts index a11376242..65f6cfbc3 100644 --- a/d.ts/root.d.ts +++ b/d.ts/root.d.ts @@ -1,6 +1,6 @@ import PreviousMap from './previous-map'; import Container from './container'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Result from './result'; import Node from './node'; export default class Root extends Container implements postcss.Root { diff --git a/d.ts/rule.d.ts b/d.ts/rule.d.ts index 1d7377a3a..dbe71940d 100644 --- a/d.ts/rule.d.ts +++ b/d.ts/rule.d.ts @@ -1,5 +1,5 @@ import Container from './container'; -import postcss from './postcss'; +import * as postcss from './postcss'; export default class Rule extends Container implements postcss.Rule { /** * Returns a string representing the node's type. Possible values are diff --git a/d.ts/stringify.d.ts b/d.ts/stringify.d.ts index 1e39b8d82..9caddfde1 100644 --- a/d.ts/stringify.d.ts +++ b/d.ts/stringify.d.ts @@ -1,5 +1,5 @@ import Stringifier from './stringifier'; -import postcss from './postcss'; +import * as postcss from './postcss'; import Node from './node'; /** * Default function to convert a node tree into a CSS string. diff --git a/d.ts/warning.d.ts b/d.ts/warning.d.ts index 4eaceaa20..66f429c10 100644 --- a/d.ts/warning.d.ts +++ b/d.ts/warning.d.ts @@ -1,4 +1,4 @@ -import postcss from './postcss'; +import * as postcss from './postcss'; import Node from './node'; export default class Warning implements postcss.Warning { /** diff --git a/docs/api.md b/docs/api.md index 21784c681..1e176eda8 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,1814 +1,5 @@ -# PostCSS API +# API docs has been moved to [api.postcss.org](http://api.postcss.org/) -* [`postcss` function](#postcss-function) -* [`Processor` class](#processor-class) -* [`LazyResult` class](#lazyresult-class) -* [`Result` class](#result-class) -* [`Warning` class](#warning-class) -* [`CssSyntaxError` class](#csssyntaxerror-class) -* [Vendor module](#vendor-module) -* [List module](#list-module) -* [`Input` class](#input-class) -* [Nodes common methods](#nodes-common-methods) -* [Containers common methods](#containers-common-methods) -* [`Root` node](#root-node) -* [`AtRule` node](#atrule-node) -* [`Rule` node](#rule-node) -* [`Declaration` node](#declaration-node) -* [`Comment` node](#comment-node) +We have found a new home for the PostCSS API documentation that you can find at [api.postcss.org](http://api.postcss.org/). We hope you find it more easy to use and more accessibility friendly. If you find any bugs or have any other thoughts regarding the API documnetation, feel free to submit an [issue](https://github.com/postcss/postcss/issues). -## `postcss` function - -The `postcss` function is the main entry point for PostCSS. - -```js -var postcss = require('postcss'); -``` - -For those using [TypeScript], typings are already provided in this package. -Simply, import PostCSS as you would normally. - -```ts -import * as postcss from 'postcss'; -``` - -[TypeScript]: http://www.typescriptlang.org/ - -### `postcss(plugins)` - -Returns a new [`Processor`] instance that will apply `plugins` -as CSS processors. - -```js -postcss([autoprefixer, cssnext, cssgrace]).process(css).css; -``` - -Arguments: - -* `plugins (array)`: list of PostCSS plugins to be included as processors. - -Plugins can also be included with the [`Processor#use`] method. -See its description 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. - -```js -// 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; -``` - -Arguments: - -* `css (string|#toString)`: String with input CSS or any object - with `toString()` method, like a Buffer. -* `opts (object) optional`: 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. - * `map`: an object of [source map options]. - Only `map.prev` is used in `parse`. - -### `postcss.plugin(name, initializer)` - -Creates a PostCSS plugin with a standard API. - -```js -var remove = postcss.plugin('postcss-remove', function (opts) { - opts = opts || {}; - var filter = opts.prop || 'z-index'; - return function (css, result) { - css.walkDecls(filter, function (decl) { - decl.remove(); - }); - }; -}); - -postcss([ remove ]) // with default options -postcss([ remove({ prop: 'color' })]) // with options -``` - -Arguments: - -* `name (string)`: PostCSS plugin name. Same as in `name` property - in `package.json`. It will be saved in `plugin.postcssPlugin` property. -* `initializer (function)`: will receive plugin options and should return - functions to modify nodes in input CSS. - -The newly-wrapped function will provide both the name and PostCSS -version of the plugin: - -```js -var processor = postcss([replace]); -processor.plugins[0].postcssPlugin //=> 'postcss-replace' -processor.plugins[0].postcssVersion //=> '4.1.0' -``` - -The plugin function receives 2 arguments: [`Root` node] and [`Result`] instance. -The function should mutate the provided `Root` node. Alternatively, you can -create a new `Root` node and override the `result.root` property. - -```js -var cleaner = postcss.plugin('postcss-cleaner', function () { - return function (css, result) { - result.root = postcss.root(); - }; -}); -``` - -As a convenience, plugins also expose a `process` method so that you can use -them as standalone tools. - -```js -cleaner.process(css, options); -// This is equivalent to: -postcss([ cleaner(options) ]).process(css); -``` - -Asynchronous plugins should return a `Promise` instance. - -```js -postcss.plugin('postcss-import', function () { - return function (css, result) { - return new Promise(function (resolve, reject) { - fs.readFile('base.css', function (base) { - css.prepend(base); - resolve(); - }); - }); - }; -}); -``` - -Add warnings using the [`Node#warn()`] method. - -```js -postcss.plugin('postcss-caniuse-test', function () { - return function (css, result) { - css.walkDecls(function (decl) { - if ( !caniuse.support(decl.prop) ) { - decl.warn(result, - 'Some browsers do not support ' + decl.prop); - } - }); - }; -}); -``` - -Send data to other plugins using the [`Result#messages`] array. - -### `postcss.root(props)` - -Creates a new [`Root` node]. - -```js -postcss.root({ after: '\n' }).toString() //=> "\n" -``` - -Arguments: - -* `props (object) optional`: properties for the new root node. - -### `postcss.atRule(props)` - -Creates a new [`AtRule` node]. - -```js -postcss.atRule({ name: 'charset' }).toString() //=> "@charset" -``` - -Arguments: - -* `props (object) optional`: properties for the new at-rule node. - -### `postcss.rule(props)` - -Creates a new [`Rule` node]. - -```js -postcss.rule({ selector: 'a' }).toString() //=> "a {\n}" -``` - -Arguments: - -* `props (object) optional`: properties for the new rule node. - -### `postcss.decl(props)` - -Creates a new [`Declaration` node]. - -```js -postcss.decl({ prop: 'color', value: 'black' }).toString() //=> "color: black" -``` - -Arguments: - -* `props (object) optional`: properties for the new declaration node. - -### `postcss.comment(props)` - -Creates a new [`Comment` node]. - -```js -postcss.comment({ text: 'test' }).toString() //=> "/* test */" -``` - -Arguments: - -* `props (object) optional`: properties for the new comment node. - -### `postcss.vendor` - -Contains the [Vendor module](#vendor-module). - -```js -postcss.vendor.unprefixed('-moz-tab') //=> ['tab'] -``` - -### `postcss.list` - -Contains the [List module](#list-module). - -```js -postcss.list.space('5px calc(10% + 5px)') //=> ['5px', 'calc(10% + 5px)'] -``` - -### `postcss.stringify(node, builder)` - -Default function to convert a node tree into a CSS string. - -## `Processor` class - -A `Processor` instance contains plugins to process CSS. Create -one `Processor` instance, initialize its plugins, and then use that instance -on numerous CSS files. - -```js -var processor = postcss([autoprefixer, cssnext, cssgrace]); -processor.process(css1).css; -processor.process(css2).css; -``` - -### `processor.use(plugin)` - -Adds a plugin to be used as a CSS processor. - -```js -var processor = postcss(); -processor.use(autoprefixer()).use(cssnext()).use(cssgrace()); -``` - -Arguments: - -* `plugin (function|#postcss|Processor)`: PostCSS plugin. It can be in three - formats: - * A plugin created by [`postcss.plugin()`] method. - * A function. PostCSS will pass the function a [`Root` node] - as the first argument and current [`Result`] instance as the second. - * An object with a `postcss` method. PostCSS will use that method - as described in #2. - * Another `Processor` instance. PostCSS will copy plugins - from that instance into this one. - -Plugins can also be added by passing them as arguments when creating -a `postcss` instance (see [`postcss(plugins)`]). - -Asynchronous Plugins should return a `Promise` instance. - -### `processor.process(css, opts)` - -Parses source CSS and returns a [`LazyResult`] instance. Because some plugins -can be asynchronous it doesn’t make any transformations. Transformations will -be applied in the `LazyResult`’s methods. - -```js -processor.process(css, { from: 'a.css', to: 'a.out.css' }).then(function (result) { - console.log(result.css); -}); -``` - -Arguments: - -* `css (string|#toString|Result)`: String with input CSS or any object - with a `toString()` method, like a Buffer. Optionally, send a [`Result`] - instance and the processor will take the existing [`Root`] parser from it. -* `opts (object) optional`: 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. - * `parser`: function to generate AST by string. - * `stringifier`: class to generate string by AST. - * `syntax`: object with `parse` and `stringify` functions. - * `map`: an object of [source map options]. - -### `processor.plugins` - -Contains plugins added to this processor. - -```js -var processor = postcss([cssnext, cssgrace]); -processor.plugins.length //=> 2 -``` - -### `processor.version` - -Contains the current version of PostCSS. - -```js -postcss().version //=> '4.0.5' -``` - -## `LazyResult` class - -A promise proxy for the result of PostCSS transformations. - -A `LazyResult` instance is returned by [`Processor#process(css, opts)`]. - -```js -var lazy = postcss([cssnext]).process(css); -``` - -### `lazy.then(onFulfilled, onRejected)` - -Processes input CSS through synchronous and asynchronous plugins -and calls `onFulfilled` with a [`Result`] instance. If a plugin throws -an error, the `onRejected` callback will be executed. - -```js -postcss([cssnext]).process(css).then(function(result) { - console.log(result.css); -}); -``` - -This method is a standard [Promise] method. - -### `lazy.catch(onRejected)` - -Processes input CSS through synchronous and asynchronous plugins -and calls `onRejected` for each error thrown in any plugin. - -```js -postcss([cssnext]).process(css).then(function(result) { - console.log(result.css); -}).catch(function (error) { - console.error(error); -}); -``` - -This method is a standard [Promise] method. - -### `lazy.toString()` - -Alias for the `LazyResult#css` property. - -### `lazy.css` - -Processes input CSS through synchronous plugins, converts `Root` to a CSS -string and returns [`Result#css`]. - -```js -processor.process(css).css; -``` - -This property will only work with synchronous plugins. If the processor -contains any asynchronous plugins it will throw an error. In this case, -you should use [`LazyResult#then()`] instead. - -```js -postcss([cssnext]).then(function (result) { - console.log(result.css); -}); -``` - -### `lazy.content` - -An alias for the `css` property. Use it with syntaxes that generate non-CSS -output. - -```js -lazy.css === lazy.content; -``` - -### `lazy.map` - -Processes input CSS through synchronous plugins and returns [`Result#map`]. - -```js -if ( result.map ) { - fs.writeFileSync(result.opts.to + '.map', result.map.toString()); -} -``` - -This property will only work with synchronous plugins. If the processor -contains any asynchronous plugins it will throw an error. In this case, -you should use [`LazyResult#then()`] instead. - -```js -postcss([cssnext]).then(function (result) { - if ( result.map ) { - fs.writeFileSync(result.opts.to + '.map', result.map.toString()); - } -}); -``` - -### `lazy.root` - -Processes input CSS through synchronous plugins and returns -[`Result#root`](#resultroot). - -This property will only work with synchronous plugins. If the processor -contains any asynchronous plugins it will throw an error. In this case, -you should use [`LazyResult#then()`] instead. - -```js -postcss([cssnext]).then(function (result) { - console.log(result.root); -}); -``` - -### `lazy.warnings()` - -Processes input CSS through synchronous plugins and calls [`Result#warnings()`]. - -```js -postcss([cssnext]).warnings().forEach(function (message) { - console.warn(message.text); -}); -``` - -This property will only work with synchronous plugins. If the processor -contains any asynchronous plugins it will throw an error. In this case, -you should use [`LazyResult#then()`] instead. - -```js -postcss([cssnext]).then(function (result) { - result.warnings().forEach(function (message) { - console.warn(message.text); - }); -}); -``` - -### `lazy.messages` - -Processes input CSS through synchronous plugins and returns [`Result#messages`]. - -This property will only work with synchronous plugins. If the processor -contains any asynchronous plugins it will throw an error. In this case, -you should use [`LazyResult#then()`] instead. - -### `lazy.processor` - -Returns a [`Processor`] instance, which will be used for CSS transformations. - -```js -var lazy = postcss([cssnext, cssgrace]).process(css); -lazy.processor.plugins.length //=> 2 -``` - -### `lazy.opts` - -Options from the [`Processor#process(css, opts)`] call that produced -this `Result` instance. - -```js -postcss().process(css, opts).opts == opts; -``` - -## `Result` class - -Provides the result of the PostCSS transformations. - -A `Result` instance is returned by [`Root#toResult(opts)`] -or [`LazyResult#then()`] methods. - -```js -postcss([cssnext]).process(css).then(function (result1) { - console.log(result1.css); -}); -var result2 = postcss.parse(css).toResult(); -``` - -### `result.toString()` - -Alias for [`Result#css`] property. - -### `result.warn(text, opts)` - -Creates an instance of [`Warning`] and adds it to [`Result#messages`]. - -```js -var plugin = postcss.plugin('postcss-important', function () { - return function (css, result) { - css.walkDecls(function (decl) { - if ( decl.important ) { - result.warn('Try to avoid !important', { node: decl }); - } - }); - }; -}); - -postcss([plugin]).process(css).then(function (result) { - result.warnings() //=> [{ - // plugin: 'postcss-important-warning', - // text: 'Try to avoid !important' - // node: { type: 'decl', … } - // }] -}); -``` - -Arguments: - -* `text (string)`: warning message. It will be used in the `text` property of - the message object. -* `opts (object) optional`: properties to assign to the message object. - * `node`: CSS node that was the source of the warning. - * `word (string)`: word inside a node’s string that should be highlighted - as the source of the warning. - * `index` (number): index inside a node’s string that should be highlighted - as the source of the warning. - * `plugin`: name of the plugin that created this warning. `Result#warn()` will - automatically fill it with the `plugin.postcssPlugin` value. - -### `result.warnings()` - -Returns warnings from plugins. Filters [`Warning`] instances -from [Result#messages]. - -```js -result.warnings().forEach(function (message) { - console.log(message.toString()); -}); -``` - -### `result.css` - -A CSS string representing this `Result`’s '`Root` instance. - -```js -postcss.parse('a{}').toResult().css //=> "a{}" -``` - -### `result.content` - -An alias for the `css` property. Use it with syntaxes that generate non-CSS -output. - -```js -result.css === result.content; -``` - -### `result.map` - -An instance of the `SourceMapGenerator` class from the [`source-map`] library, -representing changes to the `Result`’s `Root` instance. - -```js -result.map.toJSON() //=> { version: 3, file: 'a.css', sources: ['a.css'], … } -``` - -This property will have a value *only if the user does not want an inline source -map*. By default, PostCSS generates inline source maps, written directly into -the processed CSS. The `map` property will be empty by default. - -An external source map will be generated — and assigned to `map` — -only if the user has set the `map.inline` option to `false`, or if PostCSS -was passed an external input source map. - -```js -if ( result.map ) { - fs.writeFileSync(result.opts.to + '.map', result.map.toString()); -} -``` - -### `result.root` - -Contains the [`Root` node] after all transformations. - -```js -root.toResult().root == root; -``` - -### `result.messages` - -Contains messages from plugins (e.g., warnings or custom messages). - -Each message should have `type` and `plugin` properties. - -```js -postcss.plugin('postcss-min-browser', function () { - return function (css, result) { - var browsers = detectMinBrowsersByCanIUse(css); - result.messages.push({ - type: 'min-browser', - plugin: 'postcss-min-browser', - browsers: browsers - }); - }; -}); -``` - -Add a warning using [`Result#warn()`] and get all warnings -using the [`Result#warnings()`](#resultwarnings) method. - -### `result.processor` - -Returns the [`Processor`] instance used for this transformation. - -```js -result.processor.plugins.forEach(function (plugin) { - if ( plugin.postcssPlugin == 'postcss-bad' ) { - throw 'postcss-good is incompatible with postcss-bad'; - } -}); -``` - -### `result.opts` - -Options from the [`Processor#process(css, opts)`] or [`Root#toResult(opts)`] -call that produced this `Result` instance. - -```js -root.toResult(opts).opts == opts; -``` - -## `Warning` class - -Represents a plugin warning. It can be created using [`Node#warn()`]. - -```js -if ( decl.important ) { - decl.warn(result, 'Try to avoid !important'); -} -``` - -### `warning.toString()` - -Returns a string with the error position and message. - -```js -warning.toString() //=> 'postcss-important:a.css:10:4: Try to avoid !important' -``` - -### `warning.text` - -Contains the warning message. - -```js -warning.text //=> 'Try to avoid !important' -``` - -### `warning.plugin` - -Contains the name of the plugin that created this warning. When you call -[`Node#warn()`] it will fill this property automatically. - -```js -warning.plugin //=> 'postcss-important' -``` - -### `warning.node` - -Contains the CSS node that caused the warning. - -```js -warning.node.toString() //=> 'color: white !important' -``` - -### `warning.line` - -The line in the input file with this warning’s source. - -```js -warning.line //=> 5 -``` - -### `warning.column` - -Column in the input file with this warning’s source. - -```js -warning.column //=> 4 -``` - -## `CssSyntaxError` class - -The CSS parser throws this error for broken CSS. - -```js -postcss.parse('a{') //=> CssSyntaxError -``` - -Custom parsers can throw this error for broken custom syntax -using the [`Node#error()`](#nodeerrormessage) method. - -```js -throw node.error('Unknown variable', { plugin: 'postcss-vars' }); -``` - -### `error.toString()` - -Returns a string with the error position, message and source code of the -broken part. - -```js -error.toString() //=> CssSyntaxError: app.css:1:1: Unclosed block - // a { - // ^ -``` - -### `error.showSourceCode(color)` - -Returns a few lines of CSS source that caused the error. - -```js -error.showSourceCode() //=> - // a { - // bad - // ^ - // } -``` - -Arguments: - -* `color (boolean) optional`: whether arrow will be colored red by terminal - color codes. By default, PostCSS will use `process.stdout.isTTY` and - `process.env.NODE_DISABLE_COLORS`. - -If the CSS has an input source map without `sourceContent`, this method will -return an empty string. - -### `error.message` - -Contains full error text in the GNU error format. - -```js -error.message //=> 'a.css:1:1: Unclosed block' -``` - -### `error.reason` - -Contains only the error description. - -```js -error.reason //=> 'Unclosed block' -``` - -### `error.plugin` - -Contains the PostCSS plugin name if the error didn’t come from the CSS parser. - -```js -error.plugin //=> 'postcss-vars' -``` - -PostCSS will fill it automatically. - -### `error.file` - -Contains the absolute path to the broken file. If you use it, send the `from` -option to the parser. - -```js -error.file //=> 'a.sass' -``` - -PostCSS will use the input source map to detect the original error location. -If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS, -PostCSS will show the original position in the Sass file. - -If you need the position in the PostCSS input (e.g., to debug the previous -compiler), use `error.input.file`. - -```js -error.file //=> 'a.sass' -error.input.file //=> 'a.css' -``` - -### `error.line` - -Contains the source line of the error. - -```js -error.line //=> 2 -``` - -PostCSS will use the input source map to detect the original error location. -If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS, -PostCSS will show the original position in the Sass file. - -If you need the position in the PostCSS input (e.g., to debug the previous -compiler), use `error.input.file`. - -```js -error.line //=> 2 -error.input.line //=> 4 -``` - -### `error.column` - -Contains the source column of the error. - -```js -error.column //=> 1 -``` - -PostCSS will use the input source map to detect the original error location. -If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS, -PostCSS will show the original position in the Sass file. - -If you need the position in the PostCSS input (e.g., to debug the previous -compiler), use `error.input.file`. - -```js -error.column //=> 1 -error.input.column //=> 4 -``` - -### `error.source` - -Contains the source code of the broken file. - -```js -error.source //=> 'a {} b {' -``` - -PostCSS will use the input source map to detect the original error location. -If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS, -PostCSS will show the original position in the Sass file. - -If you need the position in the PostCSS input (e.g., to debug the previous -compiler), use `error.input.file`. - -```js -error.source //=> 'a { b {} }' -error.input.column //=> 'a b { }' -``` - -## Vendor module - -Contains helpers for working with vendor prefixes. - -```js -var vendor = postcss.vendor; -``` - -### `vendor.prefix(string)` - -Returns the vendor prefix extracted from an input string. - -```js -postcss.vendor.prefix('-moz-tab-size') //=> '-moz-' -``` - -### `vendor.unprefixed(string)` - -Returns the input string stripped of its vendor prefix. - -```js -postcss.vendor.unprefixed('-moz-tab-size') //=> 'tab-size' -``` - -## List module - -Contains helpers for safely splitting lists of CSS values, -preserving parentheses and quotes. - -```js -var list = postcss.list; -``` - -### `list.space(string)` - -Safely splits space-separated values (such as those for `background`, -`border-radius`, and other shorthand properties). - -```js -postcss.list.space('1px calc(10% + 1px)') //=> ['1px', 'calc(10% + 1px)'] -``` - -### `list.comma(string)` - -Safely splits comma-separated values (such as those -for `transition-*` and `background` properties). - -```js -postcss.list.comma('black, linear-gradient(white, black)') -//=> ['black', 'linear-gradient(white, black)'] -``` - -## `Input` class - -Represents the source CSS. - -```js -var root = postcss.parse(css, { from: file }); -var input = root.source.input; -``` - -### `input.file` - -The absolute path to the CSS source file defined with the [`from` option]. - -```js -var root = postcss.parse(css, { from: 'a.css' }); -root.source.input.file //=> '/home/ai/a.css' -``` - -### `input.id` - -The unique ID of the CSS source. Used if `from` -option is not provided (because PostCSS does not know the file path). - -```js -var root = postcss.parse(css); -root.source.input.file //=> undefined -root.source.input.id //=> -``` - -### `input.from` - -The CSS source identifier. Contains [`input.file`](#inputfile) if the user set -the [`from` option], or [`input.id`](#inputid) if they did not. - -```js -var root = postcss.parse(css, { from: 'a.css' }); -root.source.input.from //=> '/home/ai/a.css' - -var root = postcss.parse(css); -root.source.input.from //=> -``` - -### `input.map` - -Represents the input source map passed from a compilation step before PostCSS -(e.g., from the Sass compiler). - -`map.consumer()` returns an instance of the `SourceMapConsumer` class -from the [`source-map`] library. - -```js -root.source.input.map.consumer().sources //=> ['a.sass'] -``` - -### `input.origin(line, column)` - -Reads the input source map and returns a symbol position in the input source -(e.g., in a Sass file that was compiled to CSS before being passed -to PostCSS): - -```js -root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 } -``` - -## Nodes: common methods - -All node classes inherit the following common methods. - -### `node.type` - -Returns a string representing the node’s type. - -Possible values are `root`, `atrule`, `rule`, `decl`, or `comment`. - -```js -postcss.decl({ prop: 'color', value: 'black' }).type //=> 'decl' -``` - -### `node.parent` - -Returns the node’s parent node. - -```js -root.nodes[0].parent == root; -``` - -### `node.source` - -Returns the input source of the node, with the following properties: - -- `node.source.input`: An [`Input`] instance. -- `node.source.start`: The starting position of the node’s source — - line and column. -- `node.source.end`: The ending position of the node’s source — line and column. - -```js -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 source map generation. - -If you create a node manually (e.g., with `postcss.decl()`), -that node will not have a `source` property and will be absent -from the source map. For this reason, the plugin developer should consider -cloning nodes to create new ones (in which case the new node’s source -will reference the original, cloned node) or setting the `source` property -manually. - -```js -// Bad -var prefixed = postcss.decl({ prop: '-moz-' + decl.prop, value: decl.value }); - -// Good -var prefixed = decl.clone({ prop: '-moz-' + decl.prop }); -``` - -```js -if ( atrule.name == 'add-link' ) { - var rule = postcss.rule({ selector: 'a' }); // Rule has no source - atrule.parent.insertBefore(atrule, rule); // We add it because of atrule - rule.source = atrule.source; // So we copy source from atrule -} -``` - -### `node.raws` - -Contains information to generate byte-to-byte equal node string -as it was in the origin input. - -Every parser saves its own properties, but the default CSS parser uses: - -* `before`: the space symbols before the node. It also stores `*` and `_` - symbols before the declaration (IE hack). -* `after`: the space symbols after the last child of the node - to the end of the node. -* `between`: the symbols between the property and value for declarations, - selector and `{` for rules, or last parameter and `{` for at-rules. -* `semicolon`: contains `true` if the last child has an (optional) semicolon. -* `afterName`: the space between the at-rule’s name and its parameters. -* `left`: the space symbols between `/*` and the comment’s text. -* `right`: the space symbols between the comment’s text and `*/`. -* `important`: the content of the important statement, - if it is not just `!important`. - -PostCSS cleans selectors, declaration values and at-rule parameters -from comments and extra spaces, but it stores origin content -in `raws` properties. As such, if you don’t change a declaration’s value, -PostCSS will use the raw value with comments. - -### `node.toString()` - -Returns a CSS string representing the node. - -```js -postcss.rule({ selector: 'a' }).toString() //=> 'a {}'' -``` - -Arguments: - -* `stringifier (functions|object) optional`: a syntax to use - in string generation. - -### `node.error(message, opts)` - -Returns a [`CssSyntaxError`] instance containing the original position -of the node in the source, showing line and column numbers and also -a small excerpt to facilitate debugging. - -If present, an input source map will be used to get the original position -of the source, even from a previous compilation step -(e.g., from Sass compilation). - -This method produces very useful error messages. - -```js -if ( !variables[name] ) { - throw decl.error('Unknown variable ' + name, { word: name }); - // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black - // a - // color: $black - // ^ - // background: white -} -``` - -Arguments: - -* `message (string)`: error description. -* `opts (object) optional`: options. - * `plugin (string)`: plugin name that created this error. - PostCSS will set it automatically. - * `word (string)`: a word inside a node’s string that should be highlighted - as the source of the error. - * `index` (number): an index inside a node’s string that should be highlighted - as the source of the error. - -### `node.warn(result, text, opts)` - -This method is provided as a convenience wrapper for [`Result#warn()`]. - -```js -var plugin = postcss.plugin('postcss-deprecated', function () { - return function (css, result) { - css.walkDecls('bad', function (decl) { - decl.warn(result, 'Deprecated property bad'); - }); - }; -}); -``` - -Arguments: - -* `result`: The [`Result`] instance that will receive the warning. -* `text (string)`: warning message. It will be used in the `text` property of - the message object. -* `opts (object) optional`: properties to assign to the message object. - * `word (string)`: word inside a node’s string that should be highlighted - as the source of the warning. - * `index` (number): index inside a node’s string that should be highlighted - as the source of the warning. - * `plugin`: name of the plugin that created this warning. `Result#warn()` will - automatically fill it with the `plugin.postcssPlugin` value. - -Note that `opts.node` is automatically passed to [`Result#warn()`] for you. - -### `node.next()` and `node.prev()` - -Returns the next/previous child of the node’s parent. -Returns `undefined` if the current node is the last/first child. - -```js -var annotation = decl.prev(); -if ( annotation.type == 'comment' ) { - readAnnotation( annotation.text ); -} -``` - -### `node.root()` - -Returns the `Root` instance of the node’s tree. - -```js -root.nodes[0].nodes[0].root() == root -``` - -### `node.remove()` - -Removes the node from its parent and cleans the `parent` properties from the -node and its children. - -```js -if ( decl.prop.match(/^-webkit-/) ) { - decl.remove(); -} -``` - -### `node.replaceWith(...otherNodes)` - -Inserts node(s) before the current node and removes the current node. - -```js -if ( atrule.name == 'mixin' ) { - atrule.replaceWith(mixinRules[atrule.params]); -} -``` - -### `node.clone(props)` - -Returns a clone of the node. - -The resulting cloned node and its (cloned) children will have a clean `parent` -and code style properties. - -```js -var cloned = decl.clone({ prop: '-moz-' + decl.prop }); -cloned.raws.before //=> undefined -cloned.parent //=> undefined -cloned.toString() //=> -moz-transform: scale(0) -``` - -Arguments: - -* `props (object) optional`: new properties to override in the clone. - -### `node.cloneBefore(props)` and `node.cloneAfter(props)` - -Shortcut to clone the node and insert the resulting cloned node before/after -the current node. - -```js -decl.cloneBefore({ prop: '-moz-' + decl.prop }); -``` - -Arguments: - -* `props (object) optional`: new properties to override in the clone. - -### `node.moveTo(newParent)` - -Removes the node from its current parent and inserts it -at the end of `newParent`. - -This will clean the `before` and `after` code style properties from the node -and replace them with the indentation style of `newParent`. It will also clean -the `between` property if `newParent` is in another `Root`. - -```js -atrule.moveTo(atrule.parent.parent); -``` - -Arguments: - -* `newParent: (Container)`: container node where the current node will be moved. - -### `node.moveBefore(otherNode)` and `node.moveAfter(otherNode)` - -Removes the node from its current parent and inserts it into a new parent -before/after `otherNode`. - -This will also clean the node’s code style properties just as it would in -`node.moveTo(newParent)`. - -Arguments: - -* `otherNode (Node)`: node that will be after/before current node after moving. - -### `node.raw(prop, defaultType)` - -Returns a code style property value. If the node is missing the code style -property (because the node was manually built or cloned), PostCSS will try -to autodetect the code style property by looking at other nodes in the tree. - -```js -var root = postcss.parse('a { background: white }'); -root.nodes[0].append({ prop: 'color', value: 'black' }); -root.nodes[0].nodes[1].raws.before //=> ' ' -``` - -Arguments: - -* `prop (string)`: name or code style property. -* `defaultType (string)`: name of default value. It can be easily missed - if the value is the same as `prop`. - -## Containers: common methods - -The `Root`, `AtRule`, and `Rule` container nodes inherit some common methods -to help work with their children. - -Note that all containers can store *any* content. If you write a rule inside -a rule, PostCSS will parse it. - -### `container.nodes` - -An array containing the container’s children. - -```js -var root = postcss.parse('a { color: black }'); -root.nodes.length //=> 1 -root.nodes[0].selector //=> 'a' -root.nodes[0].nodes[0].prop //=> 'color' -``` - -### `container.first` - -The container’s first child. - -```js -rule.first == rules.nodes[0]; -``` - -### `container.last` - -The container’s last child. - -```js -rule.last == rule.nodes[rule.nodes.length - 1]; -``` - -### `container.index(child)` - -Returns a `child`’s index within the container’s `nodes` array. - -```js -rule.index( rule.nodes[2] ) //=> 2 -``` - -Arguments: - -* `child (Node)`: child of the current container. - -### `container.every(callback)` - -Returns `true` if `callback` returns true for all of the container’s children. - -```js -var noPrefixes = rule.every(function (decl) { - return decl.prop[0] != '-'; -}); -``` - -Arguments: - -* `callback (function)`: iterator. Returns true or false. - -### `container.some(callback)` - -Returns `true` if `callback` returns true for (at least) one -of the container’s children. - -```js -var hasPrefix = rule.some(function (decl) { - return decl.prop[0] == '-'; -}); -``` - -Arguments: - -* `callback (function)`: iterator. Returns true or false. - -### `container.each(callback)` - -Iterates through the container’s immediate children, calling `callback` -for each child. - -Returning `false` in the `callback` will break iteration. - -```js -var color; -rule.each(function (decl) { - if ( decl.prop == 'color' ) { - color = decl.value; - return false; - } -}); -``` - -Arguments: - -* `callback (function)`: iterator. Receives each node and its index. - -Unlike the `for {}`-cycle or `Array#forEach()` this iterator is safe -if you are mutating the array of child nodes during iteration. -PostCSS will adjust the current index to match the mutations. - -```js -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 moves the current node - // to the next index -} - -rule.each(function (decl) { - decl.cloneBefore({ prop: '-webkit-' + decl.prop }); - // Will be executed only for color and z-index -}); -``` - -`container.each()` only iterates through the container’s immediate children. -If you need to recursively iterate through all the container’s descendant nodes, -use `container.walk()`. - -### `container.walk(callback)` - -Traverses the container’s descendant nodes, calling `callback` for each node. - -```js -root.walk(function (node) { - // Traverses all descendant nodes. -}); -``` - -Arguments: - -* `callback (function)`: iterator. Receives each node and its index. - -Like `container.each()`, this method is safe to use -if you are mutating arrays during iteration. - -If you only need to iterate through the container’s immediate children, -use `container.each()`. - -### `container.walkDecls([propFilter,] callback)` - -Traverses the container’s descendant nodes, calling `callback` for each -declaration node. - -```js -root.walkDecls(function (decl) { - if ( decl.prop.match(/^-webkit-/) ) { - decl.remove(); - } -}); -``` - -Arguments: - -* `propFilter: (string|RegExp) optional`: string or regular expression - to filter declarations by property name. - * `callback (function)`: iterator. Receives each declaration node and its - index. - -If you pass a `propFilter`, iteration will only happen over declarations with -matching properties. - -```js -// Make a flat design -root.walkDecls('border-radius', function (decl) { - decl.remove(); -}); -root.walkDecls(/^background/, function (decl) { - decl.value = takeFirstColorFromGradient(decl.value); -}); -``` - -Like `container.each()`, this method is safe to use if you are mutating -arrays during iteration. - -### `container.walkAtRules([nameFilter,] callback)` - -Traverses the container’s descendant nodes, calling `callback` for each -at-rule node. - -```js -root.walkAtRules(function (rule) { - if ( rule.name.match(/^-webkit-/) ) rule.remove(); -}); -``` - -Arguments: - -* `nameFilter: (string|RegExp) optional`: string or regular expression to filter - at-rules by name. - * `callback (function)`: iterator. Receives each at-rule and its index. - -If you pass a `filter`, iteration will only happen over at-rules that have -matching names. - -```js -var first = false; -root.walkAtRules('charset', function (rule) { - if ( !first ) { - first = true; - } else { - rule.remove(); - } -}); -``` - -Like `container.each()`, this method is safe to use if you are mutating arrays -during iteration. - -### `container.walkRules([selectorFilter,] callback)` - -Traverses the container’s descendant nodes, calling `callback` for each -rule node. - -```js -var selectors = []; -root.walkRules(function (rule) { - selectors.push(rule.selector); -}); -console.log('Your CSS uses ' + selectors.length + ' selectors'); -``` - -Arguments: - -* `selectorFilter: (string|RegExp) optional`: string or regular expression - to filter rules by selector. -* `callback (function)`: iterator. Receives each rule node and its index. - -If you pass a `selectorFilter`, iteration will only happen over rules with -matching selectors. - -Like `container.each()`, this method is safe to use if you are mutating arrays -during iteration. - -### `container.walkComments(callback)` - -Traverses the container’s descendant nodes, calling `callback` for each -comment node. - -```js -root.walkComments(function (comment) { - comment.remove(); -}); -``` - -Arguments: - -* `callback (function)`: iterator. Receives each comment node and its index. - -Like `container.each()`, this method is safe to use if you are mutating arrays -during iteration. - -### `container.replaceValues(pattern, opts, callback)` - -Passes all declaration values within the container that match `pattern` through -`callback`, replacing those values with the returned result of `callback`. - -This method is useful if you are using a custom unit or function and need -to iterate through all values. - -```js -root.replaceValues(/\d+rem/, { fast: 'rem' }, function (string) { - return 15 * parseInt(string) + 'px'; -}); -``` - -Arguments: - -* `pattern (string|RegExp)`: replace pattern. -* `opts (object) optional`: options to speed up the search: - * `props`: An array of property names. The method will only search for values - that match `regexp` within declarations of listed properties. - * `fast`: A string that’s used to narrow down values and speed up - the regexp search. Searching every single value with a regexp can be slow. - If you pass a `fast` string, PostCSS will first check whether the value - contains the `fast` string; and only if it does will PostCSS check that - value against `regexp`. For example, instead of just checking for `/\d+rem/` - on all values, set `fast: 'rem'` to first check whether a value has - the `rem` unit, and only if it does perform the regexp check. -* `callback (function|string)`: string to replace `pattern` or callback that - returns a new value. The callback will receive the same arguments as those - passed to a function parameter of [`String#replace`]. - -[`String#replace`]: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter) - -### `container.prepend(...nodes)` and `container.append(...nodes)` - -Inserts new nodes to the start/end of the container. - -```js -var decl = postcss.decl({ prop: 'color', value: 'black' }); -rule.append(decl); -``` - -```js -var decl1 = postcss.decl({ prop: 'color', value: 'black' }); -var decl2 = postcss.decl({ prop: 'background-color', value: 'white' }); -rule.prepend(decl1, decl2); -``` - -Arguments: - -* `node (Node|array|object|string)`: new node. - -Because each node class is identifiable by unique properties, use -the following shortcuts to create nodes in insert methods: - -```js -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 -``` - -A string containing the CSS of the new element can also be used. -This approach is slower than the above shortcuts. - -```js -root.append('a {}'); -root.first.append('color: black; z-index: 1'); -``` - -### `container.insertBefore(oldNode, newNode)` and `container.insertAfter(oldNode, newNode)` - -Insert `newNode` before/after `oldNode` within the container. - -```js -rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop })); -``` - -Arguments: - -* `oldNode (Node|number)`: child or child’s index. -* `node (Node|array|object|string)`: new node. - -### `container.removeChild(node)` - -Removes `node` from the container and cleans the `parent` properties from the -node and its children. - -```js -rule.nodes.length //=> 5 -rule.removeChild(decl); -rule.nodes.length //=> 4 -decl.parent //=> undefined -``` - -Arguments: - -* `node (Node|number)`: child or child’s index. - -### `container.removeAll()` - -Removes all children from the container and cleans their `parent` properties. - -```js -rule.removeAll(); -rule.nodes.length //=> 0 -``` - -## `Root` node - -Represents a CSS file and contains all its parsed nodes. - -```js -var root = postcss.parse('a{color:black} b{z-index:2}'); -root.type //=> 'root' -root.nodes.length //=> 2 -``` - -### `root.toResult(opts)` - -Returns a [`Result`] instance representing the root’s CSS. - -```js -var root1 = postcss.parse(css1, { from: 'a.css' }); -var root2 = postcss.parse(css2, { from: 'b.css' }); - -root1.append(root2); -var result = root1.toResult({ to: 'all.css', map: true }); -``` - -Arguments: - -* `opts (object) optional`: options: - * `to`: the path where you’ll put the output CSS file. You should always set - `to` to generate correct source maps. - * `map`: an object of [source map options]. - -## `AtRule` node - -Represents an at-rule. - -If it’s followed in the CSS by a `{}` block, this node will have a `nodes` -property representing its children. - - -```js -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 //=> [] -``` - -### `atrule.name` - -The at-rule’s name. This is the identifier that immediately follows the `@`. - -```js -var root = postcss.parse('@media print {}'); -var media = root.first; -media.name //=> 'media' -``` - -### `atrule.params` - -The at-rule’s parameters. These are the values that follow the at-rule’s name -but precede any `{}` block. The spec refers to this area -as the at-rule’s “prelude”. - -```js -var root = postcss.parse('@media print, screen {}'); -var media = root.first; -media.params //=> 'print, screen' -``` - -## `Rule` node - -Represents a CSS rule: a selector followed by a declaration block. - -```js -var root = postcss.parse('a{}'); -var rule = root.first; -rule.type //=> 'rule' -rule.toString() //=> 'a{}' -``` - -### `rule.selector` - -The rule’s full selector represented as a string. If there are multiple -comma-separated selectors, the entire group will be included. - -```js -var root = postcss.parse('a, b { }'); -var rule = root.first; -rule.selector //=> 'a, b' -``` - -### `rule.selectors` - -An array containing the rule’s individual selectors. -Groups of selectors are split at commas. - -```js -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' -``` - -## `Declaration` node - -Represents a CSS declaration. - -```js -var root = postcss.parse('a { color: black }'); -var decl = root.first.first; -decl.type //=> 'decl' -decl.toString() //=> ' color: black' -``` - -### `declaration.prop` - -The declaration’s property name. - -```js -var root = postcss.parse('a { color: black }'); -var decl = root.first.first; -decl.prop //=> 'color' -``` - -### `declaration.value` - -The declaration’s value. - -```js -var root = postcss.parse('a { color: black }'); -var decl = root.first.first; -decl.value //=> 'black' -``` - -### `declaration.important` - -`true` if the declaration has an `!important` annotation. - -```js -var root = postcss.parse('a { color: black !important; color: white }'); -root.first.first.important //=> true -root.first.last.important //=> undefined -``` - -## `Comment` node - -Represents a comment between declarations or statements (rule and at-rules). -Comments inside selectors, at-rule parameters, or declaration values -will be stored in the [`Node#raws`] properties explained above. - -```js -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 */' -``` - -### `comment.text` - -The comment’s text. - -```js -var root = postcss.parse('/* Empty file */'); -var comment = root.first; -var comment.text //=> 'Empty file' -``` - -[`source-map`]: https://github.com/mozilla/source-map -[Promise]: http://www.html5rocks.com/en/tutorials/es6/promises/ - -[source map options]: https://github.com/postcss/postcss/blob/master/docs/source-maps.md - -[`Processor#process(css, opts)`]: #processorprocesscss-opts -[`Root#toResult(opts)`]: #roottoresultopts -[`LazyResult#then()`]: #lazythenonfulfilled-onrejected -[`postcss(plugins)`]: #postcssplugins -[`postcss.plugin()`]: #postcsspluginname-initializer -[`Declaration` node]: #declaration-node -[`Result#messages`]: #resultmessages -[`CssSyntaxError`]: #csssyntaxerror-class -[`Processor#use`]: #processoruseplugin -[`Result#warn()`]: #resultwarntext-opts -[`Node#warn()`]: #nodewarnresult-message -[`Comment` node]: #comment-node -[`AtRule` node]: #atrule-node -[`from` option]: #processorprocesscss-opts -[`LazyResult`]: #lazyresult-class -[`Result#map`]: #resultmap -[`Result#css`]: #resultcss -[`Root` node]: #root-node -[`Rule` node]: #rule-node -[`Processor`]: #processor-class -[`Node#raws`]: #noderaws -[`Warning`]: #warning-class -[`Result`]: #result-class -[`Input`]: #inputclass +Thank you, diff --git a/docs/guidelines/plugin.md b/docs/guidelines/plugin.md index bde046cea..978a62404 100644 --- a/docs/guidelines/plugin.md +++ b/docs/guidelines/plugin.md @@ -123,7 +123,7 @@ PostCSS plugins must not rely on undocumented properties or methods, which may be subject to change in any minor release. The public API is described in [API docs]. -[API docs]: https://github.com/postcss/postcss/blob/master/docs/api.md +[API docs]: http://api.postcss.org/ ## 3. Errors diff --git a/docs/guidelines/runner.md b/docs/guidelines/runner.md index 872b5564a..83f208739 100644 --- a/docs/guidelines/runner.md +++ b/docs/guidelines/runner.md @@ -64,7 +64,7 @@ PostCSS runners must not rely on undocumented properties or methods, which may be subject to change in any minor release. The public API is described in [API docs]. -[API docs]: https://github.com/postcss/postcss/blob/master/docs/api.md +[API docs]: http://api.postcss.org/ ## 3. Output diff --git a/docs/plugins.md b/docs/plugins.md index 0ca861280..be56867af 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -319,9 +319,10 @@ See also plugins in modular minifier [`cssnano`]. ## Others +* [`postcss-attribute-selector-prefix`] adds a prefix to attribute selectors * [`postcss-autoreset`] automatically adds reset styles. +* [`postcss-camelcaser`] transforms selectors to camelcase. * [`postcss-class-prefix`] adds a prefix/namespace to class selectors. -* [`postcss-attribute-selector-prefix`] adds a prefix to attribute selectors * [`postcss-currency`] replaces name of currency with symbols. * [`postcss-extract-value`] extracts values from css properties and puts them into variables. * [`postcss-fakeid`] transforms `#foo` IDs to attribute selectors `[id="foo"]`. @@ -331,31 +332,32 @@ See also plugins in modular minifier [`cssnano`]. * [`postcss-flexboxfixer`] unprefixes `-webkit-` only flexbox in legacy CSS. * [`postcss-flexbugs-fixes`] fixes some of known [flexbox bugs]. * [`postcss-gradientfixer`] unprefixes `-webkit-` only gradients in legacy CSS. +* [`postcss-ie8`] strips out unsupported properties and mediaqueries for IE8. * [`postcss-increase-specificity`] increases the specificity of your selectors. +* * [`postcss-inline-rtl`] converts your CSS to right-to-left, + but inline (adding just what you need). * [`postcss-modules`] allows to use CSS Modules everywhere. * [`postcss-mq-keyframes`] moves any animation keyframes in media queries to the end of the file. -* [`postcss-pseudo-elements-content`] adds `content: ''` to `:before-c` - and `:after-c`. * [`postcss-pseudo-content-insert`] adds `content: ''` to `:before` and `:after` if it is missing. +* [`postcss-pseudo-elements-content`] adds `content: ''` to `:before-c` + and `:after-c`. * [`postcss-pxtorem`] converts pixel units to `rem`. +* [`postcss-raw`] protects nodes inside `@raw` at-rules from being touched + by other plugins. +* [`postcss-remove-prefixes`] removes vendor prefixes. * [`postcss-safe-important`] adds `!important` to style declarations safely. * [`postcss-sanitize`] remove properties and values using rules (css sanitization). +* [`postcss-scopify`] adds a user input scope to each selector. * [`postcss-select`] select rules based off a selector list. * [`postcss-selector-prefixer`] adds a prefix to css selectors. * [`postcss-shorthand-expand`] expands shorthand properties. * [`postcss-sorting`] sort rules content with specified order. -* [`postcss-raw`] protects nodes inside `@raw` at-rules from being touched - by other plugins. -* [`postcss-remove-prefixes`] removes vendor prefixes. * [`postcss-style-guide`] generates a style guide automatically. -* [`postcss-scopify`] adds a user input scope to each selector. * [`css-declaration-sorter`] sorts CSS declarations fast and automatically in a certain order. * [`perfectionist`] formats poorly written CSS and renders a “pretty” result. -* [`postcss-inline-rtl`] converts your CSS to right-to-left, - but inline (adding just what you need). * [`rtlcss`] mirrors styles for right-to-left locales. * [`stylefmt`] modern CSS formatter that works well with `stylelint`. @@ -401,245 +403,247 @@ See also plugins in modular minifier [`cssnano`]. * [`postcss-spanish-stylesheets`] Spanish Style Sheets. [`postcss-combine-duplicated-selectors`]: https://github.com/ChristianMurphy/postcss-combine-duplicated-selectors -[`postcss-gradient-transparency-fix`]: https://github.com/gilmoreorless/postcss-gradient-transparency-fix -[`postcss-attribute-selector-prefix`]: https://github.com/GitScrum/postcss-attribute-selector-prefix -[`postcss-vertical-rhythm-function`]: https://github.com/F21/postcss-vertical-rhythm-function -[`postcss-pseudo-class-any-button`]: https://github.com/andrepolischuk/postcss-pseudo-class-any-button -[`postcss-pseudo-elements-content`]: https://github.com/omgovich/postcss-pseudo-elements-content -[`postcss-australian-stylesheets`]: https://github.com/dp-lewis/postcss-australian-stylesheets -[`postcss-andalusian-stylesheets`]: https://github.com/bameda/postcss-andalusian-stylesheets -[`postcss-pseudo-class-any-link`]: https://github.com/jonathantneal/postcss-pseudo-class-any-link -[`postcss-pseudo-content-insert`]: https://github.com/liquidlight/postcss-pseudo-content-insert -[`postcss-canadian-stylesheets`]: https://github.com/chancancode/postcss-canadian-stylesheets -[`postcss-chinese-stylesheets`]: https://github.com/zhouwenbin/postcss-chinese-stylesheets -[`postcss-czech-stylesheets`]: https://github.com/HoBi/postcss-czech-stylesheets -[`postcss-increase-specificity`]: https://github.com/MadLittleMods/postcss-increase-specificity -[`postcss-swedish-stylesheets`]: https://github.com/johnie/postcss-swedish-stylesheets -[`postcss-russian-stylesheets`]: https://github.com/Semigradsky/postcss-russian-stylesheets -[`postcss-color-rebeccapurple`]: https://github.com/postcss/postcss-color-rebeccapurple -[`postcss-color-rgba-fallback`]: https://github.com/postcss/postcss-color-rgba-fallback -[`postcss-spanish-stylesheets`]: https://github.com/ismamz/postcss-spanish-stylesheets -[`postcss-lolcat-stylesheets`]: https://github.com/sandralundgren/postcss-lolcat-stylesheets -[`postcss-german-stylesheets`]: https://github.com/timche/postcss-german-stylesheets -[`postcss-discard-duplicates`]: https://github.com/ben-eb/postcss-discard-duplicates -[`postcss-minify-font-weight`]: https://github.com/ben-eb/postcss-minify-font-weight -[`postcss-pseudo-class-enter`]: https://github.com/jonathantneal/postcss-pseudo-class-enter -[`postcss-transform-shortcut`]: https://github.com/jonathantneal/postcss-transform-shortcut -[`postcss-at-rules-variables`]: https://github.com/GitScrum/postcss-at-rules-variables -[`postcss-logical-properties`]: https://github.com/ahmadalfy/postcss-logical-properties -[`postcss-responsive-images`]: https://github.com/azat-io/postcss-responsive-images -[`postcss-tatar-stylesheets`]: https://github.com/azat-io/postcss-tatar-stylesheets -[`postcss-custom-properties`]: https://github.com/postcss/postcss-custom-properties -[`postcss-discard-font-face`]: https://github.com/ben-eb/postcss-discard-font-face -[`postcss-selector-prefixer`]: https://github.com/ronnyamarante/postcss-selector-prefixer -[`postcss-custom-selectors`]: https://github.com/postcss/postcss-custom-selectors -[`postcss-discard-comments`]: https://github.com/ben-eb/postcss-discard-comments -[`postcss-minify-selectors`]: https://github.com/ben-eb/postcss-minify-selectors -[`postcss-mqwidth-to-class`]: https://github.com/notacouch/postcss-mqwidth-to-class -[`postcss-quantity-queries`]: https://github.com/pascalduez/postcss-quantity-queries -[`postcss-browser-reporter`]: https://github.com/postcss/postcss-browser-reporter -[`postcss-selector-matches`]: https://github.com/postcss/postcss-selector-matches -[`postcss-shorthand-expand`]: https://github.com/johnotander/postcss-shorthand-expand -[`postcss-current-selector`]: https://github.com/komlev/postcss-current-selector -[`postcss-all-link-colors`]: https://github.com/jedmao/postcss-all-link-colors -[`postcss-color-hex-alpha`]: https://github.com/postcss/postcss-color-hex-alpha -[`postcss-define-property`]: https://github.com/daleeidd/postcss-define-property -[`postcss-filter-gradient`]: https://github.com/yuezk/postcss-filter-gradient -[`postcss-generate-preset`]: https://github.com/simonsmith/postcss-generate-preset -[`postcss-media-variables`]: https://github.com/WolfgangKluge/postcss-media-variables -[`postcss-property-lookup`]: https://github.com/simonsmith/postcss-property-lookup -[`postcss-vertical-rhythm`]: https://github.com/markgoodyear/postcss-vertical-rhythm -[`postcss-local-constants`]: https://github.com/macropodhq/postcss-constants -[`postcss-remove-prefixes`]: https://github.com/johnotander/postcss-remove-prefixes -[`postcss-responsive-type`]: https://github.com/seaneking/postcss-responsive-type -[`postcss-round-subpixels`]: https://github.com/himynameisdave/postcss-round-subpixels -[`postcss-short-font-size`]: https://github.com/jonathantneal/postcss-short-font-size -[`postcss-color-function`]: https://github.com/postcss/postcss-color-function -[`postcss-conic-gradient`]: https://github.com/jonathantneal/postcss-conic-gradient -[`postcss-convert-values`]: https://github.com/ben-eb/postcss-convert-values -[`postcss-partial-import`]: https://github.com/jonathantneal/postcss-partial-import -[`postcss-pseudoelements`]: https://github.com/axa-ch/postcss-pseudoelements -[`postcss-safe-important`]: https://github.com/Crimx/postcss-safe-important -[`postcss-short-position`]: https://github.com/jonathantneal/postcss-short-position -[`postcss-single-charset`]: https://github.com/hail2u/postcss-single-charset -[`postcss-flexbugs-fixes`]: https://github.com/luisrudge/postcss-flexbugs-fixes -[`postcss-shades-of-gray`]: https://github.com/laureanoarcanio/postcss-shades-of-gray -[`postcss-hash-classname`]: https://github.com/ctxhou/postcss-hash-classname -[`postcss-oldschool-grid`]: https://github.com/lordgiotto/postcss-oldschool-grid -[`postcss-alias-atrules`]: https://github.com/maximkoretskiy/postcss-alias-atrules -[`postcss-color-palette`]: https://github.com/zaim/postcss-color-palette -[`postcss-assets-rebase`]: https://github.com/devex-web-frontend/postcss-assets-rebase -[`postcss-color-pantone`]: https://github.com/longdog/postcss-color-pantone -[`postcss-css-variables`]: https://github.com/MadLittleMods/postcss-css-variables -[`postcss-discard-empty`]: https://github.com/ben-eb/postcss-discard-empty -[`postcss-gradientfixer`]: https://github.com/hallvors/postcss-gradientfixer -[`postcss-modular-scale`]: https://github.com/kristoferjoseph/postcss-modular-scale -[`postcss-normalize-url`]: https://github.com/ben-eb/postcss-normalize-url -[`postcss-reduce-idents`]: https://github.com/ben-eb/postcss-reduce-idents -[`postcss-short-spacing`]: https://github.com/jonathantneal/postcss-short-spacing -[`postcss-simple-extend`]: https://github.com/davidtheclark/postcss-simple-extend -[`postcss-russian-units`]: https://github.com/Semigradsky/postcss-russian-units -[`postcss-image-inliner`]: https://github.com/bezoerb/postcss-image-inliner -[`postcss-reverse-media`]: https://github.com/MadLittleMods/postcss-reverse-media -[`postcss-regexp-detect`]: https://github.com/devex-web-frontend/postcss-regexp-detect -[`postcss-speech-bubble`]: https://github.com/archana-s/postcss-speech-bubble -[`postcss-extract-value`]: https://github.com/lutien/postcss-extract-value -[`postcss-mq-keyframes`]: https://github.com/TCotton/postcss-mq-keyframes -[`postcss-brand-colors`]: https://github.com/postcss/postcss-brand-colors -[`postcss-class-prefix`]: https://github.com/thompsongl/postcss-class-prefix -[`postcss-conditionals`]: https://github.com/andyjansson/postcss-conditionals -[`postcss-sassy-mixins`]: https://github.com/andyjansson/postcss-sassy-mixins -[`postcss-custom-media`]: https://github.com/postcss/postcss-custom-media -[`postcss-default-unit`]: https://github.com/antyakushev/postcss-default-unit -[`postcss-font-awesome`]: https://github.com/dan-gamble/postcss-font-awesome -[`postcss-flexibility`]: https://github.com/7rulnik/postcss-flexibility -[`postcss-flexboxfixer`]: https://github.com/hallvors/postcss-flexboxfixer -[`postcss-font-normalize`]: https://github.com/iahu/postcss-font-normalize -[`postcss-font-variant`]: https://github.com/postcss/postcss-font-variant -[`postcss-media-minmax`]: https://github.com/postcss/postcss-media-minmax -[`postcss-merge-idents`]: https://github.com/ben-eb/postcss-merge-idents -[`postcss-selector-not`]: https://github.com/postcss/postcss-selector-not -[`postcss-svg-fallback`]: https://github.com/justim/postcss-svg-fallback -[`postcss-nested-props`]: https://github.com/jedmao/postcss-nested-props -[`postcss-aspect-ratio`]: https://github.com/arccoza/postcss-aspect-ratio -[`postcss-cachebuster`]: https://github.com/glebmachine/postcss-cachebuster -[`postcss-easysprites`]: https://github.com/glebmachine/postcss-easysprites -[`postcss-nested-vars`]: https://github.com/jedmao/postcss-nested-vars -[`postcss-color-alpha`]: https://github.com/avanes/postcss-color-alpha -[`postcss-color-scale`]: https://github.com/kristoferjoseph/postcss-color-scale -[`postcss-color-short`]: https://github.com/andrepolischuk/postcss-color-short -[`postcss-copy-assets`]: https://github.com/shutterstock/postcss-copy-assets -[`postcss-data-packer`]: https://github.com/Ser-Gen/postcss-data-packer -[`postcss-font-family`]: https://github.com/ben-eb/postcss-font-family -[`postcss-simple-grid`]: https://github.com/admdh/postcss-simple-grid -[`postcss-merge-rules`]: https://github.com/ben-eb/postcss-merge-rules -[`postcss-simple-vars`]: https://github.com/postcss/postcss-simple-vars -[`postcss-strip-units`]: https://github.com/whitneyit/postcss-strip-units -[`postcss-style-guide`]: https://github.com/morishitter/postcss-style-guide -[`postcss-will-change`]: https://github.com/postcss/postcss-will-change -[`postcss-input-style`]: https://github.com/seaneking/postcss-input-style -[`css-declaration-sorter`]: https://github.com/Siilwyn/css-declaration-sorter -[`postcss-remove-root`]: https://github.com/cbracco/postcss-remove-root -[`postcss-mq-optimize`]: https://github.com/panec/postcss-mq-optimize -[`postcss-ase-colors`]: https://github.com/dfernandez79/postcss-ase-colors -[`postcss-bem-linter`]: https://github.com/postcss/postcss-bem-linter -[`postcss-color-gray`]: https://github.com/postcss/postcss-color-gray -[`postcss-colorblind`]: https://github.com/btholt/postcss-colorblind -[`postcss-inline-rtl`]: https://github.com/jakob101/postcss-inline-rtl -[`postcss-color-hexa`]: https://github.com/nicksheffield/postcss-color-hexa -[`postcss-short-text`]: https://github.com/jonathantneal/postcss-short-text -[`postcss-inline-svg`]: https://github.com/TrySound/postcss-inline-svg -[`postcss-autoreset`]: https://github.com/maximkoretskiy/postcss-autoreset -[`postcss-font-pack`]: https://github.com/jedmao/postcss-font-pack -[`postcss-reference`]: https://github.com/dehuszar/postcss-reference -[`postcss-functions`]: https://github.com/andyjansson/postcss-functions -[`postcss-color-hcl`]: https://github.com/devgru/postcss-color-hcl -[`postcss-color-hwb`]: https://github.com/postcss/postcss-color-hwb -[`postcss-color-mix`]: https://github.com/iamstarkov/postcss-color-mix -[`postcss-color-yiq`]: https://github.com/ben-eb/postcss-color-yiq -[`postcss-filter-mq`]: https://github.com/simeydotme/postcss-filter-mq -[`postcss-image-set`]: https://github.com/alex499/postcss-image-set -[`postcss-write-svg`]: https://github.com/jonathantneal/postcss-write-svg -[`postcss-animation`]: https://github.com/zhouwenbin/postcss-animation -[`postcss-instagram`]: https://github.com/azat-io/postcss-instagram -[`postcss-namespace`]: https://github.com/totora0155/postcss-namespace -[`postcss-clearfix`]: https://github.com/seaneking/postcss-clearfix -[`postcss-colormin`]: https://github.com/ben-eb/colormin -[`postcss-cssstats`]: https://github.com/cssstats/postcss-cssstats -[`postcss-currency`]: https://github.com/talgautb/postcss-currency -[`postcss-fallback`]: https://github.com/MadLittleMods/postcss-fallback -[`postcss-imperial`]: https://github.com/cbas/postcss-imperial -[`postcss-position`]: https://github.com/seaneking/postcss-position -[`postcss-rgba-hex`]: https://github.com/XOP/postcss-rgba-hex -[`postcss-contrast`]: https://github.com/stephenway/postcss-contrast -[`postcss-spiffing`]: https://github.com/HashanP/postcss-spiffing -[`postcss-triangle`]: https://github.com/jedmao/postcss-triangle -[`postcss-verthorz`]: https://github.com/davidhemphill/postcss-verthorz -[`pleeease-filters`]: https://github.com/iamvdo/pleeease-filters -[`postcss-fontpath`]: https://github.com/seaneking/postcss-fontpath -[`postcss-reporter`]: https://github.com/postcss/postcss-reporter -[`postcss-trolling`]: https://github.com/juanfran/postcss-trolling -[`postcss-if-media`]: https://github.com/arccoza/postcss-if-media -[`postcss-flexbox`]: https://github.com/archana-s/postcss-flexbox -[`postcss-modules`]: https://github.com/outpunk/postcss-modules -[`postcss-easings`]: https://github.com/postcss/postcss-easings -[`postcss-hexrgba`]: https://github.com/seaneking/postcss-hexrgba -[`postcss-initial`]: https://github.com/maximkoretskiy/postcss-initial -[`postcss-rgb-plz`]: https://github.com/himynameisdave/postcss-rgb-plz -[`postcss-opacity`]: https://github.com/iamvdo/postcss-opacity -[`postcss-pointer`]: https://github.com/markgoodyear/postcss-pointer -[`postcss-pxtorem`]: https://github.com/cuth/postcss-pxtorem -[`postcss-scopify`]: https://github.com/pazams/postcss-scopify -[`postcss-sprites`]: https://github.com/2createStudio/postcss-sprites -[`postcss-sorting`]: https://github.com/hudochenkov/postcss-sorting -[`postcss-assets`]: https://github.com/borodean/postcss-assets -[`postcss-border`]: https://github.com/andrepolischuk/postcss-border -[`postcss-center`]: https://github.com/jedmao/postcss-center -[`postcss-circle`]: https://github.com/jedmao/postcss-circle -[`postcss-hidden`]: https://github.com/lukelarsen/postcss-hidden -[`postcss-urlrev`]: https://github.com/yuezk/postcss-urlrev -[`postcss-extend`]: https://github.com/travco/postcss-extend -[`postcss-fakeid`]: https://github.com/pathsofdesign/postcss-fakeid -[`postcss-filter-stream`]: https://github.com/tsm91/postcss-filter-stream -[`postcss-filter`]: https://github.com/alanev/postcss-filter -[`postcss-import`]: https://github.com/postcss/postcss-import -[`postcss-mixins`]: https://github.com/postcss/postcss-mixins -[`postcss-nested`]: https://github.com/postcss/postcss-nested -[`postcss-select`]: https://github.com/johnotander/postcss-select -[`postcss-zindex`]: https://github.com/ben-eb/postcss-zindex -[`list-selectors`]: https://github.com/davidtheclark/list-selectors -[`mq4-hover-shim`]: https://github.com/twbs/mq4-hover-shim -[`postcss-atroot`]: https://github.com/OEvgeny/postcss-atroot -[`postcss-layout`]: https://github.com/arccoza/postcss-layout -[`postcss-esplit`]: https://github.com/vitaliyr/postcss-esplit -[`postcss-focus`]: https://github.com/postcss/postcss-focus -[`postcss-apply`]: https://github.com/pascalduez/postcss-apply -[`css2modernizr`]: https://github.com/vovanbo/css2modernizr -[`font-magician`]: https://github.com/jonathantneal/postcss-font-magician -[`postcss-match`]: https://github.com/rtsao/postcss-match -[`postcss-alias`]: https://github.com/seaneking/postcss-alias -[`postcss-scrib`]: https://github.com/sneakertack/postcss-scrib -[`perfectionist`]: https://github.com/ben-eb/perfectionist -[`immutable-css`]: https://github.com/johnotander/immutable-css -[`postcss-at2x`]: https://github.com/simonsmith/postcss-at2x -[`postcss-calc`]: https://github.com/postcss/postcss-calc -[`postcss-crip`]: https://github.com/johnie/postcss-crip -[`postcss-each`]: https://github.com/outpunk/postcss-each -[`postcss-epub`]: https://github.com/Rycochet/postcss-epub -[`postcss-grid`]: https://github.com/andyjansson/postcss-grid -[`postcss-host`]: https://github.com/vitkarpov/postcss-host -[`postcss-neat`]: https://github.com/jo-asakura/postcss-neat -[`postcss-size`]: https://github.com/postcss/postcss-size -[`postcss-svgo`]: https://github.com/ben-eb/postcss-svgo -[`postcss-unmq`]: https://github.com/jonathantneal/postcss-unmq -[`postcss-vmin`]: https://github.com/iamvdo/postcss-vmin -[`autoprefixer`]: https://github.com/postcss/autoprefixer -[`css-mqpacker`]: https://github.com/hail2u/node-css-mqpacker -[`postcss-bem`]: https://github.com/ileri/postcss-bem -[`postcss-for`]: https://github.com/antyakushev/postcss-for -[`postcss-map`]: https://github.com/pascalduez/postcss-map -[`postcss-raw`]: https://github.com/MadLittleMods/postcss-raw -[`postcss-svg`]: https://github.com/Pavliko/postcss-svg -[`postcss-url`]: https://github.com/postcss/postcss-url -[`colorguard`]: https://github.com/SlexAxton/css-colorguard -[`stylehacks`]: https://github.com/ben-eb/stylehacks -[`css-byebye`]: https://github.com/AoDev/css-byebye -[`cssgrace`]: https://github.com/cssdream/cssgrace -[`csstyle`]: https://github.com/geddski/csstyle -[`webpcss`]: https://github.com/lexich/webpcss -[`stylefmt`]: https://github.com/morishitter/stylefmt -[`doiuse`]: https://github.com/anandthakker/doiuse -[`pixrem`]: https://github.com/robwierzbowski/node-pixrem -[`rtlcss`]: https://github.com/MohammadYounes/rtlcss -[`short`]: https://github.com/jonathantneal/postcss-short -[`lost`]: https://github.com/corysimmons/lost -[`postcss-maze`]: https://github.com/cathydutton/postcss-maze -[`postcss-get-color`]: https://github.com/ismamz/postcss-get-color -[`postcss-sanitize`]: https://github.com/eramdam/postcss-sanitize -[`postcss-magic-animations`]: https://github.com/nucliweb/postcss-magic-animations/ -[`postcss-border-shortcut`]: https://github.com/michelemazzucco/postcss-border-shortcut -[`postcss-button`]: https://github.com/francoisromain/postcss-button -[`postcss-typescale`]: https://github.com/francoisromain/postcss-typescale -[`postcss-grid-fluid`]: https://github.com/francoisromain/postcss-grid-fluid -[`postcss-grid-system`]: https://github.com/francoisromain/postcss-grid-system -[`postcss-placehold`]: https://github.com/awayken/postcss-placehold +[`postcss-attribute-selector-prefix`]: https://github.com/GitScrum/postcss-attribute-selector-prefix +[`postcss-gradient-transparency-fix`]: https://github.com/gilmoreorless/postcss-gradient-transparency-fix +[`postcss-vertical-rhythm-function`]: https://github.com/F21/postcss-vertical-rhythm-function +[`postcss-pseudo-class-any-button`]: https://github.com/andrepolischuk/postcss-pseudo-class-any-button +[`postcss-pseudo-elements-content`]: https://github.com/omgovich/postcss-pseudo-elements-content +[`postcss-andalusian-stylesheets`]: https://github.com/bameda/postcss-andalusian-stylesheets +[`postcss-australian-stylesheets`]: https://github.com/dp-lewis/postcss-australian-stylesheets +[`postcss-pseudo-class-any-link`]: https://github.com/jonathantneal/postcss-pseudo-class-any-link +[`postcss-pseudo-content-insert`]: https://github.com/liquidlight/postcss-pseudo-content-insert +[`postcss-canadian-stylesheets`]: https://github.com/chancancode/postcss-canadian-stylesheets +[`postcss-increase-specificity`]: https://github.com/MadLittleMods/postcss-increase-specificity +[`postcss-chinese-stylesheets`]: https://github.com/zhouwenbin/postcss-chinese-stylesheets +[`postcss-russian-stylesheets`]: https://github.com/Semigradsky/postcss-russian-stylesheets +[`postcss-swedish-stylesheets`]: https://github.com/johnie/postcss-swedish-stylesheets +[`postcss-color-rebeccapurple`]: https://github.com/postcss/postcss-color-rebeccapurple +[`postcss-color-rgba-fallback`]: https://github.com/postcss/postcss-color-rgba-fallback +[`postcss-spanish-stylesheets`]: https://github.com/ismamz/postcss-spanish-stylesheets +[`postcss-at-rules-variables`]: https://github.com/GitScrum/postcss-at-rules-variables +[`postcss-discard-duplicates`]: https://github.com/ben-eb/postcss-discard-duplicates +[`postcss-german-stylesheets`]: https://github.com/timche/postcss-german-stylesheets +[`postcss-logical-properties`]: https://github.com/ahmadalfy/postcss-logical-properties +[`postcss-lolcat-stylesheets`]: https://github.com/sandralundgren/postcss-lolcat-stylesheets +[`postcss-minify-font-weight`]: https://github.com/ben-eb/postcss-minify-font-weight +[`postcss-pseudo-class-enter`]: https://github.com/jonathantneal/postcss-pseudo-class-enter +[`postcss-transform-shortcut`]: https://github.com/jonathantneal/postcss-transform-shortcut +[`postcss-custom-properties`]: https://github.com/postcss/postcss-custom-properties +[`postcss-czech-stylesheets`]: https://github.com/HoBi/postcss-czech-stylesheets +[`postcss-discard-font-face`]: https://github.com/ben-eb/postcss-discard-font-face +[`postcss-responsive-images`]: https://github.com/azat-io/postcss-responsive-images +[`postcss-selector-prefixer`]: https://github.com/ronnyamarante/postcss-selector-prefixer +[`postcss-tatar-stylesheets`]: https://github.com/azat-io/postcss-tatar-stylesheets +[`postcss-browser-reporter`]: https://github.com/postcss/postcss-browser-reporter +[`postcss-current-selector`]: https://github.com/komlev/postcss-current-selector +[`postcss-custom-selectors`]: https://github.com/postcss/postcss-custom-selectors +[`postcss-discard-comments`]: https://github.com/ben-eb/postcss-discard-comments +[`postcss-magic-animations`]: https://github.com/nucliweb/postcss-magic-animations/ +[`postcss-minify-selectors`]: https://github.com/ben-eb/postcss-minify-selectors +[`postcss-mqwidth-to-class`]: https://github.com/notacouch/postcss-mqwidth-to-class +[`postcss-quantity-queries`]: https://github.com/pascalduez/postcss-quantity-queries +[`postcss-selector-matches`]: https://github.com/postcss/postcss-selector-matches +[`postcss-shorthand-expand`]: https://github.com/johnotander/postcss-shorthand-expand +[`postcss-all-link-colors`]: https://github.com/jedmao/postcss-all-link-colors +[`postcss-border-shortcut`]: https://github.com/michelemazzucco/postcss-border-shortcut +[`postcss-color-hex-alpha`]: https://github.com/postcss/postcss-color-hex-alpha +[`postcss-define-property`]: https://github.com/daleeidd/postcss-define-property +[`postcss-filter-gradient`]: https://github.com/yuezk/postcss-filter-gradient +[`postcss-generate-preset`]: https://github.com/simonsmith/postcss-generate-preset +[`postcss-local-constants`]: https://github.com/macropodhq/postcss-constants +[`postcss-media-variables`]: https://github.com/WolfgangKluge/postcss-media-variables +[`postcss-property-lookup`]: https://github.com/simonsmith/postcss-property-lookup +[`postcss-remove-prefixes`]: https://github.com/johnotander/postcss-remove-prefixes +[`postcss-responsive-type`]: https://github.com/seaneking/postcss-responsive-type +[`postcss-round-subpixels`]: https://github.com/himynameisdave/postcss-round-subpixels +[`postcss-short-font-size`]: https://github.com/jonathantneal/postcss-short-font-size +[`postcss-vertical-rhythm`]: https://github.com/markgoodyear/postcss-vertical-rhythm +[`postcss-color-function`]: https://github.com/postcss/postcss-color-function +[`postcss-conic-gradient`]: https://github.com/jonathantneal/postcss-conic-gradient +[`postcss-convert-values`]: https://github.com/ben-eb/postcss-convert-values +[`postcss-flexbugs-fixes`]: https://github.com/luisrudge/postcss-flexbugs-fixes +[`postcss-font-normalize`]: https://github.com/iahu/postcss-font-normalize +[`postcss-hash-classname`]: https://github.com/ctxhou/postcss-hash-classname +[`postcss-oldschool-grid`]: https://github.com/lordgiotto/postcss-oldschool-grid +[`postcss-partial-import`]: https://github.com/jonathantneal/postcss-partial-import +[`postcss-pseudoelements`]: https://github.com/axa-ch/postcss-pseudoelements +[`postcss-safe-important`]: https://github.com/Crimx/postcss-safe-important +[`postcss-shades-of-gray`]: https://github.com/laureanoarcanio/postcss-shades-of-gray +[`postcss-short-position`]: https://github.com/jonathantneal/postcss-short-position +[`postcss-single-charset`]: https://github.com/hail2u/postcss-single-charset +[`css-declaration-sorter`]: https://github.com/Siilwyn/css-declaration-sorter +[`postcss-alias-atrules`]: https://github.com/maximkoretskiy/postcss-alias-atrules +[`postcss-assets-rebase`]: https://github.com/devex-web-frontend/postcss-assets-rebase +[`postcss-color-palette`]: https://github.com/zaim/postcss-color-palette +[`postcss-color-pantone`]: https://github.com/longdog/postcss-color-pantone +[`postcss-css-variables`]: https://github.com/MadLittleMods/postcss-css-variables +[`postcss-discard-empty`]: https://github.com/ben-eb/postcss-discard-empty +[`postcss-extract-value`]: https://github.com/lutien/postcss-extract-value +[`postcss-filter-stream`]: https://github.com/tsm91/postcss-filter-stream +[`postcss-gradientfixer`]: https://github.com/hallvors/postcss-gradientfixer +[`postcss-image-inliner`]: https://github.com/bezoerb/postcss-image-inliner +[`postcss-modular-scale`]: https://github.com/kristoferjoseph/postcss-modular-scale +[`postcss-normalize-url`]: https://github.com/ben-eb/postcss-normalize-url +[`postcss-reduce-idents`]: https://github.com/ben-eb/postcss-reduce-idents +[`postcss-regexp-detect`]: https://github.com/devex-web-frontend/postcss-regexp-detect +[`postcss-reverse-media`]: https://github.com/MadLittleMods/postcss-reverse-media +[`postcss-russian-units`]: https://github.com/Semigradsky/postcss-russian-units +[`postcss-short-spacing`]: https://github.com/jonathantneal/postcss-short-spacing +[`postcss-simple-extend`]: https://github.com/davidtheclark/postcss-simple-extend +[`postcss-speech-bubble`]: https://github.com/archana-s/postcss-speech-bubble +[`postcss-aspect-ratio`]: https://github.com/arccoza/postcss-aspect-ratio +[`postcss-brand-colors`]: https://github.com/postcss/postcss-brand-colors +[`postcss-class-prefix`]: https://github.com/thompsongl/postcss-class-prefix +[`postcss-conditionals`]: https://github.com/andyjansson/postcss-conditionals +[`postcss-custom-media`]: https://github.com/postcss/postcss-custom-media +[`postcss-default-unit`]: https://github.com/antyakushev/postcss-default-unit +[`postcss-flexboxfixer`]: https://github.com/hallvors/postcss-flexboxfixer +[`postcss-font-awesome`]: https://github.com/dan-gamble/postcss-font-awesome +[`postcss-font-variant`]: https://github.com/postcss/postcss-font-variant +[`postcss-media-minmax`]: https://github.com/postcss/postcss-media-minmax +[`postcss-merge-idents`]: https://github.com/ben-eb/postcss-merge-idents +[`postcss-mq-keyframes`]: https://github.com/TCotton/postcss-mq-keyframes +[`postcss-nested-props`]: https://github.com/jedmao/postcss-nested-props +[`postcss-sassy-mixins`]: https://github.com/andyjansson/postcss-sassy-mixins +[`postcss-selector-not`]: https://github.com/postcss/postcss-selector-not +[`postcss-svg-fallback`]: https://github.com/justim/postcss-svg-fallback +[`postcss-cachebuster`]: https://github.com/glebmachine/postcss-cachebuster +[`postcss-color-alpha`]: https://github.com/avanes/postcss-color-alpha +[`postcss-color-scale`]: https://github.com/kristoferjoseph/postcss-color-scale +[`postcss-color-short`]: https://github.com/andrepolischuk/postcss-color-short +[`postcss-copy-assets`]: https://github.com/shutterstock/postcss-copy-assets +[`postcss-data-packer`]: https://github.com/Ser-Gen/postcss-data-packer +[`postcss-easysprites`]: https://github.com/glebmachine/postcss-easysprites +[`postcss-flexibility`]: https://github.com/7rulnik/postcss-flexibility +[`postcss-font-family`]: https://github.com/ben-eb/postcss-font-family +[`postcss-grid-system`]: https://github.com/francoisromain/postcss-grid-system +[`postcss-input-style`]: https://github.com/seaneking/postcss-input-style +[`postcss-merge-rules`]: https://github.com/ben-eb/postcss-merge-rules +[`postcss-mq-optimize`]: https://github.com/panec/postcss-mq-optimize +[`postcss-nested-vars`]: https://github.com/jedmao/postcss-nested-vars +[`postcss-remove-root`]: https://github.com/cbracco/postcss-remove-root +[`postcss-simple-grid`]: https://github.com/admdh/postcss-simple-grid +[`postcss-simple-vars`]: https://github.com/postcss/postcss-simple-vars +[`postcss-strip-units`]: https://github.com/whitneyit/postcss-strip-units +[`postcss-style-guide`]: https://github.com/morishitter/postcss-style-guide +[`postcss-will-change`]: https://github.com/postcss/postcss-will-change +[`postcss-ase-colors`]: https://github.com/dfernandez79/postcss-ase-colors +[`postcss-bem-linter`]: https://github.com/postcss/postcss-bem-linter +[`postcss-camelcaser`]: https://github.com/GMchris/postcss-camelcaser +[`postcss-color-gray`]: https://github.com/postcss/postcss-color-gray +[`postcss-color-hexa`]: https://github.com/nicksheffield/postcss-color-hexa +[`postcss-colorblind`]: https://github.com/btholt/postcss-colorblind +[`postcss-grid-fluid`]: https://github.com/francoisromain/postcss-grid-fluid +[`postcss-inline-rtl`]: https://github.com/jakob101/postcss-inline-rtl +[`postcss-inline-svg`]: https://github.com/TrySound/postcss-inline-svg +[`postcss-short-text`]: https://github.com/jonathantneal/postcss-short-text +[`postcss-animation`]: https://github.com/zhouwenbin/postcss-animation +[`postcss-autoreset`]: https://github.com/maximkoretskiy/postcss-autoreset +[`postcss-color-hcl`]: https://github.com/devgru/postcss-color-hcl +[`postcss-color-hwb`]: https://github.com/postcss/postcss-color-hwb +[`postcss-color-mix`]: https://github.com/iamstarkov/postcss-color-mix +[`postcss-color-yiq`]: https://github.com/ben-eb/postcss-color-yiq +[`postcss-filter-mq`]: https://github.com/simeydotme/postcss-filter-mq +[`postcss-font-pack`]: https://github.com/jedmao/postcss-font-pack +[`postcss-functions`]: https://github.com/andyjansson/postcss-functions +[`postcss-get-color`]: https://github.com/ismamz/postcss-get-color +[`postcss-image-set`]: https://github.com/alex499/postcss-image-set +[`postcss-instagram`]: https://github.com/azat-io/postcss-instagram +[`postcss-namespace`]: https://github.com/totora0155/postcss-namespace +[`postcss-placehold`]: https://github.com/awayken/postcss-placehold +[`postcss-reference`]: https://github.com/dehuszar/postcss-reference +[`postcss-typescale`]: https://github.com/francoisromain/postcss-typescale +[`postcss-write-svg`]: https://github.com/jonathantneal/postcss-write-svg +[`postcss-clearfix`]: https://github.com/seaneking/postcss-clearfix +[`postcss-colormin`]: https://github.com/ben-eb/colormin +[`postcss-contrast`]: https://github.com/stephenway/postcss-contrast +[`postcss-cssstats`]: https://github.com/cssstats/postcss-cssstats +[`postcss-currency`]: https://github.com/talgautb/postcss-currency +[`postcss-fallback`]: https://github.com/MadLittleMods/postcss-fallback +[`postcss-fontpath`]: https://github.com/seaneking/postcss-fontpath +[`postcss-if-media`]: https://github.com/arccoza/postcss-if-media +[`postcss-imperial`]: https://github.com/cbas/postcss-imperial +[`postcss-position`]: https://github.com/seaneking/postcss-position +[`postcss-reporter`]: https://github.com/postcss/postcss-reporter +[`postcss-rgba-hex`]: https://github.com/XOP/postcss-rgba-hex +[`postcss-sanitize`]: https://github.com/eramdam/postcss-sanitize +[`postcss-spiffing`]: https://github.com/HashanP/postcss-spiffing +[`postcss-triangle`]: https://github.com/jedmao/postcss-triangle +[`postcss-trolling`]: https://github.com/juanfran/postcss-trolling +[`postcss-verthorz`]: https://github.com/davidhemphill/postcss-verthorz +[`pleeease-filters`]: https://github.com/iamvdo/pleeease-filters +[`postcss-easings`]: https://github.com/postcss/postcss-easings +[`postcss-flexbox`]: https://github.com/archana-s/postcss-flexbox +[`postcss-hexrgba`]: https://github.com/seaneking/postcss-hexrgba +[`postcss-initial`]: https://github.com/maximkoretskiy/postcss-initial +[`postcss-modules`]: https://github.com/outpunk/postcss-modules +[`postcss-opacity`]: https://github.com/iamvdo/postcss-opacity +[`postcss-pointer`]: https://github.com/markgoodyear/postcss-pointer +[`postcss-pxtorem`]: https://github.com/cuth/postcss-pxtorem +[`postcss-rgb-plz`]: https://github.com/himynameisdave/postcss-rgb-plz +[`postcss-scopify`]: https://github.com/pazams/postcss-scopify +[`postcss-sorting`]: https://github.com/hudochenkov/postcss-sorting +[`postcss-sprites`]: https://github.com/2createStudio/postcss-sprites +[`postcss-assets`]: https://github.com/borodean/postcss-assets +[`postcss-atroot`]: https://github.com/OEvgeny/postcss-atroot +[`postcss-border`]: https://github.com/andrepolischuk/postcss-border +[`postcss-button`]: https://github.com/francoisromain/postcss-button +[`postcss-center`]: https://github.com/jedmao/postcss-center +[`postcss-circle`]: https://github.com/jedmao/postcss-circle +[`postcss-esplit`]: https://github.com/vitaliyr/postcss-esplit +[`postcss-extend`]: https://github.com/travco/postcss-extend +[`postcss-fakeid`]: https://github.com/pathsofdesign/postcss-fakeid +[`postcss-filter`]: https://github.com/alanev/postcss-filter +[`postcss-hidden`]: https://github.com/lukelarsen/postcss-hidden +[`postcss-import`]: https://github.com/postcss/postcss-import +[`postcss-layout`]: https://github.com/arccoza/postcss-layout +[`postcss-mixins`]: https://github.com/postcss/postcss-mixins +[`postcss-nested`]: https://github.com/postcss/postcss-nested +[`postcss-select`]: https://github.com/johnotander/postcss-select +[`postcss-urlrev`]: https://github.com/yuezk/postcss-urlrev +[`postcss-zindex`]: https://github.com/ben-eb/postcss-zindex +[`list-selectors`]: https://github.com/davidtheclark/list-selectors +[`mq4-hover-shim`]: https://github.com/twbs/mq4-hover-shim +[`postcss-alias`]: https://github.com/seaneking/postcss-alias +[`postcss-apply`]: https://github.com/pascalduez/postcss-apply +[`postcss-focus`]: https://github.com/postcss/postcss-focus +[`postcss-match`]: https://github.com/rtsao/postcss-match +[`postcss-scrib`]: https://github.com/sneakertack/postcss-scrib +[`css2modernizr`]: https://github.com/vovanbo/css2modernizr +[`font-magician`]: https://github.com/jonathantneal/postcss-font-magician +[`immutable-css`]: https://github.com/johnotander/immutable-css +[`perfectionist`]: https://github.com/ben-eb/perfectionist +[`postcss-at2x`]: https://github.com/simonsmith/postcss-at2x +[`postcss-calc`]: https://github.com/postcss/postcss-calc +[`postcss-crip`]: https://github.com/johnie/postcss-crip +[`postcss-each`]: https://github.com/outpunk/postcss-each +[`postcss-epub`]: https://github.com/Rycochet/postcss-epub +[`postcss-grid`]: https://github.com/andyjansson/postcss-grid +[`postcss-host`]: https://github.com/vitkarpov/postcss-host +[`postcss-maze`]: https://github.com/cathydutton/postcss-maze +[`postcss-neat`]: https://github.com/jo-asakura/postcss-neat +[`postcss-size`]: https://github.com/postcss/postcss-size +[`postcss-svgo`]: https://github.com/ben-eb/postcss-svgo +[`postcss-unmq`]: https://github.com/jonathantneal/postcss-unmq +[`postcss-vmin`]: https://github.com/iamvdo/postcss-vmin +[`autoprefixer`]: https://github.com/postcss/autoprefixer +[`css-mqpacker`]: https://github.com/hail2u/node-css-mqpacker +[`postcss-bem`]: https://github.com/ileri/postcss-bem +[`postcss-for`]: https://github.com/antyakushev/postcss-for +[`postcss-ie8`]: https://github.com/4wdmedia/postcss-ie8 +[`postcss-map`]: https://github.com/pascalduez/postcss-map +[`postcss-raw`]: https://github.com/MadLittleMods/postcss-raw +[`postcss-svg`]: https://github.com/Pavliko/postcss-svg +[`postcss-url`]: https://github.com/postcss/postcss-url +[`colorguard`]: https://github.com/SlexAxton/css-colorguard +[`css-byebye`]: https://github.com/AoDev/css-byebye +[`stylehacks`]: https://github.com/ben-eb/stylehacks +[`cssgrace`]: https://github.com/cssdream/cssgrace +[`stylefmt`]: https://github.com/morishitter/stylefmt +[`csstyle`]: https://github.com/geddski/csstyle +[`webpcss`]: https://github.com/lexich/webpcss +[`doiuse`]: https://github.com/anandthakker/doiuse +[`pixrem`]: https://github.com/robwierzbowski/node-pixrem +[`rtlcss`]: https://github.com/MohammadYounes/rtlcss +[`short`]: https://github.com/jonathantneal/postcss-short +[`lost`]: https://github.com/corysimmons/lost diff --git a/docs/syntax.md b/docs/syntax.md index 3e974133e..10818f72c 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -51,7 +51,7 @@ module.exports = function (css, opts) { ``` [Safe Parser]: https://github.com/postcss/postcss-safe-parser -[`Root`]: https://github.com/postcss/postcss/blob/master/docs/api.md#root-node +[`Root`]: http://api.postcss.org/Root.html ### Main Theory @@ -132,7 +132,7 @@ A good PostCSS parser should provide all information (including spaces symbols) to generate byte-to-byte equal output. It is not so difficult, but respectful for user input and allow integration smoke tests. -A parser should save all additional symbols to [`node.raws`] object. +A parser should save all additional symbols to `node.raws` object. It is an open structure for you, you can add additional keys. For example, [SCSS parser] saves comment types (`/* */` or `//`) in `node.raws.inline`. @@ -142,7 +142,6 @@ It saves the original value with comments to `node.raws.value.raw` and uses it, if the node value was not changed. [SCSS parser]: https://github.com/postcss/postcss-scss -[`node.raws`]: https://github.com/postcss/postcss/blob/master/docs/api.md#node-raws ### Tests @@ -212,7 +211,7 @@ this.builder('}', rule, 'end'); A good PostCSS custom syntax saves all symbols and provide byte-to-byte equal output if there were no changes. -This is why every node has [`node.raws`] object to store space symbol, etc. +This is why every node has `node.raws` object to store space symbol, etc. Be careful, because sometimes these raw properties will not be present; some nodes may be built manually, or may lose their indentation when they are moved @@ -222,8 +221,6 @@ This is why the default stringifier has a `raw()` method to autodetect raw properties by other nodes. For example, it will look at other nodes to detect indent size and them multiply it with the current node depth. -[`node.raws`]: https://github.com/postcss/postcss/blob/master/docs/api.md#node-raws - ### Tests A stringifier must have tests too. diff --git a/docs/writing-a-plugin.md b/docs/writing-a-plugin.md index 93036b25c..63e3b5f9b 100644 --- a/docs/writing-a-plugin.md +++ b/docs/writing-a-plugin.md @@ -9,7 +9,7 @@ ## Documentation and Support -* [PostCSS API](https://github.com/postcss/postcss/blob/master/docs/api.md) +* [PostCSS API](http://api.postcss.org/) * [Ask questions](https://gitter.im/postcss/postcss) * [PostCSS twitter](https://twitter.com/postcss) with latest updates. diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 7c673940c..bd74d764a 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -43,6 +43,12 @@ gulp.task('lint', () => { .pipe(eslint.failAfterError()); }); +gulp.task('spellcheck', () => { + let run = require('gulp-run'); + return gulp.src(['*.md', 'docs/**/*.md'], { read: false }) + .pipe(run('yaspeller <%= file.path %>')); +}); + // Tests gulp.task('test', ['compile'], () => { @@ -93,4 +99,4 @@ gulp.task('api', ['clean'], done => { gulp.task('offline', ['version', 'lint', 'test', 'api']); -gulp.task('default', ['offline', 'integration']); +gulp.task('default', ['offline', 'spellcheck', 'integration']); diff --git a/lib/at-rule.es6 b/lib/at-rule.es6 index b9ef6e858..bad41f210 100644 --- a/lib/at-rule.es6 +++ b/lib/at-rule.es6 @@ -1,7 +1,25 @@ import Container from './container'; import warnOnce from './warn-once'; -export default class AtRule extends Container { +/** + * Represents an at-rule. + * + * If it’s followed in the CSS by a {} block, this node will have + * a nodes property representing its children. + * + * @extends Container + * + * @example + * const root = postcss.parse('@charset "UTF-8"; @media print {}'); + * + * const charset = root.first; + * charset.type //=> 'atrule' + * charset.nodes //=> undefined + * + * const media = root.last; + * media.nodes //=> [] + */ +class AtRule extends Container { constructor(defaults) { super(defaults); @@ -38,4 +56,59 @@ export default class AtRule extends Container { this.raws.params = val; } + /** + * @memberof AtRule# + * @member {string} name - the at-rule’s name immediately follows the `@` + * + * @example + * const root = postcss.parse('@media print {}'); + * media.name //=> 'media' + * const media = root.first; + */ + + /** + * @memberof AtRule# + * @member {string} params - the at-rule’s parameters, the values + * that follow the at-rule’s name but precede + * any {} block + * + * @example + * const root = postcss.parse('@media print, screen {}'); + * const media = root.first; + * media.params //=> 'print, screen' + */ + + /** + * @memberof AtRule# + * @member {object} raws - Information to generate byte-to-byte equal + * node string as it was in the origin input. + * + * Every parser saves its own properties, + * but the default CSS parser uses: + * + * * `before`: the space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + * * `after`: the space symbols after the last child of the node + * to the end of the node. + * * `between`: the symbols between the property and value + * for declarations, selector and `{` for rules, or last parameter + * and `{` for at-rules. + * * `semicolon`: contains true if the last child has + * an (optional) semicolon. + * * `afterName`: the space between the at-rule name and its parameters. + * + * PostCSS cleans at-rule parameters from comments and extra spaces, + * but it stores origin content in raws properties. + * As such, if you don’t change a declaration’s value, + * PostCSS will use the raw value with comments. + * + * @example + * const root = postcss.parse(' @media\nprint {\n}') + * root.first.first.raws //=> { before: ' ', + * // between: ' ', + * // afterName: '\n', + * // after: '\n' } + */ } + +export default AtRule; diff --git a/lib/comment.es6 b/lib/comment.es6 index 1f141a098..fc118d4a4 100644 --- a/lib/comment.es6 +++ b/lib/comment.es6 @@ -1,7 +1,15 @@ import warnOnce from './warn-once'; import Node from './node'; -export default class Comment extends Node { +/** + * Represents a comment between declarations or statements (rule and at-rules). + * + * Comments inside selectors, at-rule parameters, or declaration values + * will be stored in the `raws` properties explained above. + * + * @extends Node + */ +class Comment extends Node { constructor(defaults) { super(defaults); @@ -28,4 +36,23 @@ export default class Comment extends Node { this.raws.right = val; } + /** + * @memberof Comment# + * @member {string} text - the comment’s text + */ + + /** + * @memberof Comment# + * @member {object} raws - Information to generate byte-to-byte equal + * node string as it was in the origin input. + * + * Every parser saves its own properties, + * but the default CSS parser uses: + * + * * `before`: the space symbols before the node. + * * `left`: the space symbols between `/*` and the comment’s text. + * * `right`: the space symbols between the comment’s text. + */ } + +export default Comment; diff --git a/lib/container.es6 b/lib/container.es6 index 71ac1b9e5..242ff10b8 100644 --- a/lib/container.es6 +++ b/lib/container.es6 @@ -11,7 +11,33 @@ function cleanSource(nodes) { }); } -export default class Container extends Node { +/** + * @callback childCondition + * @param {Node} node - container child + * @param {number} index - child index + * @param {Node[]} nodes - all container children + * @return {boolean} + */ + + /** + * @callback childIterator + * @param {Node} node - container child + * @param {number} index - child index + * @return {false|undefined} returning `false` will break iteration + */ + +/** + * The {@link Root}, {@link AtRule}, and {@link Rule} container nodes + * inherit some common methods to help work with their children. + * + * Note that all containers can store any content. If you write a rule inside + * a rule, PostCSS will parse it. + * + * @extends Node + * @abstract + * @ignore + */ +class Container extends Node { push(child) { child.parent = this; @@ -19,6 +45,39 @@ export default class Container extends Node { return this; } + /** + * Iterates through the container’s immediate children, + * calling `callback` for each child. + * + * Returning `false` in the callback will break iteration. + * + * This method only iterates through the container’s immediate children. + * If you need to recursively iterate through all the container’s descendant + * nodes, use {@link Container#walk}. + * + * Unlike the for `{}`-cycle or `Array#forEach` this iterator is safe + * if you are mutating the array of child nodes during iteration. + * PostCSS will adjust the current index to match the mutations. + * + * @param {childIterator} callback - iterator receives each node and index + * + * @return {false|undefined} returns `false` if iteration was broke + * + * @example + * const root = postcss.parse('a { color: black; z-index: 1 }'); + * const rule = root.first; + * + * for ( let decl of rule.nodes ) { + * decl.cloneBefore({ prop: '-webkit-' + decl.prop }); + * // Cycle will be infinite, because cloneBefore moves the current node + * // to the next index + * } + * + * rule.each(decl => { + * decl.cloneBefore({ prop: '-webkit-' + decl.prop }); + * // Will be executed only for color and z-index + * }); + */ each(callback) { if ( !this.lastEach ) this.lastEach = 0; if ( !this.indexes ) this.indexes = { }; @@ -43,6 +102,25 @@ export default class Container extends Node { return result; } + /** + * Traverses the container’s descendant nodes, calling callback + * for each node. + * + * Like container.each(), this method is safe to use + * if you are mutating arrays during iteration. + * + * If you only need to iterate through the container’s immediate children, + * use {@link Container#each}. + * + * @param {childIterator} callback - iterator receives each node and index + * + * @return {false|undefined} returns `false` if iteration was broke + * + * @example + * root.walk(node => { + * // Traverses all descendant nodes. + * }); + */ walk(callback) { return this.each( (child, i) => { let result = callback(child, i); @@ -53,6 +131,35 @@ export default class Container extends Node { }); } + /** + * Traverses the container’s descendant nodes, calling callback + * for each declaration node. + * + * If you pass a filter, iteration will only happen over declarations + * with matching properties. + * + * Like {@link Container#each}, this method is safe + * to use if you are mutating arrays during iteration. + * + * @param {string|RegExp} [prop] - string or regular expression + * to filter declarations by property name + * @param {childIterator} callback - iterator receives each node and index + * + * @return {false|undefined} returns `false` if iteration was broke + * + * @example + * root.walkDecls(decl => { + * checkPropertySupport(decl.prop); + * }); + * + * root.walkDecls('border-radius', decl => { + * decl.remove(); + * }); + * + * root.walkDecls(/^background/, decl => { + * decl.value = takeFirstColorFromGradient(decl.value); + * }); + */ walkDecls(prop, callback) { if ( !callback ) { callback = prop; @@ -76,6 +183,29 @@ export default class Container extends Node { } } + /** + * Traverses the container’s descendant nodes, calling callback + * for each rule node. + * + * If you pass a filter, iteration will only happen over rules + * with matching selectors. + * + * Like {@link Container#each}, this method is safe + * to use if you are mutating arrays during iteration. + * + * @param {string|RegExp} [selector] - string or regular expression + * to filter rules by selector + * @param {childIterator} callback - iterator receives each node and index + * + * @return {false|undefined} returns `false` if iteration was broke + * + * @example + * const selectors = []; + * root.walkRules(rule => { + * selectors.push(rule.selector); + * }); + * console.log(`Your CSS uses ${selectors.length} selectors'); + */ walkRules(selector, callback) { if ( !callback ) { callback = selector; @@ -100,6 +230,36 @@ export default class Container extends Node { } } + /** + * Traverses the container’s descendant nodes, calling callback + * for each at-rule node. + * + * If you pass a filter, iteration will only happen over at-rules + * that have matching names. + * + * Like {@link Container#each}, this method is safe + * to use if you are mutating arrays during iteration. + * + * @param {string|RegExp} [name] - string or regular expression + * to filter at-rules by name + * @param {childIterator} callback - iterator receives each node and index + * + * @return {false|undefined} returns `false` if iteration was broke + * + * @example + * root.walkAtRules(rule => { + * if ( isOld(rule.name) ) rule.remove(); + * }); + * + * let first = false; + * root.walkAtRules('charset', rule => { + * if ( !first ) { + * first = true; + * } else { + * rule.remove(); + * } + * }); + */ walkAtRules(name, callback) { if ( !callback ) { callback = name; @@ -123,6 +283,22 @@ export default class Container extends Node { } } + /** + * Traverses the container’s descendant nodes, calling callback + * for each comment node. + * + * Like {@link Container#each}, this method is safe + * to use if you are mutating arrays during iteration. + * + * @param {childIterator} callback - iterator receives each node and index + * + * @return {false|undefined} returns `false` if iteration was broke + * + * @example + * root.walkComments(comment => { + * comment.remove(); + * }); + */ walkComments(callback) { return this.walk( (child, i) => { if ( child.type === 'comment' ) { @@ -131,6 +307,26 @@ export default class Container extends Node { }); } + /** + * Inserts new nodes to the start of the container. + * + * @param {...(Node|object|string|Node[])} children - new nodes + * + * @return {Node} this node for methods chain + * + * @example + * const decl1 = postcss.decl({ prop: 'color', value: 'black' }); + * const decl2 = postcss.decl({ prop: 'background-color', value: 'white' }); + * rule.append(decl1, decl2); + * + * root.append({ name: 'charset', params: '"UTF-8"' }); // at-rule + * root.append({ selector: 'a' }); // rule + * rule.append({ prop: 'color', value: 'black' }); // declaration + * rule.append({ text: 'Comment' }) // comment + * + * root.append('a {}'); + * root.first.append('color: black; z-index: 1'); + */ append(...children) { for ( let child of children ) { let nodes = this.normalize(child, this.last); @@ -139,6 +335,26 @@ export default class Container extends Node { return this; } + /** + * Inserts new nodes to the end of the container. + * + * @param {...(Node|object|string|Node[])} children - new nodes + * + * @return {Node} this node for methods chain + * + * @example + * const decl1 = postcss.decl({ prop: 'color', value: 'black' }); + * const decl2 = postcss.decl({ prop: 'background-color', value: 'white' }); + * rule.prepend(decl1, decl2); + * + * root.append({ name: 'charset', params: '"UTF-8"' }); // at-rule + * root.append({ selector: 'a' }); // rule + * rule.append({ prop: 'color', value: 'black' }); // declaration + * rule.append({ text: 'Comment' }) // comment + * + * root.append('a {}'); + * root.first.append('color: black; z-index: 1'); + */ prepend(...children) { children = children.reverse(); for ( let child of children ) { @@ -158,6 +374,17 @@ export default class Container extends Node { } } + /** + * Insert new node before old node within the container. + * + * @param {Node|number} exist - child or child’s index. + * @param {Node|object|string|Node[]} add - new node + * + * @return {Node} this node for methods chain + * + * @example + * rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop })); + */ insertBefore(exist, add) { exist = this.index(exist); @@ -176,6 +403,14 @@ export default class Container extends Node { return this; } + /** + * Insert new node after old node within the container. + * + * @param {Node|number} exist - child or child’s index + * @param {Node|object|string|Node[]} add - new node + * + * @return {Node} this node for methods chain + */ insertAfter(exist, add) { exist = this.index(exist); @@ -204,6 +439,20 @@ export default class Container extends Node { return this; } + /** + * Removes node from the container and cleans the parent properties + * from the node and its children. + * + * @param {Node|number} child - child or child’s index + * + * @return {Node} this node for methods chain + * + * @example + * rule.nodes.length //=> 5 + * rule.removeChild(decl); + * rule.nodes.length //=> 4 + * decl.parent //=> undefined + */ removeChild(child) { child = this.index(child); this.nodes[child].parent = undefined; @@ -220,13 +469,51 @@ export default class Container extends Node { return this; } + /** + * Removes all children from the container + * and cleans their parent properties. + * + * @return {Node} this node for methods chain + * + * @example + * rule.removeAll(); + * rule.nodes.length //=> 0 + */ removeAll() { for ( let node of this.nodes ) node.parent = undefined; this.nodes = []; return this; } - replaceValues(regexp, opts, callback) { + /** + * Passes all declaration values within the container that match pattern + * through callback, replacing those values with the returned result + * of callback. + * + * This method is useful if you are using a custom unit or function + * and need to iterate through all values. + * + * @param {string|RegExp} pattern - replace pattern + * @param {object} opts - options to speed up the search + * @param {string} opts.prop - an array of property names + * @param {string} opts.fast - string that’s used + * to narrow down values and speed up + * the regexp search + * @param {function|string} callback - string to replace pattern + * or callback that returns a new value. + * The callback will receive + * the same arguments as those passed + * to a function parameter + * of `String#replace`. + * + * @return {Node} this node for methods chain + * + * @example + * root.replaceValues(/\d+rem/, { fast: 'rem' }, string => { + * return 15 * parseInt(string) + 'px'; + * }); + */ + replaceValues(pattern, opts, callback) { if ( !callback ) { callback = opts; opts = { }; @@ -236,20 +523,52 @@ export default class Container extends Node { if ( opts.props && opts.props.indexOf(decl.prop) === -1 ) return; if ( opts.fast && decl.value.indexOf(opts.fast) === -1 ) return; - decl.value = decl.value.replace(regexp, callback); + decl.value = decl.value.replace(pattern, callback); }); return this; } + /** + * Returns `true` if callback returns `true` + * for all of the container’s children. + * + * @param {childCondition} condition - iterator returns true or false. + * + * @return {boolean} is every child pass condition + * + * @example + * const noPrefixes = rule.every(i => i.prop[0] !== '-'); + */ every(condition) { return this.nodes.every(condition); } + /** + * Returns `true` if callback returns `true` for (at least) one + * of the container’s children. + * + * @param {childCondition} condition - iterator returns true or false. + * + * @return {boolean} is every child pass condition + * + * @example + * const hasPrefix = rule.every(i => i.prop[0] === '-'); + */ some(condition) { return this.nodes.some(condition); } + /** + * Returns a `child`’s index within the {@link Container#nodes} array. + * + * @param {Node} child - child of the current container. + * + * @return {number} child index + * + * @example + * rule.index( rule.nodes[2] ) //=> 2 + */ index(child) { if ( typeof child === 'number' ) { return child; @@ -258,11 +577,27 @@ export default class Container extends Node { } } + /** + * The container’s first child. + * + * @type {Node} + * + * @example + * rule.first == rules.nodes[0]; + */ get first() { if ( !this.nodes ) return undefined; return this.nodes[0]; } + /** + * The container’s last child. + * + * @type {Node} + * + * @example + * rule.last == rule.nodes[rule.nodes.length - 1]; + */ get last() { if ( !this.nodes ) return undefined; return this.nodes[this.nodes.length - 1]; @@ -393,4 +728,17 @@ export default class Container extends Node { this.raws.after = val; } + /** + * @memberof Container# + * @member {Node[]} nodes - an array containing the container’s children + * + * @example + * const root = postcss.parse('a { color: black }'); + * root.nodes.length //=> 1 + * root.nodes[0].selector //=> 'a' + * root.nodes[0].nodes[0].prop //=> 'color' + */ + } + +export default Container; diff --git a/lib/declaration.es6 b/lib/declaration.es6 index d9486b5d0..5da0461c0 100644 --- a/lib/declaration.es6 +++ b/lib/declaration.es6 @@ -1,7 +1,18 @@ import warnOnce from './warn-once'; import Node from './node'; -export default class Declaration extends Node { +/** + * Represents a CSS declaration. + * + * @extends Node + * + * @example + * const root = postcss.parse('a { color: black }'); + * const decl = root.first.first; + * decl.type //=> 'decl' + * decl.toString() //=> ' color: black' + */ +class Declaration extends Node { constructor(defaults) { super(defaults); @@ -28,4 +39,63 @@ export default class Declaration extends Node { this.raws.important = val; } + /** + * @memberof Declaration# + * @member {string} prop - the declaration’s property name + * + * @example + * const root = postcss.parse('a { color: black }'); + * const decl = root.first.first; + * decl.prop //=> 'color' + */ + + /** + * @memberof Declaration# + * @member {string} value - the declaration’s value + * + * @example + * const root = postcss.parse('a { color: black }'); + * const decl = root.first.first; + * decl.value //=> 'black' + */ + + /** + * @memberof Declaration# + * @member {boolean} important - `true` if the declaration + * has an !important annotation. + * + * @example + * const root = postcss.parse('a { color: black !important; color: red }'); + * root.first.first.important //=> true + * root.first.last.important //=> undefined + */ + + /** + * @memberof Declaration# + * @member {object} raws - Information to generate byte-to-byte equal + * node string as it was in the origin input. + * + * Every parser saves its own properties, + * but the default CSS parser uses: + * + * * `before`: the space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + * * `between`: the symbols between the property and value + * for declarations, selector and `{` for rules, or last parameter + * and `{` for at-rules. + * * `important`: the content of the important statement, + * if it is not just `!important`. + * + * PostCSS cleans declaration from comments and extra spaces, + * but it stores origin content in raws properties. + * As such, if you don’t change a declaration’s value, + * PostCSS will use the raw value with comments. + * + * @example + * const root = postcss.parse('a {\n color:black\n}') + * root.first.first.raws //=> { before: '\n ', between: ':' } + */ + } + +export default Declaration; diff --git a/lib/input.es6 b/lib/input.es6 index f0c244cad..b7b6b0d93 100644 --- a/lib/input.es6 +++ b/lib/input.es6 @@ -6,7 +6,7 @@ import path from 'path'; let sequence = 0; /** - * @typedef {object} Position + * @typedef {object} filePosition * @property {string} file - path to file * @property {number} line - source line in file * @property {number} column - source column in file @@ -112,7 +112,7 @@ class Input { * @param {number} line - line in input CSS * @param {number} column - column in input CSS * - * @return {Position} position in input source + * @return {filePosition} position in input source * * @example * root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 } diff --git a/lib/node.es6 b/lib/node.es6 index b0e579e7b..5dac49075 100644 --- a/lib/node.es6 +++ b/lib/node.es6 @@ -3,6 +3,19 @@ import Stringifier from './stringifier'; import stringify from './stringify'; import warnOnce from './warn-once'; +/** + * @typedef {object} position + * @property {number} line - source line in file + * @property {number} column - source column in file + */ + +/** + * @typedef {object} source + * @property {Input} input - {@link Input} with input file + * @property {position} start - The starting position of the node’s source + * @property {position} end - The ending position of the node’s source + */ + let cloneNode = function (obj, parent) { let cloned = new obj.constructor(); @@ -27,8 +40,17 @@ let cloneNode = function (obj, parent) { return cloned; }; -export default class Node { - +/** + * All node classes inherit the following common methods. + * + * @abstract + * @ignore + */ +class Node { + + /** + * @param {object} [defaults] - value for node properties + */ constructor(defaults = { }) { this.raws = { }; for ( let name in defaults ) { @@ -36,6 +58,38 @@ export default class Node { } } + /** + * Returns a CssSyntaxError instance containing the original position + * of the node in the source, showing line and column numbers and also + * a small excerpt to facilitate debugging. + * + * If present, an input source map will be used to get the original position + * of the source, even from a previous compilation step + * (e.g., from Sass compilation). + * + * This method produces very useful error messages. + * + * @param {string} message - error description + * @param {object} [opts] - options + * @param {string} opts.plugin - plugin name that created this error. + * PostCSS will set it automatically. + * @param {string} opts.word - a word inside a node’s string that should + * be highlighted as the source of the error + * @param {number} opts.index - an index inside a node’s string that should + * be highlighted as the source of the error + * + * @return {CssSyntaxError} error object to throw it + * + * @example + * if ( !variables[name] ) { + * throw decl.error('Unknown variable ' + name, { word: name }); + * // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black + * // color: $black + * // a + * // ^ + * // background: white + * } + */ error(message, opts = { }) { if ( this.source ) { let pos = this.positionBy(opts); @@ -45,12 +99,48 @@ export default class Node { } } + /** + * This method is provided as a convenience wrapper for {@link Result#warn}. + * + * @param {Result} result - the {@link Result} instance + * that will receive the warning + * @param {string} text - warning message + * @param {object} [opts] - options + * @param {string} opts.plugin - plugin name that created this warning. + * PostCSS will set it automatically. + * @param {string} opts.word - a word inside a node’s string that should + * be highlighted as the source of the warning + * @param {number} opts.index - an index inside a node’s string that should + * be highlighted as the source of the warning + * + * @return {Warning} created warning object + * + * @example + * const plugin = postcss.plugin('postcss-deprecated', () => { + * return (css, result) => { + * css.walkDecls('bad', decl => { + * decl.warn(result, 'Deprecated property bad'); + * }); + * }; + * }); + */ warn(result, text, opts) { let data = { node: this }; for ( let i in opts ) data[i] = opts[i]; return result.warn(text, data); } + /** + * Removes the node from its parent and cleans the parent properties + * from the node and its children. + * + * @example + * if ( decl.prop.match(/^-webkit-/) ) { + * decl.remove(); + * } + * + * @return {Node} node to make calls chain + */ remove() { if ( this.parent ) { this.parent.removeChild(this); @@ -59,6 +149,17 @@ export default class Node { return this; } + /** + * Returns a CSS string representing the node. + * + * @param {stringifier|syntax} [stringifier] - a syntax to use + * in string generation + * + * @return {string} CSS string of this node + * + * @example + * postcss.rule({ selector: 'a' }).toString() //=> "a {}" + */ toString(stringifier = stringify) { if ( stringifier.stringify ) stringifier = stringifier.stringify; let result = ''; @@ -68,6 +169,22 @@ export default class Node { return result; } + /** + * Returns a clone of the node. + * + * The resulting cloned node and its (cloned) children will have + * a clean parent and code style properties. + * + * @param {object} [overrides] - new properties to override in the clone. + * + * @example + * const cloned = decl.clone({ prop: '-moz-' + decl.prop }); + * cloned.raws.before //=> undefined + * cloned.parent //=> undefined + * cloned.toString() //=> -moz-transform: scale(0) + * + * @return {Node} clone of the node + */ clone(overrides = { }) { let cloned = cloneNode(this); for ( let name in overrides ) { @@ -76,18 +193,49 @@ export default class Node { return cloned; } + /** + * Shortcut to clone the node and insert the resulting cloned node + * before the current node. + * + * @param {object} [overrides] - new properties to override in the clone. + * + * @example + * decl.cloneBefore({ prop: '-moz-' + decl.prop }); + * + * @return {Node} - new node + */ cloneBefore(overrides = { }) { let cloned = this.clone(overrides); this.parent.insertBefore(this, cloned); return cloned; } + /** + * Shortcut to clone the node and insert the resulting cloned node + * after the current node. + * + * @param {object} [overrides] - new properties to override in the clone. + * + * @return {Node} - new node + */ cloneAfter(overrides = { }) { let cloned = this.clone(overrides); this.parent.insertAfter(this, cloned); return cloned; } + /** + * Inserts node(s) before the current node and removes the current node. + * + * @param {...Node} nodes - node(s) to replace current one + * + * @example + * if ( atrule.name == 'mixin' ) { + * atrule.replaceWith(mixinRules[atrule.params]); + * } + * + * @return {Node} current node to methods chain + */ replaceWith(...nodes) { if (this.parent) { for (let node of nodes) { @@ -100,32 +248,97 @@ export default class Node { return this; } - moveTo(container) { - this.cleanRaws(this.root() === container.root()); + /** + * Removes the node from its current parent and inserts it + * at the end of `newParent`. + * + * This will clean the `before` and `after` code {@link Node#raws} data + * from the node and replace them with the indentation style of `newParent`. + * It will also clean the `between` property + * if `newParent` is in another {@link Root}. + * + * @param {Container} newParent - container node where the current node + * will be moved + * + * @example + * atrule.moveTo(atrule.root()); + * + * @return {Node} current node to methods chain + */ + moveTo(newParent) { + this.cleanRaws(this.root() === newParent.root()); this.remove(); - container.append(this); + newParent.append(this); return this; } - moveBefore(node) { - this.cleanRaws(this.root() === node.root()); + /** + * Removes the node from its current parent and inserts it into + * a new parent before `otherNode`. + * + * This will also clean the node’s code style properties just as it would + * in {@link Node#moveTo}. + * + * @param {Node} otherNode - node that will be before current node + * + * @return {Node} current node to methods chain + */ + moveBefore(otherNode) { + this.cleanRaws(this.root() === otherNode.root()); this.remove(); - node.parent.insertBefore(node, this); + otherNode.parent.insertBefore(otherNode, this); return this; } - moveAfter(node) { - this.cleanRaws(this.root() === node.root()); + /** + * Removes the node from its current parent and inserts it into + * a new parent after `otherNode`. + * + * This will also clean the node’s code style properties just as it would + * in {@link Node#moveTo}. + * + * @param {Node} otherNode - node that will be after current node + * + * @return {Node} current node to methods chain + */ + moveAfter(otherNode) { + this.cleanRaws(this.root() === otherNode.root()); this.remove(); - node.parent.insertAfter(node, this); + otherNode.parent.insertAfter(otherNode, this); return this; } + /** + * Returns the next child of the node’s parent. + * Returns `undefined` if the current node is the last child. + * + * @return {Node|undefined} next node + * + * @example + * if ( comment.text === 'delete next' ) { + * const next = comment.next(); + * if ( next ) { + * next.remove(); + * } + * } + */ next() { let index = this.parent.index(this); return this.parent.nodes[index + 1]; } + /** + * Returns the previous child of the node’s parent. + * Returns `undefined` if the current node is the first child. + * + * @return {Node|undefined} previous node + * + * @example + * const annotation = decl.prev(); + * if ( annotation.type == 'comment' ) { + * readAnnotation(annotation.text); + * } + */ prev() { let index = this.parent.index(this); return this.parent.nodes[index - 1]; @@ -157,11 +370,37 @@ export default class Node { return fixed; } - raw(own, detect) { + /** + * Returns a {@link Node#raws} value. If the node is missing + * the code style property (because the node was manually built or cloned), + * PostCSS will try to autodetect the code style property by looking + * at other nodes in the tree. + * + * @param {string} prop - name of code style property + * @param {string} [defaultType] - name of default value, it can be missed + * if the value is the same as prop + * + * @example + * const root = postcss.parse('a { background: white }'); + * root.nodes[0].append({ prop: 'color', value: 'black' }); + * root.nodes[0].nodes[1].raws.before //=> undefined + * root.nodes[0].nodes[1].raw('before') //=> ' ' + * + * @return {string} code style value + */ + raw(prop, defaultType) { let str = new Stringifier(); - return str.raw(this, own, detect); + return str.raw(this, prop, defaultType); } + /** + * Finds the Root instance of the node’s tree. + * + * @example + * root.nodes[0].nodes[0].root() === root + * + * @return {Root} root parent + */ root() { let result = this; while ( result.parent ) result = result.parent; @@ -242,4 +481,95 @@ export default class Node { this.raws.between = val; } + /** + * @memberof Node# + * @member {string} type - String representing the node’s type. + * Possible values are `root`, `atrule`, `rule`, + * `decl`, or `comment`. + * + * @example + * postcss.decl({ prop: 'color', value: 'black' }).type //=> 'decl' + */ + + /** + * @memberof Node# + * @member {Container} parent - the node’s parent node. + * + * @example + * root.nodes[0].parent == root; + */ + + /** + * @memberof Node# + * @member {source} source - the input source of the node + * + * The property is used in source map generation. + * + * If you create a node manually (e.g., with `postcss.decl()`), + * that node will not have a `source` property and will be absent + * from the source map. For this reason, the plugin developer should + * consider cloning nodes to create new ones (in which case the new node’s + * source will reference the original, cloned node) or setting + * the `source` property manually. + * + * ```js + * // Bad + * const prefixed = postcss.decl({ + * prop: '-moz-' + decl.prop, + * value: decl.value + * }); + * + * // Good + * const prefixed = decl.clone({ prop: '-moz-' + decl.prop }); + * ``` + * + * ```js + * if ( atrule.name == 'add-link' ) { + * const rule = postcss.rule({ selector: 'a', source: atrule.source }); + * atrule.parent.insertBefore(atrule, rule); + * } + * ``` + * + * @example + * decl.source.input.from //=> '/home/ai/a.sass' + * decl.source.start //=> { line: 10, column: 2 } + * decl.source.end //=> { line: 10, column: 12 } + */ + + /** + * @memberof Node# + * @member {object} raws - Information to generate byte-to-byte equal + * node string as it was in the origin input. + * + * Every parser saves its own properties, + * but the default CSS parser uses: + * + * * `before`: the space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + * * `after`: the space symbols after the last child of the node + * to the end of the node. + * * `between`: the symbols between the property and value + * for declarations, selector and `{` for rules, or last parameter + * and `{` for at-rules. + * * `semicolon`: contains true if the last child has + * an (optional) semicolon. + * * `afterName`: the space between the at-rule name and its parameters. + * * `left`: the space symbols between `/*` and the comment’s text. + * * `right`: the space symbols between the comment’s text + * and */. + * * `important`: the content of the important statement, + * if it is not just `!important`. + * + * PostCSS cleans selectors, declaration values and at-rule parameters + * from comments and extra spaces, but it stores origin content in raws + * properties. As such, if you don’t change a declaration’s value, + * PostCSS will use the raw value with comments. + * + * @example + * const root = postcss.parse('a {\n color:black\n}') + * root.first.first.raws //=> { before: '\n ', between: ':' } + */ + } + +export default Node; diff --git a/lib/postcss.es6 b/lib/postcss.es6 index 3101dcd6c..a99d7103c 100644 --- a/lib/postcss.es6 +++ b/lib/postcss.es6 @@ -186,7 +186,7 @@ postcss.list = list; * @return {Comment} new Comment node * * @example - * postcss.comment({ text: 'test' }).toString() //=> "/* test */" + * postcss.comment({ text: 'test' }) */ postcss.comment = defaults => new Comment(defaults); diff --git a/lib/processor.es6 b/lib/processor.es6 index 60d3fd06b..cd63174bd 100644 --- a/lib/processor.es6 +++ b/lib/processor.es6 @@ -17,18 +17,18 @@ import LazyResult from './lazy-result'; * @return {Root} PostCSS AST */ - /** - * @callback stringifier - * - * @param {Node} node - start node for stringifing. Usually {@link Root}. - * @param {builder} builder - function to concatenate CSS from node’s parts - * or generate string and source map - * - * @return {void} - */ +/** + * @callback stringifier + * + * @param {Node} node - start node for stringifing. Usually {@link Root}. + * @param {builder} builder - function to concatenate CSS from node’s parts + * or generate string and source map + * + * @return {void} + */ /** - * @typedef {object} Syntax + * @typedef {object} syntax * @property {parser} parse - function to generate AST by string * @property {stringifier} stringify - function to generate string by AST */ @@ -60,7 +60,7 @@ import LazyResult from './lazy-result'; * to generate correct source maps. * @property {parser} parser - function to generate AST by string * @property {stringifier} stringifier - class to generate string by AST - * @property {Syntax} syntax - object with `parse` and `stringify` + * @property {syntax} syntax - object with `parse` and `stringify` * @property {object} map - source map options * @property {boolean} map.inline - does source map should * be embedded in the output diff --git a/lib/root.es6 b/lib/root.es6 index d18400414..b954acc33 100644 --- a/lib/root.es6 +++ b/lib/root.es6 @@ -1,7 +1,17 @@ import Container from './container'; import warnOnce from './warn-once'; -export default class Root extends Container { +/** + * Represents a CSS file and contains all its parsed nodes. + * + * @extends Container + * + * @example + * const root = postcss.parse('a{color:black} b{z-index:2}'); + * root.type //=> 'root' + * root.nodes.length //=> 2 + */ +class Root extends Container { constructor(defaults) { super(defaults); @@ -39,6 +49,19 @@ export default class Root extends Container { return nodes; } + /** + * Returns a {@link Result} instance representing the root’s CSS. + * + * @param {processOptions} [opts] - options with only `to` and `map` keys + * + * @return {Result} result with current root’s CSS + * + * @example + * const root1 = postcss.parse(css1, { from: 'a.css' }); + * const root2 = postcss.parse(css2, { from: 'b.css' }); + * root1.append(root2); + * const result = root1.toResult({ to: 'all.css', map: true }); + */ toResult(opts = { }) { let LazyResult = require('./lazy-result'); let Processor = require('./processor'); @@ -57,4 +80,22 @@ export default class Root extends Container { return this.source.input.map; } + /** + * @memberof Root# + * @member {object} raws - Information to generate byte-to-byte equal + * node string as it was in the origin input. + * + * Every parser saves its own properties, + * but the default CSS parser uses: + * + * * `after`: the space symbols after the last child to the end of file. + * * `semicolon`: is the last child has an (optional) semicolon. + * + * @example + * postcss.parse('a {}\n').raws //=> { after: '\n' } + * postcss.parse('a {}').raws //=> { after: '' } + */ + } + +export default Root; diff --git a/lib/rule.es6 b/lib/rule.es6 index a0b55dee7..15973ad4b 100644 --- a/lib/rule.es6 +++ b/lib/rule.es6 @@ -2,7 +2,18 @@ import Container from './container'; import warnOnce from './warn-once'; import list from './list'; -export default class Rule extends Container { +/** + * Represents a CSS rule: a selector followed by a declaration block. + * + * @extends Container + * + * @example + * const root = postcss.parse('a{}'); + * const rule = root.first; + * rule.type //=> 'rule' + * rule.toString() //=> 'a{}' + */ +class Rule extends Container { constructor(defaults) { super(defaults); @@ -10,6 +21,22 @@ export default class Rule extends Container { if ( !this.nodes ) this.nodes = []; } + /** + * An array containing the rule’s individual selectors. + * Groups of selectors are split at commas. + * + * @type {string[]} + * + * @example + * const root = postcss.parse('a, b { }'); + * const rule = root.first; + * + * rule.selector //=> 'a, b' + * rule.selectors //=> ['a', 'b'] + * + * rule.selectors = ['a', 'strong']; + * rule.selector //=> 'a, strong' + */ get selectors() { return list.comma(this.selector); } @@ -30,4 +57,45 @@ export default class Rule extends Container { this.raws.selector = val; } + /** + * @memberof Rule# + * @member {string} selector - the rule’s full selector represented + * as a string + * + * @example + * const root = postcss.parse('a, b { }'); + * const rule = root.first; + * rule.selector //=> 'a, b' + */ + + /** + * @memberof Rule# + * @member {object} raws - Information to generate byte-to-byte equal + * node string as it was in the origin input. + * + * Every parser saves its own properties, + * but the default CSS parser uses: + * + * * `before`: the space symbols before the node. It also stores `*` + * and `_` symbols before the declaration (IE hack). + * * `after`: the space symbols after the last child of the node + * to the end of the node. + * * `between`: the symbols between the property and value + * for declarations, selector and `{` for rules, or last parameter + * and `{` for at-rules. + * * `semicolon`: contains true if the last child has + * an (optional) semicolon. + * + * PostCSS cleans selectors from comments and extra spaces, + * but it stores origin content in raws properties. + * As such, if you don’t change a declaration’s value, + * PostCSS will use the raw value with comments. + * + * @example + * const root = postcss.parse('a {\n color:black\n}') + * root.first.first.raws //=> { before: '', between: ' ', after: '\n' } + */ + } + +export default Rule; diff --git a/lib/warning.es6 b/lib/warning.es6 index d91c99018..2070ed41c 100644 --- a/lib/warning.es6 +++ b/lib/warning.es6 @@ -92,13 +92,13 @@ class Warning { * warning.plugin //=> 'postcss-important' */ - /** - * @memberof Warning# - * @member {Node} node - Contains the CSS node that caused the warning. - * - * @example - * warning.node.toString() //=> 'color: white !important' - */ + /** + * @memberof Warning# + * @member {Node} node - Contains the CSS node that caused the warning. + * + * @example + * warning.node.toString() //=> 'color: white !important' + */ } diff --git a/package.json b/package.json index f8d534162..fa86b5d4e 100644 --- a/package.json +++ b/package.json @@ -35,24 +35,25 @@ "postcss-parser-tests": "5.0.7", "babel-preset-es2015": "6.9.0", "gulp-sourcemaps": "1.6.0", - "babel-eslint": "6.0.4", + "babel-eslint": "6.1.0", "gulp-eslint": "2.0.0", "gulp-jsdoc3": "0.3.0", - "babel-core": "6.9.1", + "babel-core": "6.10.4", "gulp-babel": "6.1.2", "strip-ansi": "3.0.1", - "yaspeller": "2.8.0", + "yaspeller": "2.8.1", + "gulp-run": "1.7.1", "gulp-ava": "0.12.1", "fs-extra": "0.30.0", "docdash": "0.4.0", - "eslint": "2.13.0", + "eslint": "2.13.1", "sinon": "1.17.4", "gulp": "3.9.1", "ava": "0.15.2", - "del": "2.2.0" + "del": "2.2.1" }, "scripts": { - "test": "gulp && yaspeller *.md docs/**/*.md" + "test": "gulp" }, "main": "lib/postcss" }