Changeset 115547 in spip-zone


Ignore:
Timestamp:
Jun 5, 2019, 12:26:49 PM (11 days ago)
Author:
cedric@…
Message:

La lib SCSSPHP change d'URL https://github.com/scssphp/scssphp et passe en version 1.0.0 avec plein de bugs résolus et un support SAAS encore ameliore
(changement aussi de namespace et de vendor)
Update de la lib, du namespace et increment de version

Location:
_plugins_/scssphp/trunk
Files:
34 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/scssphp/trunk/lib/scssphp/LICENSE.md

    r91026 r115547  
    1 Copyright (c) 2015 Leaf Corcoran, http://leafo.github.io/scssphp
     1Copyright (c) 2015 Leaf Corcoran, http://scssphp.github.io/scssphp
    22 
    33Permission is hereby granted, free of charge, to any person obtaining
  • _plugins_/scssphp/trunk/lib/scssphp/README.md

    r115410 r115547  
    11# scssphp
    2 ### <http://leafo.github.io/scssphp>
     2### <http://scssphp.github.io/scssphp>
    33
    4 [![Build](https://travis-ci.org/leafo/scssphp.svg?branch=master)](http://travis-ci.org/leafo/scssphp)
    5 [![License](https://poser.pugx.org/leafo/scssphp/license.svg)](https://packagist.org/packages/leafo/scssphp)
     4[![Build](https://travis-ci.org/scssphp/scssphp.svg?branch=master)](http://travis-ci.org/scssphp/scssphp)
     5[![License](https://poser.pugx.org/scssphp/scssphp/license)](https://packagist.org/packages/scssphp/scssphp)
    66
    77`scssphp` is a compiler for SCSS written in PHP.
    88
    9 Checkout the homepage, <http://leafo.github.io/scssphp>, for directions on how to use.
     9Checkout the homepage, <http://scssphp.github.io/scssphp>, for directions on how to use.
    1010
    1111## Running Tests
  • _plugins_/scssphp/trunk/lib/scssphp/composer.json

    r115410 r115547  
    11{
    2     "name": "leafo/scssphp",
     2    "name": "scssphp/scssphp",
    33    "type": "library",
    44    "description": "scssphp is a compiler for SCSS written in PHP.",
    55    "keywords": ["css", "stylesheet", "scss", "sass", "less"],
    6     "homepage": "http://leafo.github.io/scssphp/",
     6    "homepage": "http://scssphp.github.io/scssphp/",
    77    "license": [
    88        "MIT"
     
    1010    "authors": [
    1111        {
    12             "name": "Leaf Corcoran",
    13             "email": "leafot@gmail.com",
    14             "homepage": "http://leafo.net"
     12            "name": "Anthon Pang",
     13            "email": "apang@softwaredevelopment.ca",
     14            "homepage": "https://github.com/robocoder"
     15        },
     16        {
     17            "name": "Cédric Morin",
     18            "email": "cedric@yterium.com",
     19            "homepage": "https://github.com/Cerdic"
    1520        }
    1621    ],
    1722    "autoload": {
    18         "psr-4": { "Leafo\\ScssPhp\\": "src/" }
     23        "psr-4": { "ScssPhp\\ScssPhp\\": "src/" }
    1924    },
    2025    "autoload-dev": {
    21         "psr-4": { "Leafo\\ScssPhp\\Test\\": "tests/" }
     26        "psr-4": { "ScssPhp\\ScssPhp\\Test\\": "tests/" }
    2227    },
    2328    "require": {
  • _plugins_/scssphp/trunk/lib/scssphp/scss.inc.php

    r115305 r115547  
    44}
    55
    6 if (! class_exists('Leafo\ScssPhp\Version', false)) {
     6if (! class_exists('ScssPhp\ScssPhp\Version', false)) {
    77    include_once __DIR__ . '/src/Base/Range.php';
    88    include_once __DIR__ . '/src/Block.php';
  • _plugins_/scssphp/trunk/lib/scssphp/src/Base/Range.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2015-2018 Leaf Corcoran
     5 * @copyright 2015-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Base;
     12namespace ScssPhp\ScssPhp\Base;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Block.php

    r115301 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    1414/**
     
    2525
    2626    /**
    27      * @var \Leafo\ScssPhp\Block
     27     * @var \ScssPhp\ScssPhp\Block
    2828     */
    2929    public $parent;
     
    6565
    6666    /**
    67      * @var \Leafo\ScssPhp\Block
     67     * @var \ScssPhp\ScssPhp\Block
    6868     */
    6969    public $selfParent;
  • _plugins_/scssphp/trunk/lib/scssphp/src/Cache.php

    r115258 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    1414use Exception;
     
    1919 * In short:
    2020 *
    21  * allow to put in cache/get from fache a generic result from a known operation on a generic dataset,
     21 * allow to put in cache/get from cache a generic result from a known operation on a generic dataset,
    2222 * taking in account options that affects the result
    2323 *
    24  * The cache manager is agnostic about data format and only the operation is expected to be descripted by string
     24 * The cache manager is agnostic about data format and only the operation is expected to be described by string
    2525 *
    2626 */
     
    3333class Cache
    3434{
    35 
    36     const CACHE_VERSION = 0;
    37 
     35    const CACHE_VERSION = 1;
    3836
    3937    // directory used for storing data
    40     public static $cache_dir = false;
     38    public static $cacheDir = false;
    4139
    4240    // prefix for the storing data
     
    4442
    4543    // force a refresh : 'once' for refreshing the first hit on a cache only, true to never use the cache in this hit
    46     public static $force_refresh = false;
     44    public static $forceRefresh = false;
    4745
    4846    // specifies the number of seconds after which data cached will be seen as 'garbage' and potentially cleaned up
    49     public static $gc_lifetime = 604800;
    50 
    51 
    52     // array of already refreshed cache if $force_refresh==='once'
     47    public static $gcLifetime = 604800;
     48
     49    // array of already refreshed cache if $forceFefresh==='once'
    5350    protected static $refreshed = [];
    5451
    55 
    5652    /**
    5753     * Constructor
     54     *
     55     * @param array $options
    5856     */
    5957    public function __construct($options)
    6058    {
    61         //check $cache_dir
     59        // check $cacheDir
    6260        if (isset($options['cache_dir'])) {
    63             self::$cache_dir = $options['cache_dir'];
    64         }
    65 
    66         if (empty(self::$cache_dir)) {
     61            self::$cacheDir = $options['cache_dir'];
     62        }
     63
     64        if (empty(self::$cacheDir)) {
    6765            throw new Exception('cache_dir not set');
    6866        }
     
    7674        }
    7775
    78         if (isset($options['force_refresh'])) {
    79             self::$force_refresh = $options['force_refresh'];
     76        if (isset($options['forceRefresh'])) {
     77            self::$forceFefresh = $options['force_refresh'];
    8078        }
    8179
     
    8381    }
    8482
    85 
    86     /**
    87      * Get the cached result of $operation on $what, which is known as dependant from the content of $options
    88      *
    89      * @param string $operation
    90      *   parse, compile...
    91      * @param $what
    92      *  content key (filename to be treated for instance)
    93      * @param array $options
    94      *  any option that affect the operation result on the content
    95      * @param int $last_modified
     83    /**
     84     * Get the cached result of $operation on $what,
     85     * which is known as dependant from the content of $options
     86     *
     87     * @param string  $operation    parse, compile...
     88     * @param mixed   $what         content key (e.g., filename to be treated)
     89     * @param array   $options      any option that affect the operation result on the content
     90     * @param integer $lastModified last modified timestamp
     91     *
    9692     * @return mixed
    97      * @throws Exception
    98      */
    99     public function getCache($operation, $what, $options = array(), $last_modified = null)
    100     {
    101 
    102         $fileCache = self::$cache_dir . self::cacheName($operation, $what, $options);
    103 
    104         if ((! self::$force_refresh || (self::$force_refresh === 'once' && isset(self::$refreshed[$fileCache])))
    105           and file_exists($fileCache)) {
    106             $cache_time = filemtime($fileCache);
    107             if ((is_null($last_modified) or $cache_time > $last_modified)
    108               and $cache_time + self::$gc_lifetime > time()) {
     93     *
     94     * @throws \Exception
     95     */
     96    public function getCache($operation, $what, $options = [], $lastModified = null)
     97    {
     98        $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options);
     99
     100        if ((! self::$forceRefresh || (self::$forceRefresh === 'once' && isset(self::$refreshed[$fileCache])))
     101            && file_exists($fileCache)
     102        ) {
     103            $cacheTime = filemtime($fileCache);
     104
     105            if ((is_null($lastModified) || $cacheTime > $lastModified)
     106                && $cacheTime + self::$gcLifetime > time()
     107            ) {
    109108                $c = file_get_contents($fileCache);
    110109                $c = unserialize($c);
    111                 if (is_array($c) and isset($c['value'])) {
     110
     111                if (is_array($c) && isset($c['value'])) {
    112112                    return $c['value'];
    113113                }
     
    119119
    120120    /**
    121      * Put in cache the result of $operation on $what, which is known as dependant from the content of $options
     121     * Put in cache the result of $operation on $what,
     122     * which is known as dependant from the content of $options
    122123     *
    123124     * @param string $operation
    124      * @param $what
    125      * @param $value
    126      * @param array $options
    127      */
    128     public function setCache($operation, $what, $value, $options = array())
    129     {
    130         $fileCache = self::$cache_dir . self::cacheName($operation, $what, $options);
    131 
    132         $c = array('value' => $value);
     125     * @param mixed  $what
     126     * @param mixed  $value
     127     * @param array  $options
     128     */
     129    public function setCache($operation, $what, $value, $options = [])
     130    {
     131        $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options);
     132
     133        $c = ['value' => $value];
    133134        $c = serialize($c);
    134135        file_put_contents($fileCache, $c);
    135136
    136         if (self::$force_refresh === 'once') {
     137        if (self::$forceRefresh === 'once') {
    137138            self::$refreshed[$fileCache] = true;
    138139        }
    139140    }
    140141
    141 
    142     /**
    143      * get the cachename for the caching of $opetation on $what, which is known as dependant from the content of $options
     142    /**
     143     * Get the cache name for the caching of $operation on $what,
     144     * which is known as dependant from the content of $options
     145     *
    144146     * @param string $operation
    145      * @param $what
    146      * @param array $options
     147     * @param mixed  $what
     148     * @param array  $options
     149     *
    147150     * @return string
    148151     */
    149     private static function cacheName($operation, $what, $options = array())
    150     {
    151 
    152         $t = array(
     152    private static function cacheName($operation, $what, $options = [])
     153    {
     154        $t = [
    153155          'version' => self::CACHE_VERSION,
    154156          'operation' => $operation,
    155157          'what' => $what,
    156158          'options' => $options
    157         );
     159        ];
    158160
    159161        $t = self::$prefix
     
    165167    }
    166168
    167 
    168     /**
    169      * Check that the cache dir is existing and writeable
    170      * @throws Exception
     169    /**
     170     * Check that the cache dir exists and is writeable
     171     *
     172     * @throws \Exception
    171173     */
    172174    public static function checkCacheDir()
    173175    {
    174 
    175         self::$cache_dir = str_replace('\\', '/', self::$cache_dir);
    176         self::$cache_dir = rtrim(self::$cache_dir, '/') . '/';
    177 
    178         if (! file_exists(self::$cache_dir)) {
    179             if (! mkdir(self::$cache_dir)) {
    180                 throw new Exception('Cache directory couldn\'t be created: ' . self::$cache_dir);
    181             }
    182         } elseif (! is_dir(self::$cache_dir)) {
    183             throw new Exception('Cache directory doesn\'t exist: ' . self::$cache_dir);
    184         } elseif (! is_writable(self::$cache_dir)) {
    185             throw new Exception('Cache directory isn\'t writable: ' . self::$cache_dir);
     176        self::$cacheDir = str_replace('\\', '/', self::$cacheDir);
     177        self::$cacheDir = rtrim(self::$cacheDir, '/') . '/';
     178
     179        if (! file_exists(self::$cacheDir)) {
     180            if (! mkdir(self::$cacheDir)) {
     181                throw new Exception('Cache directory couldn\'t be created: ' . self::$cacheDir);
     182            }
     183        } elseif (! is_dir(self::$cacheDir)) {
     184            throw new Exception('Cache directory doesn\'t exist: ' . self::$cacheDir);
     185        } elseif (! is_writable(self::$cacheDir)) {
     186            throw new Exception('Cache directory isn\'t writable: ' . self::$cacheDir);
    186187        }
    187188    }
     
    189190    /**
    190191     * Delete unused cached files
    191      *
    192192     */
    193193    public static function cleanCache()
     
    195195        static $clean = false;
    196196
    197 
    198         if ($clean || empty(self::$cache_dir)) {
     197        if ($clean || empty(self::$cacheDir)) {
    199198            return;
    200199        }
     
    204203        // only remove files with extensions created by SCSSPHP Cache
    205204        // css files removed based on the list files
    206         $remove_types = array('scsscache' => 1);
    207 
    208         $files = scandir(self::$cache_dir);
     205        $removeTypes = ['scsscache' => 1];
     206
     207        $files = scandir(self::$cacheDir);
     208
    209209        if (! $files) {
    210210            return;
    211211        }
    212212
    213         $check_time = time() - self::$gc_lifetime;
     213        $checkTime = time() - self::$gcLifetime;
     214
    214215        foreach ($files as $file) {
    215216            // don't delete if the file wasn't created with SCSSPHP Cache
     
    221222            $type = array_pop($parts);
    222223
    223 
    224             if (! isset($remove_types[$type])) {
     224            if (! isset($removeTypes[$type])) {
    225225                continue;
    226226            }
    227227
    228             $full_path = self::$cache_dir . $file;
    229             $mtime = filemtime($full_path);
     228            $fullPath = self::$cacheDir . $file;
     229            $mtime = filemtime($fullPath);
    230230
    231231            // don't delete if it's a relatively new file
    232             if ($mtime > $check_time) {
     232            if ($mtime > $checkTime) {
    233233                continue;
    234234            }
    235235
    236             unlink($full_path);
     236            unlink($fullPath);
    237237        }
    238238    }
  • _plugins_/scssphp/trunk/lib/scssphp/src/Colors.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Compiler.php

    r115410 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
    13 
    14 use Leafo\ScssPhp\Base\Range;
    15 use Leafo\ScssPhp\Block;
    16 use Leafo\ScssPhp\Cache;
    17 use Leafo\ScssPhp\Colors;
    18 use Leafo\ScssPhp\Compiler\Environment;
    19 use Leafo\ScssPhp\Exception\CompilerException;
    20 use Leafo\ScssPhp\Formatter\OutputBlock;
    21 use Leafo\ScssPhp\Node;
    22 use Leafo\ScssPhp\SourceMap\SourceMapGenerator;
    23 use Leafo\ScssPhp\Type;
    24 use Leafo\ScssPhp\Parser;
    25 use Leafo\ScssPhp\Util;
     12namespace ScssPhp\ScssPhp;
     13
     14use ScssPhp\ScssPhp\Base\Range;
     15use ScssPhp\ScssPhp\Block;
     16use ScssPhp\ScssPhp\Cache;
     17use ScssPhp\ScssPhp\Colors;
     18use ScssPhp\ScssPhp\Compiler\Environment;
     19use ScssPhp\ScssPhp\Exception\CompilerException;
     20use ScssPhp\ScssPhp\Formatter\OutputBlock;
     21use ScssPhp\ScssPhp\Node;
     22use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
     23use ScssPhp\ScssPhp\Type;
     24use ScssPhp\ScssPhp\Parser;
     25use ScssPhp\ScssPhp\Util;
    2626
    2727/**
     
    100100    ];
    101101
    102     static public $true = [Type::T_KEYWORD, 'true'];
    103     static public $false = [Type::T_KEYWORD, 'false'];
    104     static public $null = [Type::T_NULL];
    105     static public $nullString = [Type::T_STRING, '', []];
     102    static public $true         = [Type::T_KEYWORD, 'true'];
     103    static public $false        = [Type::T_KEYWORD, 'false'];
     104    static public $null         = [Type::T_NULL];
     105    static public $nullString   = [Type::T_STRING, '', []];
    106106    static public $defaultValue = [Type::T_KEYWORD, ''];
    107107    static public $selfSelector = [Type::T_SELF];
    108     static public $emptyList = [Type::T_LIST, '', []];
    109     static public $emptyMap = [Type::T_MAP, [], []];
    110     static public $emptyString = [Type::T_STRING, '"', []];
    111     static public $with = [Type::T_KEYWORD, 'with'];
    112     static public $without = [Type::T_KEYWORD, 'without'];
     108    static public $emptyList    = [Type::T_LIST, '', []];
     109    static public $emptyMap     = [Type::T_MAP, [], []];
     110    static public $emptyString  = [Type::T_STRING, '"', []];
     111    static public $with         = [Type::T_KEYWORD, 'with'];
     112    static public $without      = [Type::T_KEYWORD, 'without'];
    113113
    114114    protected $importPaths = [''];
     
    131131
    132132    /**
    133      * @var string|\Leafo\ScssPhp\Formatter
    134      */
    135     protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
     133     * @var string|\ScssPhp\ScssPhp\Formatter
     134     */
     135    protected $formatter = 'ScssPhp\ScssPhp\Formatter\Nested';
    136136
    137137    protected $rootEnv;
     
    139139
    140140    /**
    141      * @var \Leafo\ScssPhp\Compiler\Environment
     141     * @var \ScssPhp\ScssPhp\Compiler\Environment
    142142     */
    143143    protected $env;
     
    166166     * Constructor
    167167     */
    168     public function __construct($cache_options = null)
     168    public function __construct($cacheOptions = null)
    169169    {
    170170        $this->parsedFiles = [];
    171171        $this->sourceNames = [];
    172172
    173         if ($cache_options) {
    174             $this->cache = new Cache($cache_options);
     173        if ($cacheOptions) {
     174            $this->cache = new Cache($cacheOptions);
    175175        }
    176176    }
     
    178178    public function getCompileOptions()
    179179    {
    180         $options = array(
    181             'importPaths' => $this->importPaths,
    182             'registeredVars' => $this->registeredVars,
     180        $options = [
     181            'importPaths'        => $this->importPaths,
     182            'registeredVars'     => $this->registeredVars,
    183183            'registeredFeatures' => $this->registeredFeatures,
    184             'encoding' => $this->encoding,
    185             'sourceMap' => serialize($this->sourceMap),
    186             'sourceMapOptions' => $this->sourceMapOptions,
    187             'formater' => $this->formatter,
    188         );
     184            'encoding'           => $this->encoding,
     185            'sourceMap'          => serialize($this->sourceMap),
     186            'sourceMapOptions'   => $this->sourceMapOptions,
     187            'formatter'          => $this->formatter,
     188        ];
     189
    189190        return $options;
    190191    }
     
    202203    public function compile($code, $path = null)
    203204    {
    204 
    205205        if ($this->cache) {
    206             $cache_key = ($path ? $path : "(stdin)") . ":" . md5($code);
    207             $compile_options = $this->getCompileOptions();
    208             $cache = $this->cache->getCache("compile", $cache_key, $compile_options);
     206            $cacheKey = ($path ? $path : "(stdin)") . ":" . md5($code);
     207            $compileOptions = $this->getCompileOptions();
     208            $cache = $this->cache->getCache("compile", $cacheKey, $compileOptions);
     209
    209210            if (is_array($cache)
    210                 and isset($cache['dependencies'])
    211                 and isset($cache['out']) ) {
     211                && isset($cache['dependencies'])
     212                && isset($cache['out'])
     213            ) {
    212214                // check if any dependency file changed before accepting the cache
    213215                foreach ($cache['dependencies'] as $file => $mtime) {
    214                     if (!file_exists($file)
    215                         or filemtime($file) !== $mtime) {
     216                    if (! file_exists($file)
     217                        || filemtime($file) !== $mtime
     218                    ) {
    216219                        unset($cache);
    217220                        break;
    218221                    }
    219222                }
     223
    220224                if (isset($cache)) {
    221225                    return $cache['out'];
     
    280284        }
    281285
    282         if ($this->cache and isset($cache_key) and isset($compile_options)) {
    283             $v = array(
     286        if ($this->cache && isset($cacheKey) && isset($compileOptions)) {
     287            $v = [
    284288                'dependencies' => $this->getParsedFiles(),
    285289                'out' => &$out,
    286             );
    287             $this->cache->setCache("compile", $cache_key, $v, $compile_options);
     290            ];
     291
     292            $this->cache->setCache("compile", $cacheKey, $v, $compileOptions);
    288293        }
    289294
     
    296301     * @param string $path
    297302     *
    298      * @return \Leafo\ScssPhp\Parser
     303     * @return \ScssPhp\ScssPhp\Parser
    299304     */
    300305    protected function parserFactory($path)
     
    358363     * @param array  $selectors
    359364     *
    360      * @return \Leafo\ScssPhp\Formatter\OutputBlock
     365     * @return \ScssPhp\ScssPhp\Formatter\OutputBlock
    361366     */
    362367    protected function makeOutputBlock($type, $selectors = null)
     
    386391     * Compile root
    387392     *
    388      * @param \Leafo\ScssPhp\Block $rootBlock
     393     * @param \ScssPhp\ScssPhp\Block $rootBlock
    389394     */
    390395    protected function compileRoot(Block $rootBlock)
     
    425430     * Flatten selectors
    426431     *
    427      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
    428      * @param string                               $parentKey
     432     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
     433     * @param string                                 $parentKey
    429434     */
    430435    protected function flattenSelectors(OutputBlock $block, $parentKey = null)
     
    491496    {
    492497        $new = [];
     498
    493499        foreach ($parts as $part) {
    494500            if (is_array($part)) {
     
    507513            }
    508514        }
     515
    509516        return $new;
    510517    }
     
    521528    {
    522529        static $partsPile = [];
     530
    523531        $selector = $this->glueFunctionSelectors($selector);
    524532
     
    540548            if ($this->matchExtendsSingle($part, $origin)) {
    541549                $partsPile[] = $part;
    542                 $after = array_slice($selector, $i + 1);
    543                 $before = array_slice($selector, 0, $i);
     550                $after       = array_slice($selector, $i + 1);
     551                $before      = array_slice($selector, 0, $i);
    544552
    545553                list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before);
     
    549557
    550558                    // remove shared parts
    551                     if (count($new)>1) {
     559                    if (count($new) > 1) {
    552560                        while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) {
    553561                            $k++;
     
    562570
    563571                        foreach ($tempReplacement[$l] as $chunk) {
    564                             if (!in_array($chunk, $slice)) {
     572                            if (! in_array($chunk, $slice)) {
    565573                                $slice[] = $chunk;
    566574                            }
     
    593601
    594602                    // recursively check for more matches
    595                     $startRecursFrom = count($before) + min(count($nonBreakableBefore), count($mergedBefore));
    596                     $this->matchExtends($result, $out, $startRecursFrom, false);
     603                    $startRecurseFrom = count($before) + min(count($nonBreakableBefore), count($mergedBefore));
     604                    $this->matchExtends($result, $out, $startRecurseFrom, false);
    597605
    598606                    // selector sequence merging
    599607                    if (! empty($before) && count($new) > 1) {
    600                         $sharedParts = $k > 0 ? array_slice($before, 0, $k) : [];
     608                        $preSharedParts = $k > 0 ? array_slice($before, 0, $k) : [];
    601609                        $postSharedParts = $k > 0 ? array_slice($before, $k) : $before;
    602610
    603                         list($injectBetweenSharedParts, $nonBreakable2) = $this->extractRelationshipFromFragment($afterBefore);
     611                        list($betweenSharedParts, $nonBreakable2) = $this->extractRelationshipFromFragment($afterBefore);
    604612
    605613                        $result2 = array_merge(
    606                             $sharedParts,
    607                             $injectBetweenSharedParts,
     614                            $preSharedParts,
     615                            $betweenSharedParts,
    608616                            $postSharedParts,
    609617                            $nonBreakable2,
     
    616624                    }
    617625                }
     626
    618627                array_pop($partsPile);
    619628            }
     
    672681        foreach ($counts as $idx => $count) {
    673682            list($target, $origin, /* $block */) = $this->extends[$idx];
     683
    674684            $origin = $this->glueFunctionSelectors($origin);
    675685
     
    787797     * Compile media
    788798     *
    789      * @param \Leafo\ScssPhp\Block $media
     799     * @param \ScssPhp\ScssPhp\Block $media
    790800     */
    791801    protected function compileMedia(Block $media)
     
    798808            $previousScope = $this->scope;
    799809            $parentScope = $this->mediaParent($this->scope);
     810
    800811            foreach ($mediaQueries as $mediaQuery) {
    801812                $this->scope = $this->makeOutputBlock(Type::T_MEDIA, [$mediaQuery]);
     
    812823
    813824                if ($type !== Type::T_BLOCK &&
    814                   $type !== Type::T_MEDIA &&
    815                   $type !== Type::T_DIRECTIVE &&
    816                   $type !== Type::T_IMPORT
     825                    $type !== Type::T_MEDIA &&
     826                    $type !== Type::T_DIRECTIVE &&
     827                    $type !== Type::T_IMPORT
    817828                ) {
    818829                    $needsWrap = true;
     
    869880     * Media parent
    870881     *
    871      * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope
    872      *
    873      * @return \Leafo\ScssPhp\Formatter\OutputBlock
     882     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
     883     *
     884     * @return \ScssPhp\ScssPhp\Formatter\OutputBlock
    874885     */
    875886    protected function mediaParent(OutputBlock $scope)
     
    889900     * Compile directive
    890901     *
    891      * @param \Leafo\ScssPhp\Block $block
     902     * @param \ScssPhp\ScssPhp\Block $block
    892903     */
    893904    protected function compileDirective(Block $block)
     
    909920     * Compile at-root
    910921     *
    911      * @param \Leafo\ScssPhp\Block $block
     922     * @param \ScssPhp\ScssPhp\Block $block
    912923     */
    913924    protected function compileAtRoot(Block $block)
     
    960971     * Filter at-root scope depending of with/without option
    961972     *
    962      * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope
    963      * @param mixed                                $without
     973     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
     974     * @param mixed                                  $without
    964975     *
    965976     * @return mixed
     
    10031014        }
    10041015
    1005         if (!count($filteredScopes)) {
     1016        if (! count($filteredScopes)) {
    10061017            return $this->rootBlock;
    10071018        }
     
    10281039     * (if at-root is just enclosing a property, the selector is in the parent tree)
    10291040     *
    1030      * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope
    1031      * @param \Leafo\ScssPhp\Formatter\OutputBlock $previousScope
     1041     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
     1042     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $previousScope
    10321043     *
    10331044     * @return mixed
     
    10511062     * Find a selector by the depth node in the scope
    10521063     *
    1053      * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope
    1054      * @param integer                              $depth
     1064     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
     1065     * @param integer                                $depth
    10551066     *
    10561067     * @return array
     
    11291140     * @param integer $without
    11301141     *
    1131      * @return \Leafo\ScssPhp\Compiler\Environment
     1142     * @return \ScssPhp\ScssPhp\Compiler\Environment
    11321143     */
    11331144    protected function filterWithout($envs, $without)
     
    11371148        foreach ($envs as $e) {
    11381149            if ($e->block && $this->isWithout($without, $e->block)) {
    1139                 continue;
    1140             }
    1141 
    1142             $filtered[] = $e;
     1150                $ec = clone $e;
     1151                $ec->block = null;
     1152                $ec->selectors = [];
     1153                $filtered[] = $ec;
     1154            } else {
     1155                $filtered[] = $e;
     1156            }
    11431157        }
    11441158
     
    11491163     * Filter WITH rules
    11501164     *
    1151      * @param integer                                                   $without
    1152      * @param \Leafo\ScssPhp\Block|\Leafo\ScssPhp\Formatter\OutputBlock $block
     1165     * @param integer                                                       $without
     1166     * @param \ScssPhp\ScssPhp\Block|\ScssPhp\ScssPhp\Formatter\OutputBlock $block
    11531167     *
    11541168     * @return boolean
     
    11821196     * Compile keyframe block
    11831197     *
    1184      * @param \Leafo\ScssPhp\Block $block
    1185      * @param array                $selectors
     1198     * @param \ScssPhp\ScssPhp\Block $block
     1199     * @param array                  $selectors
    11861200     */
    11871201    protected function compileKeyframeBlock(Block $block, $selectors)
     
    12101224     * Compile nested block
    12111225     *
    1212      * @param \Leafo\ScssPhp\Block $block
    1213      * @param array                $selectors
     1226     * @param \ScssPhp\ScssPhp\Block $block
     1227     * @param array                  $selectors
    12141228     */
    12151229    protected function compileNestedBlock(Block $block, $selectors)
     
    12721286     * @see Compiler::compileChild()
    12731287     *
    1274      * @param \Leafo\ScssPhp\Block $block
     1288     * @param \ScssPhp\ScssPhp\Block $block
    12751289     */
    12761290    protected function compileBlock(Block $block)
     
    13391353    {
    13401354        $out = $this->makeOutputBlock(Type::T_COMMENT);
    1341         $out->lines[] = $block[1];
     1355        $out->lines[] = is_string($block[1]) ? $block[1] : $this->compileValue($block[1]);
    13421356
    13431357        $this->scope->children[] = $out;
     
    14141428     * Collapse selectors
    14151429     *
    1416      * @param array $selectors
    1417      * @param bool $selectorFormat
     1430     * @param array   $selectors
     1431     * @param boolean $selectorFormat
    14181432     *   if false return a collapsed string
    14191433     *   if true return an array description of a structured selector
     
    14281442            $output = [];
    14291443            $glueNext = false;
     1444
    14301445            foreach ($selector as $node) {
    14311446                $compound = '';
     
    14371452                    }
    14381453                );
     1454
    14391455                if ($selectorFormat && $this->isImmediateRelationshipCombinator($compound)) {
    14401456                    if (count($output)) {
     
    14601476                $output = implode(' ', $output);
    14611477            }
     1478
    14621479            $parts[] = $output;
    14631480        }
     
    14901507            }
    14911508        }
     1509
    14921510        return $selectors;
    14931511    }
     
    16051623          Parser::SOURCE_COLUMN => $this->sourceColumn
    16061624        ];
     1625
    16071626        // infinite calling loop
    16081627        if (count($this->callStack) > 25000) {
     
    16221641     * Compile children and return result
    16231642     *
    1624      * @param array                                $stms
    1625      * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
    1626      * @param string                               $traceName
     1643     * @param array                                  $stms
     1644     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
     1645     * @param string                                 $traceName
    16271646     *
    16281647     * @return array|null
     
    16311650    {
    16321651        $this->pushCallStack($traceName);
     1652
    16331653        foreach ($stms as $stm) {
    16341654            $ret = $this->compileChild($stm, $out);
     
    16381658            }
    16391659        }
     1660
    16401661        $this->popCallStack();
    16411662
     
    16461667     * Compile children and throw exception if unexpected @return
    16471668     *
    1648      * @param array                                $stms
    1649      * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
    1650      * @param \Leafo\ScssPhp\Block                 $selfParent
    1651      * @param string                               $traceName
     1669     * @param array                                  $stms
     1670     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
     1671     * @param \ScssPhp\ScssPhp\Block                 $selfParent
     1672     * @param string                                 $traceName
    16521673     *
    16531674     * @throws \Exception
     
    16561677    {
    16571678        $this->pushCallStack($traceName);
     1679
    16581680        foreach ($stms as $stm) {
    16591681            if ($selfParent && isset($stm[1]) && is_object($stm[1]) && $stm[1] instanceof Block) {
     
    16751697            }
    16761698        }
     1699
    16771700        $this->popCallStack();
    16781701    }
     
    17551778
    17561779            $mediaTypeOnly = true;
     1780
    17571781            foreach ($query as $q) {
    17581782                if ($q[0] !== Type::T_MEDIA_TYPE) {
     
    17611785                }
    17621786            }
     1787
    17631788            foreach ($query as $q) {
    17641789                switch ($q[0]) {
     
    17711796                                    array_unshift($parts, implode(' ', array_filter($type)));
    17721797                                }
     1798
    17731799                                if (! empty($parts)) {
    17741800                                    if (strlen($current)) {
    17751801                                        $current .= $this->formatter->tagSeparator;
    17761802                                    }
     1803
    17771804                                    $current .= implode(' and ', $parts);
    17781805                                }
     1806
    17791807                                if ($current) {
    17801808                                    $out[] = $start . $current;
    17811809                                }
     1810
    17821811                                $current = "";
    17831812                                $type = null;
     
    17851814                            }
    17861815                        }
     1816
    17871817                        if ($newType === ['all'] && $default) {
    17881818                            $default = $start . 'all';
    17891819                        }
     1820
    17901821                        // all can be safely ignored and mixed with whatever else
    17911822                        if ($newType !== ['all']) {
     
    18411872            $out[] = $start . $current;
    18421873        }
     1874
    18431875        // no @media type except all, and no conflict?
    1844         if (!$out && $default) {
     1876        if (! $out && $default) {
    18451877            $out[] = $default;
    18461878        }
     1879
    18471880        return $out;
    18481881    }
     
    18821915                    $merged = array_merge($selectors1, [$part1], $selectors2, [$part2], $merged);
    18831916                }
     1917
    18841918                break;
    18851919            }
     
    19601994     * Compile import; returns true if the value was something that could be imported
    19611995     *
    1962      * @param array                                $rawPath
    1963      * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
    1964      * @param boolean                              $once
     1996     * @param array                                  $rawPath
     1997     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
     1998     * @param boolean                                $once
    19651999     *
    19662000     * @return boolean
     
    20082042     * Compile child; returns a value to halt execution
    20092043     *
    2010      * @param array                                $child
    2011      * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
     2044     * @param array                                  $child
     2045     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
    20122046     *
    20132047     * @return array
     
    20192053            $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1;
    20202054            $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1;
    2021         } elseif (is_array($child) and isset($child[1]->sourceLine)) {
     2055        } elseif (is_array($child) && isset($child[1]->sourceLine)) {
    20222056            $this->sourceIndex = $child[1]->sourceIndex;
    20232057            $this->sourceLine = $child[1]->sourceLine;
    20242058            $this->sourceColumn = $child[1]->sourceColumn;
    2025         } elseif (! empty($out->sourceLine) and ! empty($out->sourceName)) {
     2059        } elseif (! empty($out->sourceLine) && ! empty($out->sourceName)) {
    20262060            $this->sourceLine = $out->sourceLine;
    20272061            $this->sourceIndex = array_search($out->sourceName, $this->sourceNames);
     
    23802414
    23812415            case Type::T_MIXIN_CONTENT:
    2382                 $content = $this->get(static::$namespaces['special'] . 'content', false, isset($this->storeEnv) ? $this->storeEnv : $this->env);
     2416                $env = isset($this->storeEnv) ? $this->storeEnv : $this->env;
     2417                $content = $this->get(static::$namespaces['special'] . 'content', false, $env);
    23832418
    23842419                if (! $content) {
     
    25142549     * @param boolean $inExp
    25152550     *
    2516      * @return array|\Leafo\ScssPhp\Node\Number
     2551     * @return array|\ScssPhp\ScssPhp\Node\Number
    25172552     */
    25182553    protected function reduce($value, $inExp = false)
     
    27912826     * @param array $right
    27922827     *
    2793      * @return \Leafo\ScssPhp\Node\Number
     2828     * @return \ScssPhp\ScssPhp\Node\Number
    27942829     */
    27952830    protected function opAddNumberNumber($left, $right)
     
    28042839     * @param array $right
    28052840     *
    2806      * @return \Leafo\ScssPhp\Node\Number
     2841     * @return \ScssPhp\ScssPhp\Node\Number
    28072842     */
    28082843    protected function opMulNumberNumber($left, $right)
     
    28172852     * @param array $right
    28182853     *
    2819      * @return \Leafo\ScssPhp\Node\Number
     2854     * @return \ScssPhp\ScssPhp\Node\Number
    28202855     */
    28212856    protected function opSubNumberNumber($left, $right)
     
    28302865     * @param array $right
    28312866     *
    2832      * @return array|\Leafo\ScssPhp\Node\Number
     2867     * @return array|\ScssPhp\ScssPhp\Node\Number
    28332868     */
    28342869    protected function opDivNumberNumber($left, $right)
     
    28472882     * @param array $right
    28482883     *
    2849      * @return \Leafo\ScssPhp\Node\Number
     2884     * @return \ScssPhp\ScssPhp\Node\Number
    28502885     */
    28512886    protected function opModNumberNumber($left, $right)
     
    28982933    protected function opAnd($left, $right, $shouldEval)
    28992934    {
     2935        $truthy = ($left === static::$null || $right === static::$null) ||
     2936                  ($left === static::$false || $left === static::$true) &&
     2937                  ($right === static::$false || $right === static::$true);
     2938
    29002939        if (! $shouldEval) {
    2901             return null;
    2902         }
    2903 
    2904         if ($left !== static::$false and $left !== static::$null) {
     2940            if (! $truthy) {
     2941                return null;
     2942            }
     2943        }
     2944
     2945        if ($left !== static::$false && $left !== static::$null) {
    29052946            return $this->reduce($right, true);
    29062947        }
     
    29202961    protected function opOr($left, $right, $shouldEval)
    29212962    {
     2963        $truthy = ($left === static::$null || $right === static::$null) ||
     2964                  ($left === static::$false || $left === static::$true) &&
     2965                  ($right === static::$false || $right === static::$true);
     2966
    29222967        if (! $shouldEval) {
    2923             return null;
    2924         }
    2925 
    2926         if ($left !== static::$false and $left !== static::$null) {
     2968            if (! $truthy) {
     2969                return null;
     2970            }
     2971        }
     2972
     2973        if ($left !== static::$false && $left !== static::$null) {
    29272974            return $left;
    29282975        }
     
    31353182     * @param array $right
    31363183     *
    3137      * @return \Leafo\ScssPhp\Node\Number
     3184     * @return \ScssPhp\ScssPhp\Node\Number
    31383185     */
    31393186    protected function opCmpNumberNumber($left, $right)
     
    33893436     * Find the final set of selectors
    33903437     *
    3391      * @param \Leafo\ScssPhp\Compiler\Environment $env
    3392      * @param \Leafo\ScssPhp\Block                $selfParent
     3438     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
     3439     * @param \ScssPhp\ScssPhp\Block                $selfParent
    33933440     *
    33943441     * @return array
     
    34023449        $selfParentSelectors = null;
    34033450
    3404         if (!is_null($selfParent) and $selfParent->selectors) {
     3451        if (! is_null($selfParent) && $selfParent->selectors) {
    34053452            $selfParentSelectors = $this->evalSelectors($selfParent->selectors);
    34063453        }
     
    34453492     * Join selectors; looks for & to replace, or append parent before child
    34463493     *
    3447      * @param array $parent
    3448      * @param array $child
    3449      * @param bool  &$stillHasSelf
    3450      * @param array $selfParentSelectors
     3494     * @param array   $parent
     3495     * @param array   $child
     3496     * @param boolean &$stillHasSelf
     3497     * @param array   $selfParentSelectors
    34513498
    34523499     * @return array
     
    34653512                    $stillHasSelf = true;
    34663513                }
    3467                 if ($p === static::$selfSelector && !$setSelf) {
     3514
     3515                if ($p === static::$selfSelector && ! $setSelf) {
    34683516                    $setSelf = true;
    34693517
     
    34863534                                $pp = implode($flatten);
    34873535                            }
     3536
    34883537                            $newPart[] = $pp;
    34893538                        }
     
    35033552     * Multiply media
    35043553     *
    3505      * @param \Leafo\ScssPhp\Compiler\Environment $env
    3506      * @param array                               $childQueries
     3554     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
     3555     * @param array                                 $childQueries
    35073556     *
    35083557     * @return array
     
    35393588            foreach ($parentQueries as $parentQuery) {
    35403589                foreach ($originalQueries as $childQuery) {
    3541                     $childQueries []= array_merge($parentQuery, [[Type::T_MEDIA_TYPE, [Type::T_KEYWORD, 'all']]], $childQuery);
     3590                    $childQueries[] = array_merge(
     3591                        $parentQuery,
     3592                        [[Type::T_MEDIA_TYPE, [Type::T_KEYWORD, 'all']]],
     3593                        $childQuery
     3594                    );
    35423595                }
    35433596            }
     
    35503603     * Convert env linked list to stack
    35513604     *
    3552      * @param \Leafo\ScssPhp\Compiler\Environment $env
     3605     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
    35533606     *
    35543607     * @return array
     
    35683621     * @param array $envs
    35693622     *
    3570      * @return \Leafo\ScssPhp\Compiler\Environment
     3623     * @return \ScssPhp\ScssPhp\Compiler\Environment
    35713624     */
    35723625    protected function extractEnv($envs)
     
    35833636     * Push environment
    35843637     *
    3585      * @param \Leafo\ScssPhp\Block $block
    3586      *
    3587      * @return \Leafo\ScssPhp\Compiler\Environment
     3638     * @param \ScssPhp\ScssPhp\Block $block
     3639     *
     3640     * @return \ScssPhp\ScssPhp\Compiler\Environment
    35883641     */
    35893642    protected function pushEnv(Block $block = null)
     
    36113664     * Get store environment
    36123665     *
    3613      * @return \Leafo\ScssPhp\Compiler\Environment
     3666     * @return \ScssPhp\ScssPhp\Compiler\Environment
    36143667     */
    36153668    protected function getStoreEnv()
     
    36213674     * Set variable
    36223675     *
    3623      * @param string                              $name
    3624      * @param mixed                               $value
    3625      * @param boolean                             $shadow
    3626      * @param \Leafo\ScssPhp\Compiler\Environment $env
    3627      * @param mixed                               $valueUnreduced
     3676     * @param string                                $name
     3677     * @param mixed                                 $value
     3678     * @param boolean                               $shadow
     3679     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
     3680     * @param mixed                                 $valueUnreduced
    36283681     */
    36293682    protected function set($name, $value, $shadow = false, Environment $env = null, $valueUnreduced = null)
     
    36453698     * Set existing variable
    36463699     *
    3647      * @param string                              $name
    3648      * @param mixed                               $value
    3649      * @param \Leafo\ScssPhp\Compiler\Environment $env
    3650      * @param mixed                               $valueUnreduced
     3700     * @param string                                $name
     3701     * @param mixed                                 $value
     3702     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
     3703     * @param mixed                                 $valueUnreduced
    36513704     */
    36523705    protected function setExisting($name, $value, Environment $env, $valueUnreduced = null)
     
    36843737     * Set raw variable
    36853738     *
    3686      * @param string                              $name
    3687      * @param mixed                               $value
    3688      * @param \Leafo\ScssPhp\Compiler\Environment $env
    3689      * @param mixed                               $valueUnreduced
     3739     * @param string                                $name
     3740     * @param mixed                                 $value
     3741     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
     3742     * @param mixed                                 $valueUnreduced
    36903743     */
    36913744    protected function setRaw($name, $value, Environment $env, $valueUnreduced = null)
     
    37033756     * @api
    37043757     *
    3705      * @param string                              $name
    3706      * @param boolean                             $shouldThrow
    3707      * @param \Leafo\ScssPhp\Compiler\Environment $env
    3708      * @param boolean                             $unreduced
     3758     * @param string                                $name
     3759     * @param boolean                               $shouldThrow
     3760     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
     3761     * @param boolean                               $unreduced
    37093762     *
    37103763     * @return mixed|null
     
    37283781                break;
    37293782            }
     3783
    37303784            if (array_key_exists($normalizedName, $env->store)) {
    37313785                if ($unreduced && isset($env->storeUnreduced[$normalizedName])) {
     
    37643818     * Has variable?
    37653819     *
    3766      * @param string                              $name
    3767      * @param \Leafo\ScssPhp\Compiler\Environment $env
     3820     * @param string                                $name
     3821     * @param \ScssPhp\ScssPhp\Compiler\Environment $env
    37683822     *
    37693823     * @return boolean
     
    39894043     * Import file
    39904044     *
    3991      * @param string                               $path
    3992      * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
     4045     * @param string                                 $path
     4046     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
    39934047     */
    39944048    protected function importFile($path, OutputBlock $out)
     
    40414095                foreach ($urls as $full) {
    40424096                    $separator = (
    4043                         !empty($dir) &&
     4097                        ! empty($dir) &&
    40444098                        substr($dir, -1) !== '/' &&
    40454099                        substr($full, 0, 1) !== '/'
     
    40854139     * @param boolean $ignoreErrors
    40864140     *
    4087      * @return \Leafo\ScssPhp\Compiler
     4141     * @return \ScssPhp\ScssPhp\Compiler
    40884142     */
    40894143    public function setIgnoreErrors($ignoreErrors)
     
    41014155     * @param string $msg Message with optional sprintf()-style vararg parameters
    41024156     *
    4103      * @throws \Leafo\ScssPhp\Exception\CompilerException
     4157     * @throws \ScssPhp\ScssPhp\Exception\CompilerException
    41044158     */
    41054159    public function throwError($msg)
     
    41094163        }
    41104164
     4165        $line   = $this->sourceLine;
     4166        $column = $this->sourceColumn;
     4167
     4168        $loc = isset($this->sourceNames[$this->sourceIndex])
     4169             ? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column"
     4170             : "line: $line, column: $column";
     4171
    41114172        if (func_num_args() > 1) {
    41124173            $msg = call_user_func_array('sprintf', func_get_args());
    41134174        }
    41144175
    4115         $line = $this->sourceLine;
    4116         $loc = isset($this->sourceNames[$this->sourceIndex])
    4117              ? $this->sourceNames[$this->sourceIndex] . " on line $line"
    4118              : "line: $line";
    41194176        $msg = "$msg: $loc";
    41204177
    41214178        $callStackMsg = $this->callStackMessage();
     4179
    41224180        if ($callStackMsg) {
    41234181            $msg .= "\nCall Stack:\n" . $callStackMsg;
     
    41284186
    41294187    /**
    4130      * @param bool $all
    4131      * @param null $limit
     4188     * Beautify call stack for output
     4189     *
     4190     * @param boolean $all
     4191     * @param null    $limit
     4192     *
    41324193     * @return string
    41334194     */
     
    41464207                    $msg .= " on line " . $call[Parser::SOURCE_LINE];
    41474208                    $callStackMsg[] = $msg;
    4148                     if (!is_null($limit) && $ncall>$limit) {
     4209
     4210                    if (! is_null($limit) && $ncall>$limit) {
    41494211                        break;
    41504212                    }
     
    44634525     * @param mixed $value
    44644526     *
    4465      * @return array|\Leafo\ScssPhp\Node\Number
     4527     * @return array|\ScssPhp\ScssPhp\Node\Number
    44664528     */
    44674529    protected function coerceValue($value)
     
    59756037        return $args[0];
    59766038    }
     6039
     6040    /**
     6041     * Preprocess selector args
     6042     *
     6043     * @param array $arg
     6044     *
     6045     * @return array|boolean
     6046     */
     6047    protected function getSelectorArg($arg)
     6048    {
     6049        static $parser = null;
     6050
     6051        if (is_null($parser)) {
     6052            $parser = $this->parserFactory(__METHOD__);
     6053        }
     6054
     6055        $arg = $this->libUnquote([$arg]);
     6056        $arg = $this->compileValue($arg);
     6057
     6058        $parsedSelector = [];
     6059
     6060        if ($parser->parseSelector($arg, $parsedSelector)) {
     6061            $selector = $this->evalSelectors($parsedSelector);
     6062            $gluedSelector = $this->glueFunctionSelectors($selector);
     6063
     6064            return $gluedSelector;
     6065        }
     6066
     6067        return false;
     6068    }
     6069
     6070    /**
     6071     * Postprocess selector to output in right format
     6072     *
     6073     * @param array $selectors
     6074     *
     6075     * @return string
     6076     */
     6077    protected function formatOutputSelector($selectors)
     6078    {
     6079        $selectors = $this->collapseSelectors($selectors, true);
     6080
     6081        return $selectors;
     6082    }
     6083
     6084    protected static $libIsSuperselector = ['super', 'sub'];
     6085    protected function libIsSuperselector($args)
     6086    {
     6087        list($super, $sub) = $args;
     6088
     6089        $super = $this->getSelectorArg($super);
     6090        $sub = $this->getSelectorArg($sub);
     6091
     6092        return $this->isSuperSelector($super, $sub);
     6093    }
     6094
     6095    /**
     6096     * Test a $super selector again $sub
     6097     *
     6098     * @param array $super
     6099     * @param array $sub
     6100     *
     6101     * @return boolean
     6102     */
     6103    protected function isSuperSelector($super, $sub)
     6104    {
     6105        // one and only one selector for each arg
     6106        if (! $super || count($super) !== 1) {
     6107            $this->throwError("Invalid super selector for isSuperSelector()");
     6108        }
     6109
     6110        if (! $sub || count($sub) !== 1) {
     6111            $this->throwError("Invalid sub selector for isSuperSelector()");
     6112        }
     6113
     6114        $super = reset($super);
     6115        $sub = reset($sub);
     6116
     6117        $i = 0;
     6118        $nextMustMatch = false;
     6119
     6120        foreach ($super as $node) {
     6121            $compound = '';
     6122
     6123            array_walk_recursive(
     6124                $node,
     6125                function ($value, $key) use (&$compound) {
     6126                    $compound .= $value;
     6127                }
     6128            );
     6129
     6130            if ($this->isImmediateRelationshipCombinator($compound)) {
     6131                if ($node !== $sub[$i]) {
     6132                    return false;
     6133                }
     6134
     6135                $nextMustMatch = true;
     6136                $i++;
     6137            } else {
     6138                while ($i < count($sub) && ! $this->isSuperPart($node, $sub[$i])) {
     6139                    if ($nextMustMatch) {
     6140                        return false;
     6141                    }
     6142
     6143                    $i++;
     6144                }
     6145
     6146                if ($i >= count($sub)) {
     6147                    return false;
     6148                }
     6149
     6150                $nextMustMatch = false;
     6151                $i++;
     6152            }
     6153        }
     6154
     6155        return true;
     6156    }
     6157
     6158    /**
     6159     * Test a part of super selector again a part of sub selector
     6160     *
     6161     * @param array $superParts
     6162     * @param array $subParts
     6163     *
     6164     * @return boolean
     6165     */
     6166    protected function isSuperPart($superParts, $subParts)
     6167    {
     6168        $i = 0;
     6169
     6170        foreach ($superParts as $superPart) {
     6171            while ($i < count($subParts) && $subParts[$i] !== $superPart) {
     6172                $i++;
     6173            }
     6174
     6175            if ($i >= count($subParts)) {
     6176                return false;
     6177            }
     6178
     6179            $i++;
     6180        }
     6181
     6182        return true;
     6183    }
     6184
     6185    //protected static $libSelectorAppend = ['selector...'];
     6186    protected function libSelectorAppend($args)
     6187    {
     6188        if (count($args) < 1) {
     6189            $this->throwError("selector-append() needs at least 1 argument");
     6190        }
     6191
     6192        $selectors = array_map([$this, 'getSelectorArg'], $args);
     6193
     6194        return $this->formatOutputSelector($this->selectorAppend($selectors));
     6195    }
     6196
     6197    /**
     6198     * Append parts of the last selector in the list to the previous, recursively
     6199     *
     6200     * @param array $selectors
     6201     *
     6202     * @return array
     6203     *
     6204     * @throws \ScssPhp\ScssPhp\Exception\CompilerException
     6205     */
     6206    protected function selectorAppend($selectors)
     6207    {
     6208        $lastSelectors = array_pop($selectors);
     6209
     6210        if (! $lastSelectors) {
     6211            $this->throwError("Invalid selector list in selector-append()");
     6212        }
     6213
     6214        while (count($selectors)) {
     6215            $previousSelectors = array_pop($selectors);
     6216
     6217            if (! $previousSelectors) {
     6218                $this->throwError("Invalid selector list in selector-append()");
     6219            }
     6220
     6221            // do the trick, happening $lastSelector to $previousSelector
     6222            $appended = [];
     6223
     6224            foreach ($lastSelectors as $lastSelector) {
     6225                $previous = $previousSelectors;
     6226
     6227                foreach ($lastSelector as $lastSelectorParts) {
     6228                    foreach ($lastSelectorParts as $lastSelectorPart) {
     6229                        foreach ($previous as $i => $previousSelector) {
     6230                            foreach ($previousSelector as $j => $previousSelectorParts) {
     6231                                $previous[$i][$j][] = $lastSelectorPart;
     6232                            }
     6233                        }
     6234                    }
     6235                }
     6236
     6237                foreach ($previous as $ps) {
     6238                    $appended[] = $ps;
     6239                }
     6240            }
     6241
     6242            $lastSelectors = $appended;
     6243        }
     6244
     6245        return $lastSelectors;
     6246    }
     6247
     6248    protected static $libSelectorExtend = ['selectors', 'extendee', 'extender'];
     6249    protected function libSelectorExtend($args)
     6250    {
     6251        list($selectors, $extendee, $extender) = $args;
     6252
     6253        $selectors = $this->getSelectorArg($selectors);
     6254        $extendee = $this->getSelectorArg($extendee);
     6255        $extender = $this->getSelectorArg($extender);
     6256
     6257        if (! $selectors || ! $extendee || ! $extender) {
     6258            $this->throwError("selector-extend() invalid arguments");
     6259        }
     6260
     6261        $extended = $this->extendOrReplaceSelectors($selectors, $extendee, $extender);
     6262
     6263        return $this->formatOutputSelector($extended);
     6264    }
     6265
     6266    protected static $libSelectorReplace = ['selectors', 'original', 'replacement'];
     6267    protected function libSelectorReplace($args)
     6268    {
     6269        list($selectors, $original, $replacement) = $args;
     6270
     6271        $selectors = $this->getSelectorArg($selectors);
     6272        $original = $this->getSelectorArg($original);
     6273        $replacement = $this->getSelectorArg($replacement);
     6274
     6275        if (! $selectors || ! $original || ! $replacement) {
     6276            $this->throwError("selector-replace() invalid arguments");
     6277        }
     6278
     6279        $replaced = $this->extendOrReplaceSelectors($selectors, $original, $replacement, true);
     6280
     6281        return $this->formatOutputSelector($replaced);
     6282    }
     6283
     6284    /**
     6285     * Extend/replace in selectors
     6286     * used by selector-extend and selector-replace that use the same logic
     6287     *
     6288     * @param array   $selectors
     6289     * @param array   $extendee
     6290     * @param array   $extender
     6291     * @param boolean $replace
     6292     *
     6293     * @return array
     6294     */
     6295    protected function extendOrReplaceSelectors($selectors, $extendee, $extender, $replace = false)
     6296    {
     6297        $saveExtends = $this->extends;
     6298        $saveExtendsMap = $this->extendsMap;
     6299
     6300        $this->extends = [];
     6301        $this->extendsMap = [];
     6302
     6303        foreach ($extendee as $es) {
     6304            // only use the first one
     6305            $this->pushExtends(reset($es), $extender, null);
     6306        }
     6307
     6308        $extended = [];
     6309
     6310        foreach ($selectors as $selector) {
     6311            if (! $replace) {
     6312                $extended[] = $selector;
     6313            }
     6314
     6315            $n = count($extended);
     6316
     6317            $this->matchExtends($selector, $extended);
     6318
     6319            // if didnt match, keep the original selector if we are in a replace operation
     6320            if ($replace and count($extended) === $n) {
     6321                $extended[] = $selector;
     6322            }
     6323        }
     6324
     6325        $this->extends = $saveExtends;
     6326        $this->extendsMap = $saveExtendsMap;
     6327
     6328        return $extended;
     6329    }
     6330
     6331    //protected static $libSelectorNest = ['selector...'];
     6332    protected function libSelectorNest($args)
     6333    {
     6334        if (count($args) < 1) {
     6335            $this->throwError("selector-nest() needs at least 1 argument");
     6336        }
     6337
     6338        $selectorsMap = array_map([$this, 'getSelectorArg'], $args);
     6339
     6340        $envs = [];
     6341        foreach ($selectorsMap as $selectors) {
     6342            $env = new Environment();
     6343            $env->selectors = $selectors;
     6344
     6345            $envs[] = $env;
     6346        }
     6347
     6348        $envs = array_reverse($envs);
     6349        $env = $this->extractEnv($envs);
     6350        $outputSelectors = $this->multiplySelectors($env);
     6351
     6352        return $this->formatOutputSelector($outputSelectors);
     6353    }
     6354
     6355    protected static $libSelectorParse = ['selectors'];
     6356    protected function libSelectorParse($args)
     6357    {
     6358        $selectors = reset($args);
     6359        $selectors = $this->getSelectorArg($selectors);
     6360
     6361        return $this->formatOutputSelector($selectors);
     6362    }
     6363
     6364    protected static $libSelectorUnify = ['selectors1', 'selectors2'];
     6365    protected function libSelectorUnify($args)
     6366    {
     6367        list($selectors1, $selectors2) = $args;
     6368
     6369        $selectors1 = $this->getSelectorArg($selectors1);
     6370        $selectors2 = $this->getSelectorArg($selectors2);
     6371
     6372        if (! $selectors1 || ! $selectors2) {
     6373            $this->throwError("selector-unify() invalid arguments");
     6374        }
     6375
     6376        // only consider the first compound of each
     6377        $compound1 = reset($selectors1);
     6378        $compound2 = reset($selectors2);
     6379
     6380        // unify them and that's it
     6381        $unified = $this->unifyCompoundSelectors($compound1, $compound2);
     6382
     6383        return $this->formatOutputSelector($unified);
     6384    }
     6385
     6386    /**
     6387     * The selector-unify magic as its best
     6388     * (at least works as expected on test cases)
     6389     *
     6390     * @param array $compound1
     6391     * @param array $compound2
     6392     * @return array|mixed
     6393     */
     6394    protected function unifyCompoundSelectors($compound1, $compound2)
     6395    {
     6396        if (! count($compound1)) {
     6397            return $compound2;
     6398        }
     6399
     6400        if (! count($compound2)) {
     6401            return $compound1;
     6402        }
     6403
     6404        // check that last part are compatible
     6405        $lastPart1 = array_pop($compound1);
     6406        $lastPart2 = array_pop($compound2);
     6407        $last = $this->mergeParts($lastPart1, $lastPart2);
     6408
     6409        if (! $last) {
     6410            return [[]];
     6411        }
     6412
     6413        $unifiedCompound = [$last];
     6414        $unifiedSelectors = [$unifiedCompound];
     6415
     6416        // do the rest
     6417        while (count($compound1) || count($compound2)) {
     6418            $part1 = end($compound1);
     6419            $part2 = end($compound2);
     6420
     6421            if ($part1 && ($match2 = $this->matchPartInCompound($part1, $compound2))) {
     6422                list($compound2, $part2, $after2) = $match2;
     6423
     6424                if ($after2) {
     6425                    $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after2);
     6426                }
     6427
     6428                $c = $this->mergeParts($part1, $part2);
     6429                $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]);
     6430                $part1 = $part2 = null;
     6431
     6432                array_pop($compound1);
     6433            }
     6434
     6435            if ($part2 && ($match1 = $this->matchPartInCompound($part2, $compound1))) {
     6436                list($compound1, $part1, $after1) = $match1;
     6437
     6438                if ($after1) {
     6439                    $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after1);
     6440                }
     6441
     6442                $c = $this->mergeParts($part2, $part1);
     6443                $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]);
     6444                $part1 = $part2 = null;
     6445
     6446                array_pop($compound2);
     6447            }
     6448
     6449            $new = [];
     6450
     6451            if ($part1 && $part2) {
     6452                array_pop($compound1);
     6453                array_pop($compound2);
     6454
     6455                $s = $this->prependSelectors($unifiedSelectors, [$part2]);
     6456                $new = array_merge($new, $this->prependSelectors($s, [$part1]));
     6457                $s = $this->prependSelectors($unifiedSelectors, [$part1]);
     6458                $new = array_merge($new, $this->prependSelectors($s, [$part2]));
     6459            } elseif ($part1) {
     6460                array_pop($compound1);
     6461
     6462                $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part1]));
     6463            } elseif ($part2) {
     6464                array_pop($compound2);
     6465
     6466                $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part2]));
     6467            }
     6468
     6469            if ($new) {
     6470                $unifiedSelectors = $new;
     6471            }
     6472        }
     6473
     6474        return $unifiedSelectors;
     6475    }
     6476
     6477    /**
     6478     * Prepend each selector from $selectors with $parts
     6479     *
     6480     * @param array $selectors
     6481     * @param array $parts
     6482     *
     6483     * @return array
     6484     */
     6485    protected function prependSelectors($selectors, $parts)
     6486    {
     6487        $new = [];
     6488
     6489        foreach ($selectors as $compoundSelector) {
     6490            array_unshift($compoundSelector, $parts);
     6491
     6492            $new[] = $compoundSelector;
     6493        }
     6494
     6495        return $new;
     6496    }
     6497
     6498    /**
     6499     * Try to find a matching part in a compound:
     6500     * - with same html tag name
     6501     * - with some class or id or something in common
     6502     *
     6503     * @param array $part
     6504     * @param array $compound
     6505     *
     6506     * @return array|boolean
     6507     */
     6508    protected function matchPartInCompound($part, $compound)
     6509    {
     6510        $partTag = $this->findTagName($part);
     6511        $before = $compound;
     6512        $after = [];
     6513
     6514        // try to find a match by tag name first
     6515        while (count($before)) {
     6516            $p = array_pop($before);
     6517
     6518            if ($partTag && $partTag !== '*' && $partTag == $this->findTagName($p)) {
     6519                return [$before, $p, $after];
     6520            }
     6521
     6522            $after[] = $p;
     6523        }
     6524
     6525        // try again matching a non empty intersection and a compatible tagname
     6526        $before = $compound;
     6527        $after = [];
     6528
     6529        while (count($before)) {
     6530            $p = array_pop($before);
     6531
     6532            if ($this->checkCompatibleTags($partTag, $this->findTagName($p))) {
     6533                if (count(array_intersect($part, $p))) {
     6534                    return [$before, $p, $after];
     6535                }
     6536            }
     6537
     6538            $after[] = $p;
     6539        }
     6540
     6541        return false;
     6542    }
     6543
     6544    /**
     6545     * Merge two part list taking care that
     6546     * - the html tag is coming first - if any
     6547     * - the :something are coming last
     6548     *
     6549     * @param array $parts1
     6550     * @param array $parts2
     6551     *
     6552     * @return array
     6553     */
     6554    protected function mergeParts($parts1, $parts2)
     6555    {
     6556        $tag1 = $this->findTagName($parts1);
     6557        $tag2 = $this->findTagName($parts2);
     6558        $tag = $this->checkCompatibleTags($tag1, $tag2);
     6559
     6560        // not compatible tags
     6561        if ($tag === false) {
     6562            return [];
     6563        }
     6564
     6565        if ($tag) {
     6566            if ($tag1) {
     6567                $parts1 = array_diff($parts1, [$tag1]);
     6568            }
     6569
     6570            if ($tag2) {
     6571                $parts2 = array_diff($parts2, [$tag2]);
     6572            }
     6573        }
     6574
     6575        $mergedParts = array_merge($parts1, $parts2);
     6576        $mergedOrderedParts = [];
     6577
     6578        foreach ($mergedParts as $part) {
     6579            if (strpos($part, ':') === 0) {
     6580                $mergedOrderedParts[] = $part;
     6581            }
     6582        }
     6583
     6584        $mergedParts = array_diff($mergedParts, $mergedOrderedParts);
     6585        $mergedParts = array_merge($mergedParts, $mergedOrderedParts);
     6586
     6587        if ($tag) {
     6588            array_unshift($mergedParts, $tag);
     6589        }
     6590
     6591        return $mergedParts;
     6592    }
     6593
     6594    /**
     6595     * Check the compatibility between two tag names:
     6596     * if both are defined they should be identical or one has to be '*'
     6597     *
     6598     * @param string $tag1
     6599     * @param string $tag2
     6600     *
     6601     * @return array|boolean
     6602     */
     6603    protected function checkCompatibleTags($tag1, $tag2)
     6604    {
     6605        $tags = [$tag1, $tag2];
     6606        $tags = array_unique($tags);
     6607        $tags = array_filter($tags);
     6608
     6609        if (count($tags)>1) {
     6610            $tags = array_diff($tags, ['*']);
     6611        }
     6612
     6613        // not compatible nodes
     6614        if (count($tags)>1) {
     6615            return false;
     6616        }
     6617
     6618        return $tags;
     6619    }
     6620
     6621    /**
     6622     * Find the html tag name in a selector parts list
     6623     *
     6624     * @param array $parts
     6625     *
     6626     * @return mixed|string
     6627     */
     6628    protected function findTagName($parts)
     6629    {
     6630        foreach ($parts as $part) {
     6631            if (! preg_match('/^[\[.:#%_-]/', $part)) {
     6632                return $part;
     6633            }
     6634        }
     6635
     6636        return '';
     6637    }
     6638
     6639    protected static $libSimpleSelectors = ['selector'];
     6640    protected function libSimpleSelectors($args)
     6641    {
     6642        $selector = reset($args);
     6643        $selector = $this->getSelectorArg($selector);
     6644
     6645        // remove selectors list layer, keeping the first one
     6646        $selector = reset($selector);
     6647
     6648        // remove parts list layer, keeping the first part
     6649        $part = reset($selector);
     6650
     6651        $listParts = [];
     6652
     6653        foreach ($part as $p) {
     6654            $listParts[] = [Type::T_STRING, '', [$p]];
     6655        }
     6656
     6657        return [Type::T_LIST, ',', $listParts];
     6658    }
    59776659}
  • _plugins_/scssphp/trunk/lib/scssphp/src/Compiler/Environment.php

    r115043 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Compiler;
     12namespace ScssPhp\ScssPhp\Compiler;
    1313
    1414/**
     
    2020{
    2121    /**
    22      * @var \Leafo\ScssPhp\Block
     22     * @var \ScssPhp\ScssPhp\Block
    2323     */
    2424    public $block;
    2525
    2626    /**
    27      * @var \Leafo\ScssPhp\Compiler\Environment
     27     * @var \ScssPhp\ScssPhp\Compiler\Environment
    2828     */
    2929    public $parent;
  • _plugins_/scssphp/trunk/lib/scssphp/src/Exception/CompilerException.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Exception;
     12namespace ScssPhp\ScssPhp\Exception;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Exception/ParserException.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Exception;
     12namespace ScssPhp\ScssPhp\Exception;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Exception/RangeException.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Exception;
     12namespace ScssPhp\ScssPhp\Exception;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Exception/ServerException.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Exception;
     12namespace ScssPhp\ScssPhp\Exception;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter.php

    r115044 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
    13 
    14 use Leafo\ScssPhp\Formatter\OutputBlock;
    15 use Leafo\ScssPhp\SourceMap\SourceMapGenerator;
     12namespace ScssPhp\ScssPhp;
     13
     14use ScssPhp\ScssPhp\Formatter\OutputBlock;
     15use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
    1616
    1717/**
     
    6363
    6464    /**
    65      * @var \Leafo\ScssPhp\Formatter\OutputBlock
     65     * @var \ScssPhp\ScssPhp\Formatter\OutputBlock
    6666     */
    6767    protected $currentBlock;
     
    7878
    7979    /**
    80      * @var \Leafo\ScssPhp\SourceMap\SourceMapGenerator
     80     * @var \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator
    8181     */
    8282    protected $sourceMapGenerator;
     
    137137     * Output lines inside a block
    138138     *
    139      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     139     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    140140     */
    141141    protected function blockLines(OutputBlock $block)
     
    155155     * Output block selectors
    156156     *
    157      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     157     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    158158     */
    159159    protected function blockSelectors(OutputBlock $block)
     
    169169     * Output block children
    170170     *
    171      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     171     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    172172     */
    173173    protected function blockChildren(OutputBlock $block)
     
    181181     * Output non-empty block
    182182     *
    183      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     183     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    184184     */
    185185    protected function block(OutputBlock $block)
     
    223223     * @api
    224224     *
    225      * @param \Leafo\ScssPhp\Formatter\OutputBlock             $block              An abstract syntax tree
    226      * @param \Leafo\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator
     225     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock             $block              An abstract syntax tree
     226     * @param \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator
    227227     *
    228228     * @return string
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/Compact.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
     12namespace ScssPhp\ScssPhp\Formatter;
    1313
    14 use Leafo\ScssPhp\Formatter;
     14use ScssPhp\ScssPhp\Formatter;
    1515
    1616/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/Compressed.php

    r115410 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
     12namespace ScssPhp\ScssPhp\Formatter;
    1313
    14 use Leafo\ScssPhp\Formatter;
    15 use Leafo\ScssPhp\Formatter\OutputBlock;
     14use ScssPhp\ScssPhp\Formatter;
     15use ScssPhp\ScssPhp\Formatter\OutputBlock;
    1616
    1717/**
     
    6464     * Output block selectors
    6565     *
    66      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     66     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    6767     */
    6868    protected function blockSelectors(OutputBlock $block)
     
    7070        $inner = $this->indentStr();
    7171
    72         $this->write($inner
    73             . implode($this->tagSeparator, str_replace(array(' > ', ' + ', ' ~ '), array('>', '+', '~'), $block->selectors))
    74             . $this->open . $this->break);
     72        $this->write(
     73            $inner
     74            . implode(
     75                $this->tagSeparator,
     76                str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors)
     77            )
     78            . $this->open . $this->break
     79        );
    7580    }
    7681}
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/Crunched.php

    r115410 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
     12namespace ScssPhp\ScssPhp\Formatter;
    1313
    14 use Leafo\ScssPhp\Formatter;
    15 use Leafo\ScssPhp\Formatter\OutputBlock;
     14use ScssPhp\ScssPhp\Formatter;
     15use ScssPhp\ScssPhp\Formatter\OutputBlock;
    1616
    1717/**
     
    6262     * Output block selectors
    6363     *
    64      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     64     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    6565     */
    6666    protected function blockSelectors(OutputBlock $block)
     
    6868        $inner = $this->indentStr();
    6969
    70         $this->write($inner
    71             . implode($this->tagSeparator, str_replace(array(' > ', ' + ', ' ~ '), array('>', '+', '~'), $block->selectors))
    72             . $this->open . $this->break);
     70        $this->write(
     71            $inner
     72            . implode(
     73                $this->tagSeparator,
     74                str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors)
     75            )
     76            . $this->open . $this->break
     77        );
    7378    }
    7479}
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/Debug.php

    r115044 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
     12namespace ScssPhp\ScssPhp\Formatter;
    1313
    14 use Leafo\ScssPhp\Formatter;
    15 use Leafo\ScssPhp\Formatter\OutputBlock;
     14use ScssPhp\ScssPhp\Formatter;
     15use ScssPhp\ScssPhp\Formatter\OutputBlock;
    1616
    1717/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/Expanded.php

    r115044 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
     12namespace ScssPhp\ScssPhp\Formatter;
    1313
    14 use Leafo\ScssPhp\Formatter;
    15 use Leafo\ScssPhp\Formatter\OutputBlock;
     14use ScssPhp\ScssPhp\Formatter;
     15use ScssPhp\ScssPhp\Formatter\OutputBlock;
    1616
    1717/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/Nested.php

    r115044 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
    13 
    14 use Leafo\ScssPhp\Formatter;
    15 use Leafo\ScssPhp\Formatter\OutputBlock;
     12namespace ScssPhp\ScssPhp\Formatter;
     13
     14use ScssPhp\ScssPhp\Formatter;
     15use ScssPhp\ScssPhp\Formatter\OutputBlock;
    1616
    1717/**
     
    154154     * Adjust the depths of all children, depth first
    155155     *
    156      * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
     156     * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
    157157     */
    158158    private function adjustAllChildren(OutputBlock $block)
  • _plugins_/scssphp/trunk/lib/scssphp/src/Formatter/OutputBlock.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Formatter;
     12namespace ScssPhp\ScssPhp\Formatter;
    1313
    1414/**
     
    4545
    4646    /**
    47      * @var \Leafo\ScssPhp\Formatter\OutputBlock
     47     * @var \ScssPhp\ScssPhp\Formatter\OutputBlock
    4848     */
    4949    public $parent;
  • _plugins_/scssphp/trunk/lib/scssphp/src/Node.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Node/Number.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\Node;
    13 
    14 use Leafo\ScssPhp\Compiler;
    15 use Leafo\ScssPhp\Node;
    16 use Leafo\ScssPhp\Type;
     12namespace ScssPhp\ScssPhp\Node;
     13
     14use ScssPhp\ScssPhp\Compiler;
     15use ScssPhp\ScssPhp\Node;
     16use ScssPhp\ScssPhp\Type;
    1717
    1818/**
     
    101101     * @param array $units
    102102     *
    103      * @return \Leafo\ScssPhp\Node\Number
     103     * @return \ScssPhp\ScssPhp\Node\Number
    104104     */
    105105    public function coerce($units)
     
    124124     * Normalize number
    125125     *
    126      * @return \Leafo\ScssPhp\Node\Number
     126     * @return \ScssPhp\ScssPhp\Node\Number
    127127     */
    128128    public function normalize()
     
    260260     * Output number
    261261     *
    262      * @param \Leafo\ScssPhp\Compiler $compiler
     262     * @param \ScssPhp\ScssPhp\Compiler $compiler
    263263     *
    264264     * @return string
  • _plugins_/scssphp/trunk/lib/scssphp/src/Parser.php

    r115410 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
    13 
    14 use Leafo\ScssPhp\Block;
    15 use Leafo\ScssPhp\Compiler;
    16 use Leafo\ScssPhp\Exception\ParserException;
    17 use Leafo\ScssPhp\Node;
    18 use Leafo\ScssPhp\Type;
     12namespace ScssPhp\ScssPhp;
     13
     14use ScssPhp\ScssPhp\Block;
     15use ScssPhp\ScssPhp\Cache;
     16use ScssPhp\ScssPhp\Compiler;
     17use ScssPhp\ScssPhp\Exception\ParserException;
     18use ScssPhp\ScssPhp\Node;
     19use ScssPhp\ScssPhp\Type;
    1920
    2021/**
     
    7576     * @api
    7677     *
    77      * @param string  $sourceName
    78      * @param integer $sourceIndex
    79      * @param string  $encoding
    80      * @param Cache $cache
     78     * @param string                 $sourceName
     79     * @param integer                $sourceIndex
     80     * @param string                 $encoding
     81     * @param \ScssPhp\ScssPhp\Cache $cache
    8182     */
    8283    public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', $cache = null)
     
    8788        $this->utf8             = ! $encoding || strtolower($encoding) === 'utf-8';
    8889        $this->patternModifiers = $this->utf8 ? 'Aisu' : 'Ais';
    89         $this->commentsSeen   = [];
     90        $this->commentsSeen     = [];
    9091
    9192        if (empty(static::$operatorPattern)) {
     
    126127     * @param string $msg
    127128     *
    128      * @throws \Leafo\ScssPhp\Exception\ParserException
     129     * @throws \ScssPhp\ScssPhp\Exception\ParserException
    129130     */
    130131    public function throwParseError($msg = 'parse error')
    131132    {
    132         list($line, /* $column */) = $this->getSourcePosition($this->count);
    133 
    134         $loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
     133        list($line, $column) = $this->getSourcePosition($this->count);
     134
     135        $loc = empty($this->sourceName)
     136             ? "line: $line, column: $column"
     137             : "$this->sourceName on line $line, at column $column";
    135138
    136139        if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
     
    148151     * @param string $buffer
    149152     *
    150      * @return \Leafo\ScssPhp\Block
     153     * @return \ScssPhp\ScssPhp\Block
    151154     */
    152155    public function parse($buffer)
    153156    {
    154 
    155157        if ($this->cache) {
    156             $cache_key = $this->sourceName . ":" . md5($buffer);
    157             $parse_options = array(
     158            $cacheKey = $this->sourceName . ":" . md5($buffer);
     159            $parseOptions = [
    158160                'charset' => $this->charset,
    159161                'utf8' => $this->utf8,
    160             );
    161             $v = $this->cache->getCache("parse", $cache_key, $parse_options);
    162             if (!is_null($v)) {
     162            ];
     163            $v = $this->cache->getCache("parse", $cacheKey, $parseOptions);
     164
     165            if (! is_null($v)) {
    163166                return $v;
    164167            }
     
    200203        }
    201204
    202         $this->env->isRoot    = true;
    203 
    204205        $this->restoreEncoding();
    205206
    206207        if ($this->cache) {
    207             $this->cache->setCache("parse", $cache_key, $this->env, $parse_options);
     208            $this->cache->setCache("parse", $cacheKey, $this->env, $parseOptions);
    208209        }
    209210
     
    662663
    663664        // opening css block
    664         if ($this->selectors($selectors) && $this->matchChar('{')) {
     665        if ($this->selectors($selectors) && $this->matchChar('{', false)) {
    665666            $this->pushBlock($selectors, $s);
     667
     668            if ($this->eatWhiteDefault) {
     669                $this->whitespace();
     670                $this->append(null); // collect comments at the begining if needed
     671            }
    666672
    667673            return true;
     
    675681
    676682            if ($this->valueList($value)) {
     683                if (empty($this->env->parent)) {
     684                    $this->throwParseError('expected "{"');
     685                }
     686
    677687                $this->append([Type::T_ASSIGN, $name, $value], $s);
    678688                $foundSomething = true;
     
    727737     * @param integer $pos
    728738     *
    729      * @return \Leafo\ScssPhp\Block
     739     * @return \ScssPhp\ScssPhp\Block
    730740     */
    731741    protected function pushBlock($selectors, $pos = 0)
     
    764774     * @param integer $pos
    765775     *
    766      * @return \Leafo\ScssPhp\Block
     776     * @return \ScssPhp\ScssPhp\Block
    767777     */
    768778    protected function pushSpecialBlock($type, $pos)
     
    777787     * Pop scope and return last block
    778788     *
    779      * @return \Leafo\ScssPhp\Block
     789     * @return \ScssPhp\ScssPhp\Block
    780790     *
    781791     * @throws \Exception
     
    933943            $this->whitespace();
    934944        }
     945
    935946        return true;
    936947    }
     
    947958    protected function literal($what, $len, $eatWhitespace = null)
    948959    {
    949 
    950960        if (strcasecmp(substr($this->buffer, $this->count, $len), $what) !== 0) {
    951961            return false;
     
    961971            $this->whitespace();
    962972        }
     973
    963974        return true;
    964975    }
     
    975986        while (preg_match(static::$whitePattern, $this->buffer, $m, null, $this->count)) {
    976987            if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
    977                 $this->appendComment([Type::T_COMMENT, $m[1]]);
     988                // comment that are kept in the output CSS
     989                $comment = [];
     990                $endCommentCount = $this->count + strlen($m[1]);
     991
     992                // find interpolations in comment
     993                $p = strpos($this->buffer, '#{', $this->count);
     994
     995                while ($p !== false && $p < $endCommentCount) {
     996                    $c = substr($this->buffer, $this->count, $p - $this->count);
     997                    $comment[] = $c;
     998                    $this->count = $p;
     999                    $out = null;
     1000
     1001                    if ($this->interpolation($out)) {
     1002                        // keep right spaces in the following string part
     1003                        if ($out[3]) {
     1004                            while ($this->buffer[$this->count-1] !== '}') {
     1005                                $this->count--;
     1006                            }
     1007
     1008                            $out[3] = '';
     1009                        }
     1010
     1011                        $comment[] = $out;
     1012                    } else {
     1013                        $comment[] = substr($this->buffer, $this->count, 2);
     1014
     1015                        $this->count += 2;
     1016                    }
     1017
     1018                    $p = strpos($this->buffer, '#{', $this->count);
     1019                }
     1020
     1021                // remaining part
     1022                $c = substr($this->buffer, $this->count, $endCommentCount - $this->count);
     1023
     1024                if (! $comment) {
     1025                    // single part static comment
     1026                    $this->appendComment([Type::T_COMMENT, $c]);
     1027                } else {
     1028                    $comment[] = $c;
     1029                    $this->appendComment([Type::T_COMMENT, [Type::T_STRING, '', $comment]]);
     1030                }
    9781031
    9791032                $this->commentsSeen[$this->count] = true;
    980             }
    981 
    982             $this->count += strlen($m[0]);
     1033                $this->count = $endCommentCount;
     1034            } else {
     1035                // comment that are ignored and not kept in the output css
     1036                $this->count += strlen($m[0]);
     1037            }
     1038
    9831039            $gotWhite = true;
    9841040        }
     
    9941050    protected function appendComment($comment)
    9951051    {
    996         $comment[1] = substr(preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], $comment[1]), 1);
     1052        if ($comment[0] === Type::T_COMMENT && is_string($comment[1])) {
     1053            $comment[1] = substr(preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], $comment[1]), 1);
     1054        }
    9971055
    9981056        $this->env->comments[] = $comment;
     
    10071065    protected function append($statement, $pos = null)
    10081066    {
    1009         if ($pos !== null) {
    1010             list($line, $column) = $this->getSourcePosition($pos);
    1011 
    1012             $statement[static::SOURCE_LINE]   = $line;
    1013             $statement[static::SOURCE_COLUMN] = $column;
    1014             $statement[static::SOURCE_INDEX]  = $this->sourceIndex;
    1015         }
    1016 
    1017         $this->env->children[] = $statement;
     1067        if (! is_null($statement)) {
     1068            if ($pos !== null) {
     1069                list($line, $column) = $this->getSourcePosition($pos);
     1070
     1071                $statement[static::SOURCE_LINE]   = $line;
     1072                $statement[static::SOURCE_COLUMN] = $column;
     1073                $statement[static::SOURCE_INDEX]  = $this->sourceIndex;
     1074            }
     1075
     1076            $this->env->children[] = $statement;
     1077        }
    10181078
    10191079        $comments = $this->env->comments;
     
    12361296        }
    12371297
    1238         if (!$items) {
     1298        if (! $items) {
    12391299            $this->seek($s);
    12401300
     
    12711331
    12721332        if ($this->matchChar('[')) {
    1273             if ($this->parenExpression($out, $s, "]")) {
     1333            if ($this->parenExpression($out, $s, "]", [Type::T_LIST, Type::T_KEYWORD])) {
     1334                if ($out[0] !== Type::T_LIST && $out[0] !== Type::T_MAP) {
     1335                    $out = [Type::T_STRING, '', [ '[', $out, ']' ]];
     1336                }
     1337
    12741338                return true;
    12751339            }
     
    12931357     * @param integer $s
    12941358     * @param string  $closingParen
    1295      *
    1296      * @return boolean
    1297      */
    1298     protected function parenExpression(&$out, $s, $closingParen = ")")
     1359     * @param array   $allowedTypes
     1360     *
     1361     * @return boolean
     1362     */
     1363    protected function parenExpression(&$out, $s, $closingParen = ")", $allowedTypes = [Type::T_LIST, Type::T_MAP])
    12991364    {
    13001365        if ($this->matchChar($closingParen)) {
     
    13041369        }
    13051370
    1306         if ($this->valueList($out) && $this->matchChar($closingParen) && $out[0] === Type::T_LIST) {
     1371        if ($this->valueList($out) && $this->matchChar($closingParen) && in_array($out[0], $allowedTypes)) {
    13071372            return true;
    13081373        }
     
    13101375        $this->seek($s);
    13111376
    1312         if ($this->map($out)) {
     1377        if (in_array(Type::T_MAP, $allowedTypes) && $this->map($out)) {
    13131378            return true;
    13141379        }
     
    13851450
    13861451        if ($this->literal('url(', 4) && $this->match('data:([a-z]+)\/([a-z0-9.+-]+);base64,', $m, false)) {
    1387             $len = strspn($this->buffer, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/=', $this->count);
     1452            $len = strspn(
     1453                $this->buffer,
     1454                'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/=',
     1455                $this->count
     1456            );
    13881457
    13891458            $this->count += $len;
     
    13911460            if ($this->matchChar(')')) {
    13921461                $content = substr($this->buffer, $s, $this->count - $s);
     1462                $out = [Type::T_KEYWORD, $content];
     1463
     1464                return true;
     1465            }
     1466        }
     1467
     1468        $this->seek($s);
     1469
     1470        if ($this->literal('url(', 4, false) && $this->match('\s*(\/\/\S+)\s*', $m)) {
     1471            $content = 'url(' . $m[1];
     1472
     1473            if ($this->matchChar(')')) {
     1474                $content .= ')';
    13931475                $out = [Type::T_KEYWORD, $content];
    13941476
     
    14241506            if ($this->value($inner)) {
    14251507                $out = [Type::T_UNARY, '+', $inner, $this->inParens];
     1508
    14261509                return true;
    14271510            }
     
    14381521            if ($this->variable($inner) || $this->unit($inner) || $this->parenValue($inner)) {
    14391522                $out = [Type::T_UNARY, '-', $inner, $this->inParens];
    1440                 return true;
    1441             }
     1523
     1524                return true;
     1525            }
     1526
    14421527            $this->count--;
    14431528        }
     
    14561541        if ($this->matchChar('&', true)) {
    14571542            $out = [Type::T_SELF];
     1543
    14581544            return true;
    14591545        }
     
    14721558
    14731559        if ($this->unit($out)) {
     1560            return true;
     1561        }
     1562
     1563        // unicode range with wildcards
     1564        if ($this->literal('U+', 2) && $this->match('([0-9A-F]+\?*)(-([0-9A-F]+))?', $m, false)) {
     1565            $out = [Type::T_KEYWORD, 'U+' . $m[0]];
    14741566            return true;
    14751567        }
     
    16431735        }
    16441736
    1645         if (! $this->matchChar(')') || !$args) {
     1737        if (! $this->matchChar(')') || ! $args) {
    16461738            $this->seek($s);
    16471739
     
    17411833        }
    17421834
    1743         if (!$keys || ! $this->matchChar(')')) {
     1835        if (! $keys || ! $this->matchChar(')')) {
    17441836            $this->seek($s);
    17451837
     
    17791871                        $num >>= 4;
    17801872                    }
     1873
    17811874                    break;
    17821875
     
    17891882                        $num >>= 8;
    17901883                    }
     1884
    17911885                    break;
    17921886
     
    18851979                } elseif ($this->literal("\\", 1, false)) {
    18861980                    $content[] = $m[2] . "\\";
     1981                } elseif ($this->literal("\r\n", 2, false)
     1982                  || $this->matchChar("\r", false)
     1983                  || $this->matchChar("\n", false)
     1984                  || $this->matchChar("\f", false)) {
     1985                    // this is a continuation escaping, to be ignored
    18871986                } else {
    18881987                    $content[] = $m[2];
     
    19512050        $this->eatWhiteDefault = $oldWhite;
    19522051
    1953         if (!$parts) {
     2052        if (! $parts) {
    19542053            return false;
    19552054        }
     
    20172116        $this->eatWhiteDefault = $oldWhite;
    20182117
    2019         if (!$content) {
     2118        if (! $content) {
    20202119            return false;
    20212120        }
     
    20592158                $out = [Type::T_INTERPOLATE, $value, $left, $right];
    20602159            }
     2160
    20612161            $this->eatWhiteDefault = $oldWhite;
    20622162
     
    21002200            }
    21012201
    2102             if (!$parts && $this->match('[:.#]', $m, false)) {
     2202            if (! $parts && $this->match('[:.#]', $m, false)) {
    21032203                // css hacks
    21042204                $parts[] = $m[0];
     
    21112211        $this->eatWhiteDefault = $oldWhite;
    21122212
    2113         if (!$parts) {
     2213        if (! $parts) {
    21142214            return false;
    21152215        }
     
    21432243     * @return boolean
    21442244     */
    2145     protected function selectors(&$out)
     2245    protected function selectors(&$out, $subSelector = false)
    21462246    {
    21472247        $s = $this->count;
    21482248        $selectors = [];
    21492249
    2150         while ($this->selector($sel)) {
     2250        while ($this->selector($sel, $subSelector)) {
    21512251            $selectors[] = $sel;
    21522252
    2153             if (! $this->matchChar(',')) {
     2253            if (! $this->matchChar(',', true)) {
    21542254                break;
    21552255            }
    21562256
    2157             while ($this->matchChar(',')) {
     2257            while ($this->matchChar(',', true)) {
    21582258                ; // ignore extra
    21592259            }
    21602260        }
    21612261
    2162         if (!$selectors) {
     2262        if (! $selectors) {
    21632263            $this->seek($s);
    21642264
     
    21782278     * @return boolean
    21792279     */
    2180     protected function selector(&$out)
     2280    protected function selector(&$out, $subSelector = false)
    21812281    {
    21822282        $selector = [];
    21832283
    21842284        for (;;) {
    2185             if ($this->match('[>+~]+', $m)) {
     2285            if ($this->match('[>+~]+', $m, true)) {
    21862286                $selector[] = [$m[0]];
    21872287                continue;
    21882288            }
    21892289
    2190             if ($this->selectorSingle($part)) {
     2290            if ($this->selectorSingle($part, $subSelector)) {
    21912291                $selector[] = $part;
    21922292                $this->match('\s+', $m);
     
    21942294            }
    21952295
    2196             if ($this->match('\/[^\/]+\/', $m)) {
     2296            if ($this->match('\/[^\/]+\/', $m, true)) {
    21972297                $selector[] = [$m[0]];
    21982298                continue;
     
    22022302        }
    22032303
    2204         if (!$selector) {
     2304        if (! $selector) {
    22052305            return false;
    22062306        }
    22072307
    22082308        $out = $selector;
     2309
    22092310        return true;
    22102311    }
     
    22212322     * @return boolean
    22222323     */
    2223     protected function selectorSingle(&$out)
     2324    protected function selectorSingle(&$out, $subSelector = false)
    22242325    {
    22252326        $oldWhite = $this->eatWhiteDefault;
     
    22422343            // see if we can stop early
    22432344            if ($char === '{' || $char === ',' || $char === ';' || $char === '}' || $char === '@') {
     2345                break;
     2346            }
     2347
     2348            // parsing a sub selector in () stop with the closing )
     2349            if ($subSelector && $char === ')') {
    22442350                break;
    22452351            }
     
    22512357                    $this->count++;
    22522358                    continue 2;
     2359
    22532360                case '.':
    22542361                    $parts[] = '.';
    22552362                    $this->count++;
    22562363                    continue 2;
     2364
    22572365                case '|':
    22582366                    $parts[] = '|';
     
    23082416                    $ss = $this->count;
    23092417
    2310                     if ($this->matchChar('(') &&
    2311                       ($this->openString(')', $str, '(') || true) &&
    2312                       $this->matchChar(')')
     2418                    if ($nameParts === ['not'] || $nameParts === ['is'] ||
     2419                        $nameParts === ['has'] || $nameParts === ['where']
    23132420                    ) {
    2314                         $parts[] = '(';
    2315 
    2316                         if (! empty($str)) {
    2317                             $parts[] = $str;
     2421                        if ($this->matchChar('(') &&
     2422                          ($this->selectors($subs, true) || true) &&
     2423                          $this->matchChar(')')
     2424                        ) {
     2425                            $parts[] = '(';
     2426
     2427                            while ($sub = array_shift($subs)) {
     2428                                while ($ps = array_shift($sub)) {
     2429                                    foreach ($ps as &$p) {
     2430                                        $parts[] = $p;
     2431                                    }
     2432                                    if (count($sub) && reset($sub)) {
     2433                                        $parts[] = ' ';
     2434                                    }
     2435                                }
     2436                                if (count($subs) && reset($subs)) {
     2437                                    $parts[] = ', ';
     2438                                }
     2439                            }
     2440
     2441                            $parts[] = ')';
     2442                        } else {
     2443                            $this->seek($ss);
    23182444                        }
    2319 
    2320                         $parts[] = ')';
    23212445                    } else {
    2322                         $this->seek($ss);
     2446                        if ($this->matchChar('(') &&
     2447                          ($this->openString(')', $str, '(') || true) &&
     2448                          $this->matchChar(')')
     2449                        ) {
     2450                            $parts[] = '(';
     2451
     2452                            if (! empty($str)) {
     2453                                $parts[] = $str;
     2454                            }
     2455
     2456                            $parts[] = ')';
     2457                        } else {
     2458                            $this->seek($ss);
     2459                        }
    23232460                    }
    23242461
     
    23312468            // attribute selector
    23322469            if ($char === '[' &&
    2333               $this->matchChar('[') &&
    2334               ($this->openString(']', $str, '[') || true) &&
    2335               $this->matchChar(']')
     2470                $this->matchChar('[') &&
     2471                ($this->openString(']', $str, '[') || true) &&
     2472                $this->matchChar(']')
    23362473            ) {
    23372474                $parts[] = '[';
     
    23422479
    23432480                $parts[] = ']';
    2344 
    23452481                continue;
    23462482            }
     
    23642500        $this->eatWhiteDefault = $oldWhite;
    23652501
    2366         if (!$parts) {
     2502        if (! $parts) {
    23672503            return false;
    23682504        }
     
    24072543        if ($this->match(
    24082544            $this->utf8
    2409                 ? '(([\pL\w_\-\*!"\']|[\\\\].)([\pL\w\-_"\']|[\\\\].)*)'
     2545                ? '(([\pL\w\x{00A0}-\x{10FFFF}_\-\*!"\']|[\\\\].)([\pL\w\x{00A0}-\x{10FFFF}\-_"\']|[\\\\].)*)'
    24102546                : '(([\w_\-\*!"\']|[\\\\].)([\w\-_"\']|[\\\\].)*)',
    24112547            $m,
  • _plugins_/scssphp/trunk/lib/scssphp/src/SourceMap/Base64.php

    r115043 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2015 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\SourceMap;
     12namespace ScssPhp\ScssPhp\SourceMap;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/SourceMap/Base64VLQ.php

    r115044 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2015 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\SourceMap;
     12namespace ScssPhp\ScssPhp\SourceMap;
    1313
    14 use Leafo\ScssPhp\SourceMap\Base64;
     14use ScssPhp\ScssPhp\SourceMap\Base64;
    1515
    1616/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/SourceMap/Base64VLQEncoder.php

    r115043 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\SourceMap;
     12namespace ScssPhp\ScssPhp\SourceMap;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/SourceMap/SourceMapGenerator.php

    r115301 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp\SourceMap;
    13 
    14 use Leafo\ScssPhp\Exception\CompilerException;
     12namespace ScssPhp\ScssPhp\SourceMap;
     13
     14use ScssPhp\ScssPhp\Exception\CompilerException;
    1515
    1616/**
     
    6262     * The base64 VLQ encoder
    6363     *
    64      * @var \Leafo\ScssPhp\SourceMap\Base64VLQ
     64     * @var \ScssPhp\ScssPhp\SourceMap\Base64VLQ
    6565     */
    6666    protected $encoder;
     
    128128     * @return string
    129129     *
    130      * @throws \Leafo\ScssPhp\Exception\CompilerException If the file could not be saved
     130     * @throws \ScssPhp\ScssPhp\Exception\CompilerException If the file could not be saved
    131131     */
    132132    public function saveMap($content)
     
    138138        if (! is_dir($dir)) {
    139139            // FIXME: create the dir automatically?
    140             throw new CompilerException(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir));
     140            throw new CompilerException(
     141                sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir)
     142            );
    141143        }
    142144
  • _plugins_/scssphp/trunk/lib/scssphp/src/Type.php

    r108871 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    1414/**
  • _plugins_/scssphp/trunk/lib/scssphp/src/Util.php

    r115043 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    14 use Leafo\ScssPhp\Base\Range;
    15 use Leafo\ScssPhp\Exception\RangeException;
     14use ScssPhp\ScssPhp\Base\Range;
     15use ScssPhp\ScssPhp\Exception\RangeException;
    1616
    1717/**
     
    2727     *
    2828     * @param string                    $name  The name of the value. Used in the error message.
    29      * @param \Leafo\ScssPhp\Base\Range $range Range of values.
     29     * @param \ScssPhp\ScssPhp\Base\Range $range Range of values.
    3030     * @param array                     $value The value to check.
    3131     * @param string                    $unit  The unit of the value. Used in error reporting.
     
    3333     * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin.
    3434     *
    35      * @throws \Leafo\ScssPhp\Exception\RangeException
     35     * @throws \ScssPhp\ScssPhp\Exception\RangeException
    3636     */
    3737    public static function checkRange($name, Range $range, $value, $unit = '')
  • _plugins_/scssphp/trunk/lib/scssphp/src/Version.php

    r115301 r115547  
    33 * SCSSPHP
    44 *
    5  * @copyright 2012-2018 Leaf Corcoran
     5 * @copyright 2012-2019 Leaf Corcoran
    66 *
    77 * @license http://opensource.org/licenses/MIT MIT
    88 *
    9  * @link http://leafo.github.io/scssphp
     9 * @link http://scssphp.github.io/scssphp
    1010 */
    1111
    12 namespace Leafo\ScssPhp;
     12namespace ScssPhp\ScssPhp;
    1313
    1414/**
     
    1919class Version
    2020{
    21     const VERSION = 'v0.8.2.1';
     21    const VERSION = 'v1.0.0';
    2222}
  • _plugins_/scssphp/trunk/paquet.xml

    r115410 r115547  
    22        prefix="scssphp"
    33        categorie="outil"
    4         version="2.0.1"
     4        version="2.1.0"
    55        etat="stable"
    66        compatibilite="[3.1.0;3.2.*]"
     
    1212        <auteur lien="http://elastick.net">Anne-lise Martenot, elastick.net</auteur>
    1313        <credit>Jean-Baptiste Bourgoin</credit>
    14         <credit lien="http://leafo.github.io/scssphp/">leafo/scssphp</credit>
     14        <credit lien="https://github.com/scssphp/scssphp">scssphp/scssphp</credit>
    1515
    1616        <licence lien="http://www.gnu.org/licenses/gpl-3.0.html">GPL 3</licence>
     
    2222        <pipeline nom="formulaire_admin" />
    2323
    24         <procure nom="scssphp" version="0.8.2.1" />
     24        <procure nom="scssphp" version="1.0.0" />
    2525
    2626        <necessite nom="php" compatibilite="[5.6.0;[" />
  • _plugins_/scssphp/trunk/scssphp_fonctions.php

    r115258 r115547  
    55 *
    66 */
    7 use Leafo\ScssPhp\Compiler;
     7use ScssPhp\ScssPhp\Compiler;
    88
    99if (!defined('_ECRIRE_INC_VERSION')) {
     
    4949        }
    5050
    51         // le compilateur Leafo\ScssPhp\Compiler compile le contenu
     51        // le compilateur ScssPhp\ScssPhp\Compiler compile le contenu
    5252        $scss = new Compiler($cache_options);
    53         $scss->setFormatter("Leafo\ScssPhp\Formatter\Expanded");
     53        $scss->setFormatter("ScssPhp\ScssPhp\Formatter\Expanded");
    5454
    5555        // lui transmettre le path qu'il utilise pour les @import
Note: See TracChangeset for help on using the changeset viewer.