Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/Exception/CssSyntaxError.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@
/**
* The CSS parser throws this error for broken CSS.
*
* Custom parsers can throw this error for broken custom syntax using
* the {@link Node#error} method.
* Custom parsers can throw this error for broken custom syntax using Node->error method.
*
* PostCSS will use the input source map to detect the original error location.
* If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS,
* PostCSS will show the original position in the Sass file.
* If you 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`.
* If you need the position in the PostCSS input (e.g., to debug the previous compiler), use `$error->input['file']`.
*
* @link https://github.com/postcss/postcss/blob/master/lib/css-syntax-error.es6
*/
class CssSyntaxError extends Exception
{
Expand Down Expand Up @@ -90,6 +89,9 @@ public function setMessage($message)
$this->message = (string) $message;
}

/**
* Updates the message.
*/
public function updateMessage()
{
$plugin = ($this->postcssPlugin instanceof PluginInterface) ? $this->postcssPlugin->getName() : (string) $this->postcssPlugin;
Expand Down Expand Up @@ -208,6 +210,11 @@ public function showSourceCode($color = null)
return implode("\n", $output);
}

/**
* {@inheritdoc}
*
* @see Exception::__toString()
*/
public function __toString()
{
$fqn = get_class($this);
Expand Down
81 changes: 56 additions & 25 deletions src/LazyResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

namespace PostCSS;

use React\Promise\Promise;
use PostCSS\Plugin\PluginInterface;
use React\Promise\Promise;
use React\Promise\PromiseInterface;

/**
* A Promise proxy for the result of PostCSS transformations.
Expand Down Expand Up @@ -50,6 +51,18 @@ class LazyResult
*/
protected $processing = null;

/**
* Current plugin index.
*
* @var int
*/
protected $plugin;

/**
* @param Processor $processor
* @param mixed $css
* @param array $opts
*/
public function __construct(Processor $processor, $css, array $opts = [])
{
$this->stringified = false;
Expand Down Expand Up @@ -122,8 +135,7 @@ public function __get($name)
}

/**
* Processes input CSS through synchronous plugins
* and calls {@link Result#warnings()}.
* Processes input CSS through synchronous plugins and calls Result->warnings().
*
* @return Warning[] warnings from plugins
*/
Expand All @@ -133,10 +145,10 @@ public function warnings()
}

/**
* Alias for the {@link LazyResult#css} property.
* Alias for the LazyResult->css property.
*
* @example
* lazy + '' === lazy.css;
* (string) $lazy === $lazy->css;
*
* @return string output CSS
*/
Expand All @@ -146,43 +158,37 @@ public function __toString()
}

/**
* 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.
* 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.
*
* It implements standard Promise API.
*
* @param {onFulfilled} onFulfilled - callback will be executed
* when all plugins will finish work
* @param {onRejected} onRejected - callback will be execited on any error
* @param callable $onFulfilled Callback will be executed when all plugins will finish work
* @param callable $onRejected Callback will be execited on any error
*
* @return Promise Promise API to make queue
*
* @example
* postcss([cssnext]).process(css).then(result => {
* console.log(result.css);
* });
* (new \PostCSS\Processor([Cssnext::class]))->process($css)->then(function ($result) { echo $result->css; })->done();
*/
public function then($onFulfilled, $onRejected)
{
return $this->async()->then($onFulfilled, $onRejected);
}

/**
* Processes input CSS through synchronous and asynchronous plugins
* and calls onRejected for each error thrown in any plugin.
*
* Processes input CSS through synchronous and asynchronous plugins and calls onRejected for each error thrown in any plugin.
* It implements standard Promise API.
*
* @param {onRejected} onRejected - callback will be execited on any error
* @param callable $onRejected Callback will be execited on any error
*
* @return Promise Promise API to make queue
*
* @example
* postcss([cssnext]).process(css).then(result => {
* console.log(result.css);
* }).catch(error => {
* console.error(error);
* (new \PostCSS\Processor([Cssnext::class]))->process($css)->then(function ($result) {
* echo $result->css);
* })->catchError(function ($error) {
* echo (string) $error;
* });
*/
public function catchError($onRejected)
Expand All @@ -193,6 +199,10 @@ public function catchError($onRejected)
);
}

/**
* @param \Exception $error
* @param PluginInterface|string $plugin
*/
public function handleError(\Exception $error, $plugin)
{
try {
Expand All @@ -216,6 +226,12 @@ public function handleError(\Exception $error, $plugin)
}
}

/**
* @param callable $resolve
* @param callable $reject
*
* @return mixed
*/
public function asyncTick($resolve, $reject)
{
if ($this->plugin >= count($this->result->processor->plugins)) {
Expand All @@ -228,7 +244,7 @@ public function asyncTick($resolve, $reject)
$promise = $this->run($plugin);
$this->plugin += 1;

if ($promise instanceof Promise) {
if ($promise instanceof PromiseInterface) {
$me = $this;
$promise->then(
function () use ($me, $resolve, $reject) {
Expand All @@ -249,6 +265,9 @@ function ($error) use ($me, $plugin, $reject) {
}
}

/**
* @return Promise
*/
public function async()
{
if ($this->processed) {
Expand Down Expand Up @@ -284,6 +303,11 @@ function () use ($me) {
return $this->processing;
}

/**
* @throws \Exception
*
* @return \PostCSS\Result
*/
public function sync()
{
if ($this->processed) {
Expand All @@ -292,7 +316,7 @@ public function sync()
$this->processed = true;

if ($this->processing) {
throw new \Exception('Use process(css).then(cb) to work with async plugins');
throw new \Exception('Use process($css)->then($cb) to work with async plugins');
}

if ($this->error) {
Expand All @@ -303,13 +327,20 @@ public function sync()
for ($i = 0; $i < count($processor->plugins); ++$i) {
$promise = $this->run($processor->plugins[$i]);
if ($promise instanceof Promise) {
throw new \Exception('Use process(css).then(cb) to work with async plugins');
throw new \Exception('Use process($css)->then($cb) to work with async plugins');
}
}

return $this->result;
}

/**
* @param PluginInterface $plugin
*
* @throws \Exception
*
* @return mixed
*/
public function run(PluginInterface $plugin)
{
$this->result->lastPlugin = $plugin;
Expand Down
45 changes: 42 additions & 3 deletions src/MapGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace PostCSS;

use PostCSS\SourceMap\Consumer\Consumer;
use PostCSS\Path\NodeJS as Path;
use PostCSS\SourceMap\Consumer\Consumer;

/**
* @link https://github.com/postcss/postcss/blob/master/lib/map-generator.es6
Expand Down Expand Up @@ -45,6 +45,11 @@ class MapGenerator
*/
protected $map = null;

/**
* @param callable $stringify
* @param Root $root
* @param array $opts
*/
public function __construct(callable $stringify, Root $root, array $opts = [])
{
$this->stringify = $stringify;
Expand All @@ -53,6 +58,9 @@ public function __construct(callable $stringify, Root $root, array $opts = [])
$this->opts = $opts;
}

/**
* @return bool
*/
public function isMap()
{
if (isset($this->opts['map'])) {
Expand All @@ -64,6 +72,9 @@ public function isMap()
}
}

/**
* @return PreviousMap[]
*/
public function previous()
{
if ($this->previousMaps === null) {
Expand All @@ -82,6 +93,9 @@ public function previous()
return $this->previousMaps;
}

/**
* @return bool
*/
public function isInline()
{
if (isset($this->mapOpts['inline'])) {
Expand Down Expand Up @@ -109,6 +123,9 @@ public function isInline()
}
}

/**
* @return bool
*/
public function isSourcesContent()
{
if (isset($this->mapOpts['sourcesContent'])) {
Expand Down Expand Up @@ -151,7 +168,7 @@ public function setSourcesContent()
$me = $this;
$already = [];
$this->root->walk(function (Node $node) use ($me, &$already) {
if ($node->source) {
if ($node->source && isset($node->source['input'])) {
$from = $node->source['input']->from;
if ($from && !isset($already[$from])) {
$already[$from] = true;
Expand Down Expand Up @@ -180,6 +197,9 @@ public function applyPrevMaps()
}
}

/**
* @return bool
*/
public function isAnnotation()
{
if ($this->isInline()) {
Expand Down Expand Up @@ -222,6 +242,9 @@ public function addAnnotation()
$this->css .= $eol.'/*# sourceMappingURL='.$content.' */';
}

/**
* @return string
*/
public function outputFile()
{
if (isset($this->opts['to']) && $this->opts['to']) {
Expand All @@ -233,6 +256,9 @@ public function outputFile()
}
}

/**
* @return array First array item is the css. If not inline, there's a second item (a SourceMap\Generator instance)
*/
public function generateMap()
{
$this->generateString();
Expand All @@ -254,6 +280,11 @@ public function generateMap()
}
}

/**
* @param string $file
*
* @return string
*/
public function relative($file)
{
if (preg_match('/^\w+:\/\//', $file)) {
Expand All @@ -274,7 +305,12 @@ public function relative($file)
}
}

public function sourcePath($node)
/**
* @param Node $node
*
* @return string
*/
public function sourcePath(Node $node)
{
if (isset($this->mapOpts['from']) && $this->mapOpts['from']) {
return $this->mapOpts['from'];
Expand Down Expand Up @@ -364,6 +400,9 @@ function ($str, Node $node = null, $type = null) use ($me, &$line, &$column) {
);
}

/**
* @return array First array item is the css. If not inline, there's a second item (a SourceMap\Generator instance)
*/
public function generate()
{
$this->clearAnnotation();
Expand Down
Loading